├── README.md ├── lines.sh ├── pics ├── agile │ ├── kanban.jpg │ └── scrum.jpg ├── ai │ ├── ai_chain_of_thought.png │ └── ai_control_flow.png ├── architecture │ ├── architecture_c4model_maps.jpg │ ├── architecture_c4model_scope.jpg │ └── architecture_web_101.png ├── arduino_led.jpg ├── binary │ └── binary_calculator.jpg ├── blockchain │ └── blockchain_bitcoin_transaction.jpg ├── breadboard.png ├── comics │ ├── automation.png │ ├── dependency.png │ ├── dependency_2.jpg │ ├── interruption_1.png │ ├── interruption_2.png │ ├── is_it_worth_the_time.png │ ├── password_strength.png │ └── standards.png ├── css │ ├── css_area_desktop.jpg │ ├── css_area_mobile.jpg │ └── css_grid.jpg ├── database │ ├── database_1nf.jpg │ ├── database_2nf.jpg │ ├── database_3nf.jpg │ ├── database_denormalization.jpg │ ├── database_many_to_many_1.jpg │ ├── database_many_to_many_2.jpg │ ├── database_normalization.jpg │ ├── database_one_to_many_1.jpg │ ├── database_one_to_many_2.jpg │ ├── database_one_to_one_1.jpg │ ├── database_one_to_one_2.jpg │ └── database_sql_execution_order.jpg ├── electronics │ ├── khan_current.jpg │ └── khan_voltage.jpg ├── elm │ ├── TEA.png │ └── elm_arch.png ├── express │ └── express_middleware.jpg ├── git │ ├── git_feature1.png │ ├── git_feature2.jpg │ ├── git_trunk1a.png │ ├── git_trunk1b.png │ ├── git_trunk2.jpg │ └── git_workflow.jpg ├── github_commits.jpg ├── graphTheory │ ├── graphTheory_graphs.jpg │ ├── graphTheory_traversal.jpg │ ├── graphTheory_traversal_breadth.jpg │ └── graphTheory_traversal_depth.jpg ├── inherit.jpg ├── js_event_loop.png ├── mobile │ ├── mobile_appTypes.jpg │ ├── mobile_comparison1.jpg │ ├── mobile_comparison2.jpg │ ├── mobile_comparison3.jpg │ ├── mobile_comparison4.jpg │ ├── mobile_compiledApps.jpg │ └── mobile_pwa.jpg ├── mvc_full_stack.jpg ├── networking │ ├── OSI-7-layers.jpg │ ├── OSI-vs.-TCPIP-models.jpg │ ├── OSI.png │ ├── TCPIP.jpg │ ├── data_flow.jpg │ ├── ddns.jpg │ ├── dns.jpg │ └── http.jpg ├── react │ └── react_components.jpg ├── rfid_wiegand_arduino.jpg ├── sql │ └── pivot_unpivot.png ├── startup │ ├── business │ │ ├── business_startup_top100YC.jpg │ │ └── startup_motivation_pyramid_of_clarity.png │ ├── market_fit │ │ ├── market_fit_startup_curve.jpg │ │ └── market_fit_startup_stages.jpg │ ├── marketing │ │ ├── advertising_creative_order.jpg │ │ ├── advertising_long_form_founder_ad.jpg │ │ ├── advertising_stealth_ad.jpg │ │ ├── advertising_value_formula.jpg │ │ ├── advertising_value_formula_ad_example.jpg │ │ ├── advertising_value_formula_example.jpg │ │ ├── analytics-account.jpg │ │ ├── copywriting_framework_4cs.webp │ │ ├── copywriting_framework_aida.webp │ │ ├── copywriting_framework_bab.webp │ │ ├── copywriting_framework_fab.webp │ │ ├── copywriting_framework_pas.webp │ │ ├── copywriting_framework_pppp.webp │ │ ├── copywriting_framework_slap.webp │ │ ├── copywriting_framework_so-what.webp │ │ ├── copywriting_framework_sss.webp │ │ ├── langing-page-action-plan-example.jpg │ │ ├── langing-page-action-plan.jpg │ │ ├── langing-page-benefits-example.jpg │ │ ├── langing-page-benefits.jpg │ │ ├── langing-page-cta.jpg │ │ ├── langing-page-faq.jpg │ │ ├── langing-page-hero-example.jpg │ │ ├── langing-page-navigation.jpg │ │ ├── langing-page-problem-example.jpg │ │ ├── langing-page-problem.jpg │ │ ├── langing-page-solution-example.jpg │ │ ├── langing-page-solution.jpg │ │ ├── langing-page-testimonials.jpg │ │ ├── tag-manager_account.jpg │ │ └── tag-manager_tags.jpg │ ├── mvp │ │ ├── mvp.jpg │ │ ├── mvp_airbnb.jpg │ │ ├── mvp_stripe.jpg │ │ └── mvp_twitch.jpg │ ├── pricing │ │ ├── pricing_billion_formula.jpg │ │ ├── pricing_optimization.jpg │ │ ├── pricing_quadrants.jpg │ │ ├── pricing_rule.jpg │ │ ├── pricing_sales_stages.jpg │ │ └── pricing_thermometer.jpg │ ├── product_design │ │ ├── object_model.jpg │ │ └── responsibilities.jpg │ └── sales │ │ ├── email_example.jpg │ │ ├── email_open_hour.jpg │ │ ├── email_response_hour.jpg │ │ ├── linkedin_about.jpg │ │ ├── linkedin_banner.jpg │ │ ├── linkedin_connection.jpg │ │ ├── linkedin_custom-button.jpg │ │ ├── linkedin_experience.jpg │ │ ├── linkedin_fatures.jpg │ │ ├── linkedin_headline.jpg │ │ ├── linkedin_recommendation.jpg │ │ ├── sales_conversations_phone.jpg │ │ ├── sales_conversions.jpg │ │ ├── sales_cycle.jpg │ │ ├── sales_expectations.jpg │ │ ├── sales_follow_up.jpg │ │ ├── sales_map.jpg │ │ ├── sales_marketing-buyer-journey.jpg │ │ ├── sales_process.jpg │ │ ├── sales_reality.jpg │ │ └── sales_time_spent.jpg ├── svelte │ ├── svelte_degit.jpg │ └── svelte_vite.jpg ├── uiux │ └── uiux_fonts.jpg └── vim │ └── vim_graphical_cheat_sheet.jpg └── topics ├── agile.md ├── ai ├── apiChatGPT.md ├── concepts.md ├── embeddings.md ├── langchain.md ├── mcp.md └── prompting.md ├── ansible.md ├── assembly.md ├── babel.md ├── binary ├── ascii.md ├── binary.md └── bitwise.md ├── blockchain.md ├── caching.md ├── cryptojs.md ├── css.md ├── cybersecurity ├── cors.md ├── csrf.md ├── cybersecurity.md ├── jwt.md ├── sqlinjection.md └── xss.md ├── database ├── conventions.md ├── mysql.md ├── node-mssql.md ├── node-mysql.md ├── normalization.md ├── optimizationDiagnostics.md ├── optimizationEngine.md ├── optimizationHardware.md ├── optimizationIndexing.md ├── optimizationQuerying.md ├── queriesAdmin.md ├── queriesAggregate.md ├── queriesCRUD.md ├── queriesLogic.md ├── queriesPivot.md ├── queriesSchema.md ├── queriesUtilities.md ├── queriesVarious.md ├── queriesWindow.md ├── sqlserver.md └── terminology.md ├── docker.md ├── dotenv.md ├── dotnet.md ├── electron.md ├── electronics ├── arduino.md ├── electricity.md ├── electronics.md ├── nodemcu.md ├── raspberrypi.md └── rfid.md ├── elm.md ├── excel.md ├── express-structure.md ├── express.md ├── ftp.md ├── git.md ├── googleapi.md ├── googling.md ├── graphql.md ├── javascript ├── async.md ├── basics.md ├── debugging.md ├── dom.md ├── es6.md └── language.md ├── libraries-frontend.md ├── linux ├── bash.md ├── cron.md ├── ffmpeg.md ├── filesystem.md ├── fzf.md ├── grep.md ├── gzip.md ├── linux.md ├── rsync.md ├── services.md ├── ssh.md ├── terminal.md ├── terminology.md ├── tmux.md ├── users.md └── vim.md ├── logging.md ├── messageBrokers.md ├── microservices.md ├── middleware.md ├── mobile.md ├── mobileAndroid.md ├── mobileCapacitor.md ├── mobileCordova.md ├── mobilePWA.md ├── mobileiOS.md ├── multiTenancy.md ├── mvc.md ├── networkingDevices.md ├── networkingLayer2LinkMAC.md ├── networkingLayer3NetworkIP.md ├── networkingLayer4TransferTCP.md ├── networkingLayer5ApplicationHTTP.md ├── networkingModelOSI.md ├── networkingModelTCPIP.md ├── networkingOverview.md ├── networkingRoles.md ├── networkingTools.md ├── node.md ├── nodemailer.md ├── notifications.md ├── npm.md ├── optimization ├── algorithms.md ├── codeGolf.md ├── comments.md ├── dependencyInjection.md ├── graphs.md ├── naming.md ├── nesting.md └── premature.md ├── pdfmake.md ├── puppeteer.md ├── react.md ├── reddit.md ├── restful.md ├── serverless.md ├── sheetjs.md ├── startup ├── copywritingAdCreatives.md ├── copywritingBestPractices.md ├── copywritingDirectResponse.md ├── copywritingFrameworks.md ├── marketingAdvertising.md ├── marketingFacebookPixel.md ├── marketingGoogleAnalytics.md ├── marketingGoogleTagManager.md ├── marketingLandingPage.md ├── marketingSeo.md ├── productBusinessModel.md ├── productDesign.md ├── productMVP.md ├── productMarketFit.md ├── salesColdCalling.md ├── salesEmail.md ├── salesEnterprise.md ├── salesLinkedin.md ├── salesMeetings.md ├── salesObjections.md ├── salesOverview.md ├── salesPricing.md ├── startupEquity.md ├── startupFocus.md ├── startupIdeas.md ├── startupMotivation.md └── startupProblemSolving.md ├── statistics.md ├── styles ├── fp.md └── oop.md ├── svelte.md ├── tabulator.md ├── tagify.md ├── testing ├── jest.md ├── mocha.md └── testing.md ├── uiux.md ├── vagrant.md ├── vm.md ├── vscode.md ├── vue.md ├── wasm.md ├── webComponents.md ├── webpack.md ├── webserver ├── nginx.md └── ssl.md ├── websockets.md └── workflow ├── deployment.md ├── development.md └── environment.md /lines.sh: -------------------------------------------------------------------------------- 1 | find src topics -name '*.md' | xargs wc -l -------------------------------------------------------------------------------- /pics/agile/kanban.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/agile/kanban.jpg -------------------------------------------------------------------------------- /pics/agile/scrum.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/agile/scrum.jpg -------------------------------------------------------------------------------- /pics/ai/ai_chain_of_thought.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/ai/ai_chain_of_thought.png -------------------------------------------------------------------------------- /pics/ai/ai_control_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/ai/ai_control_flow.png -------------------------------------------------------------------------------- /pics/architecture/architecture_c4model_maps.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/architecture/architecture_c4model_maps.jpg -------------------------------------------------------------------------------- /pics/architecture/architecture_c4model_scope.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/architecture/architecture_c4model_scope.jpg -------------------------------------------------------------------------------- /pics/architecture/architecture_web_101.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/architecture/architecture_web_101.png -------------------------------------------------------------------------------- /pics/arduino_led.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/arduino_led.jpg -------------------------------------------------------------------------------- /pics/binary/binary_calculator.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/binary/binary_calculator.jpg -------------------------------------------------------------------------------- /pics/blockchain/blockchain_bitcoin_transaction.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/blockchain/blockchain_bitcoin_transaction.jpg -------------------------------------------------------------------------------- /pics/breadboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/breadboard.png -------------------------------------------------------------------------------- /pics/comics/automation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/comics/automation.png -------------------------------------------------------------------------------- /pics/comics/dependency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/comics/dependency.png -------------------------------------------------------------------------------- /pics/comics/dependency_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/comics/dependency_2.jpg -------------------------------------------------------------------------------- /pics/comics/interruption_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/comics/interruption_1.png -------------------------------------------------------------------------------- /pics/comics/interruption_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/comics/interruption_2.png -------------------------------------------------------------------------------- /pics/comics/is_it_worth_the_time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/comics/is_it_worth_the_time.png -------------------------------------------------------------------------------- /pics/comics/password_strength.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/comics/password_strength.png -------------------------------------------------------------------------------- /pics/comics/standards.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/comics/standards.png -------------------------------------------------------------------------------- /pics/css/css_area_desktop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/css/css_area_desktop.jpg -------------------------------------------------------------------------------- /pics/css/css_area_mobile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/css/css_area_mobile.jpg -------------------------------------------------------------------------------- /pics/css/css_grid.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/css/css_grid.jpg -------------------------------------------------------------------------------- /pics/database/database_1nf.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/database/database_1nf.jpg -------------------------------------------------------------------------------- /pics/database/database_2nf.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/database/database_2nf.jpg -------------------------------------------------------------------------------- /pics/database/database_3nf.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/database/database_3nf.jpg -------------------------------------------------------------------------------- /pics/database/database_denormalization.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/database/database_denormalization.jpg -------------------------------------------------------------------------------- /pics/database/database_many_to_many_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/database/database_many_to_many_1.jpg -------------------------------------------------------------------------------- /pics/database/database_many_to_many_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/database/database_many_to_many_2.jpg -------------------------------------------------------------------------------- /pics/database/database_normalization.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/database/database_normalization.jpg -------------------------------------------------------------------------------- /pics/database/database_one_to_many_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/database/database_one_to_many_1.jpg -------------------------------------------------------------------------------- /pics/database/database_one_to_many_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/database/database_one_to_many_2.jpg -------------------------------------------------------------------------------- /pics/database/database_one_to_one_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/database/database_one_to_one_1.jpg -------------------------------------------------------------------------------- /pics/database/database_one_to_one_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/database/database_one_to_one_2.jpg -------------------------------------------------------------------------------- /pics/database/database_sql_execution_order.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/database/database_sql_execution_order.jpg -------------------------------------------------------------------------------- /pics/electronics/khan_current.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/electronics/khan_current.jpg -------------------------------------------------------------------------------- /pics/electronics/khan_voltage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/electronics/khan_voltage.jpg -------------------------------------------------------------------------------- /pics/elm/TEA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/elm/TEA.png -------------------------------------------------------------------------------- /pics/elm/elm_arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/elm/elm_arch.png -------------------------------------------------------------------------------- /pics/express/express_middleware.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/express/express_middleware.jpg -------------------------------------------------------------------------------- /pics/git/git_feature1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/git/git_feature1.png -------------------------------------------------------------------------------- /pics/git/git_feature2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/git/git_feature2.jpg -------------------------------------------------------------------------------- /pics/git/git_trunk1a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/git/git_trunk1a.png -------------------------------------------------------------------------------- /pics/git/git_trunk1b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/git/git_trunk1b.png -------------------------------------------------------------------------------- /pics/git/git_trunk2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/git/git_trunk2.jpg -------------------------------------------------------------------------------- /pics/git/git_workflow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/git/git_workflow.jpg -------------------------------------------------------------------------------- /pics/github_commits.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/github_commits.jpg -------------------------------------------------------------------------------- /pics/graphTheory/graphTheory_graphs.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/graphTheory/graphTheory_graphs.jpg -------------------------------------------------------------------------------- /pics/graphTheory/graphTheory_traversal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/graphTheory/graphTheory_traversal.jpg -------------------------------------------------------------------------------- /pics/graphTheory/graphTheory_traversal_breadth.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/graphTheory/graphTheory_traversal_breadth.jpg -------------------------------------------------------------------------------- /pics/graphTheory/graphTheory_traversal_depth.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/graphTheory/graphTheory_traversal_depth.jpg -------------------------------------------------------------------------------- /pics/inherit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/inherit.jpg -------------------------------------------------------------------------------- /pics/js_event_loop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/js_event_loop.png -------------------------------------------------------------------------------- /pics/mobile/mobile_appTypes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/mobile/mobile_appTypes.jpg -------------------------------------------------------------------------------- /pics/mobile/mobile_comparison1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/mobile/mobile_comparison1.jpg -------------------------------------------------------------------------------- /pics/mobile/mobile_comparison2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/mobile/mobile_comparison2.jpg -------------------------------------------------------------------------------- /pics/mobile/mobile_comparison3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/mobile/mobile_comparison3.jpg -------------------------------------------------------------------------------- /pics/mobile/mobile_comparison4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/mobile/mobile_comparison4.jpg -------------------------------------------------------------------------------- /pics/mobile/mobile_compiledApps.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/mobile/mobile_compiledApps.jpg -------------------------------------------------------------------------------- /pics/mobile/mobile_pwa.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/mobile/mobile_pwa.jpg -------------------------------------------------------------------------------- /pics/mvc_full_stack.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/mvc_full_stack.jpg -------------------------------------------------------------------------------- /pics/networking/OSI-7-layers.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/networking/OSI-7-layers.jpg -------------------------------------------------------------------------------- /pics/networking/OSI-vs.-TCPIP-models.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/networking/OSI-vs.-TCPIP-models.jpg -------------------------------------------------------------------------------- /pics/networking/OSI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/networking/OSI.png -------------------------------------------------------------------------------- /pics/networking/TCPIP.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/networking/TCPIP.jpg -------------------------------------------------------------------------------- /pics/networking/data_flow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/networking/data_flow.jpg -------------------------------------------------------------------------------- /pics/networking/ddns.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/networking/ddns.jpg -------------------------------------------------------------------------------- /pics/networking/dns.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/networking/dns.jpg -------------------------------------------------------------------------------- /pics/networking/http.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/networking/http.jpg -------------------------------------------------------------------------------- /pics/react/react_components.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/react/react_components.jpg -------------------------------------------------------------------------------- /pics/rfid_wiegand_arduino.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/rfid_wiegand_arduino.jpg -------------------------------------------------------------------------------- /pics/sql/pivot_unpivot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/sql/pivot_unpivot.png -------------------------------------------------------------------------------- /pics/startup/business/business_startup_top100YC.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/business/business_startup_top100YC.jpg -------------------------------------------------------------------------------- /pics/startup/business/startup_motivation_pyramid_of_clarity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/business/startup_motivation_pyramid_of_clarity.png -------------------------------------------------------------------------------- /pics/startup/market_fit/market_fit_startup_curve.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/market_fit/market_fit_startup_curve.jpg -------------------------------------------------------------------------------- /pics/startup/market_fit/market_fit_startup_stages.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/market_fit/market_fit_startup_stages.jpg -------------------------------------------------------------------------------- /pics/startup/marketing/advertising_creative_order.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/advertising_creative_order.jpg -------------------------------------------------------------------------------- /pics/startup/marketing/advertising_long_form_founder_ad.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/advertising_long_form_founder_ad.jpg -------------------------------------------------------------------------------- /pics/startup/marketing/advertising_stealth_ad.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/advertising_stealth_ad.jpg -------------------------------------------------------------------------------- /pics/startup/marketing/advertising_value_formula.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/advertising_value_formula.jpg -------------------------------------------------------------------------------- /pics/startup/marketing/advertising_value_formula_ad_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/advertising_value_formula_ad_example.jpg -------------------------------------------------------------------------------- /pics/startup/marketing/advertising_value_formula_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/advertising_value_formula_example.jpg -------------------------------------------------------------------------------- /pics/startup/marketing/analytics-account.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/analytics-account.jpg -------------------------------------------------------------------------------- /pics/startup/marketing/copywriting_framework_4cs.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/copywriting_framework_4cs.webp -------------------------------------------------------------------------------- /pics/startup/marketing/copywriting_framework_aida.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/copywriting_framework_aida.webp -------------------------------------------------------------------------------- /pics/startup/marketing/copywriting_framework_bab.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/copywriting_framework_bab.webp -------------------------------------------------------------------------------- /pics/startup/marketing/copywriting_framework_fab.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/copywriting_framework_fab.webp -------------------------------------------------------------------------------- /pics/startup/marketing/copywriting_framework_pas.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/copywriting_framework_pas.webp -------------------------------------------------------------------------------- /pics/startup/marketing/copywriting_framework_pppp.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/copywriting_framework_pppp.webp -------------------------------------------------------------------------------- /pics/startup/marketing/copywriting_framework_slap.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/copywriting_framework_slap.webp -------------------------------------------------------------------------------- /pics/startup/marketing/copywriting_framework_so-what.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/copywriting_framework_so-what.webp -------------------------------------------------------------------------------- /pics/startup/marketing/copywriting_framework_sss.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/copywriting_framework_sss.webp -------------------------------------------------------------------------------- /pics/startup/marketing/langing-page-action-plan-example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/langing-page-action-plan-example.jpg -------------------------------------------------------------------------------- /pics/startup/marketing/langing-page-action-plan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/langing-page-action-plan.jpg -------------------------------------------------------------------------------- /pics/startup/marketing/langing-page-benefits-example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/langing-page-benefits-example.jpg -------------------------------------------------------------------------------- /pics/startup/marketing/langing-page-benefits.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/langing-page-benefits.jpg -------------------------------------------------------------------------------- /pics/startup/marketing/langing-page-cta.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/langing-page-cta.jpg -------------------------------------------------------------------------------- /pics/startup/marketing/langing-page-faq.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/langing-page-faq.jpg -------------------------------------------------------------------------------- /pics/startup/marketing/langing-page-hero-example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/langing-page-hero-example.jpg -------------------------------------------------------------------------------- /pics/startup/marketing/langing-page-navigation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/langing-page-navigation.jpg -------------------------------------------------------------------------------- /pics/startup/marketing/langing-page-problem-example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/langing-page-problem-example.jpg -------------------------------------------------------------------------------- /pics/startup/marketing/langing-page-problem.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/langing-page-problem.jpg -------------------------------------------------------------------------------- /pics/startup/marketing/langing-page-solution-example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/langing-page-solution-example.jpg -------------------------------------------------------------------------------- /pics/startup/marketing/langing-page-solution.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/langing-page-solution.jpg -------------------------------------------------------------------------------- /pics/startup/marketing/langing-page-testimonials.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/langing-page-testimonials.jpg -------------------------------------------------------------------------------- /pics/startup/marketing/tag-manager_account.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/tag-manager_account.jpg -------------------------------------------------------------------------------- /pics/startup/marketing/tag-manager_tags.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/marketing/tag-manager_tags.jpg -------------------------------------------------------------------------------- /pics/startup/mvp/mvp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/mvp/mvp.jpg -------------------------------------------------------------------------------- /pics/startup/mvp/mvp_airbnb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/mvp/mvp_airbnb.jpg -------------------------------------------------------------------------------- /pics/startup/mvp/mvp_stripe.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/mvp/mvp_stripe.jpg -------------------------------------------------------------------------------- /pics/startup/mvp/mvp_twitch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/mvp/mvp_twitch.jpg -------------------------------------------------------------------------------- /pics/startup/pricing/pricing_billion_formula.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/pricing/pricing_billion_formula.jpg -------------------------------------------------------------------------------- /pics/startup/pricing/pricing_optimization.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/pricing/pricing_optimization.jpg -------------------------------------------------------------------------------- /pics/startup/pricing/pricing_quadrants.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/pricing/pricing_quadrants.jpg -------------------------------------------------------------------------------- /pics/startup/pricing/pricing_rule.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/pricing/pricing_rule.jpg -------------------------------------------------------------------------------- /pics/startup/pricing/pricing_sales_stages.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/pricing/pricing_sales_stages.jpg -------------------------------------------------------------------------------- /pics/startup/pricing/pricing_thermometer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/pricing/pricing_thermometer.jpg -------------------------------------------------------------------------------- /pics/startup/product_design/object_model.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/product_design/object_model.jpg -------------------------------------------------------------------------------- /pics/startup/product_design/responsibilities.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/product_design/responsibilities.jpg -------------------------------------------------------------------------------- /pics/startup/sales/email_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/sales/email_example.jpg -------------------------------------------------------------------------------- /pics/startup/sales/email_open_hour.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/sales/email_open_hour.jpg -------------------------------------------------------------------------------- /pics/startup/sales/email_response_hour.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/sales/email_response_hour.jpg -------------------------------------------------------------------------------- /pics/startup/sales/linkedin_about.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/sales/linkedin_about.jpg -------------------------------------------------------------------------------- /pics/startup/sales/linkedin_banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/sales/linkedin_banner.jpg -------------------------------------------------------------------------------- /pics/startup/sales/linkedin_connection.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/sales/linkedin_connection.jpg -------------------------------------------------------------------------------- /pics/startup/sales/linkedin_custom-button.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/sales/linkedin_custom-button.jpg -------------------------------------------------------------------------------- /pics/startup/sales/linkedin_experience.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/sales/linkedin_experience.jpg -------------------------------------------------------------------------------- /pics/startup/sales/linkedin_fatures.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/sales/linkedin_fatures.jpg -------------------------------------------------------------------------------- /pics/startup/sales/linkedin_headline.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/sales/linkedin_headline.jpg -------------------------------------------------------------------------------- /pics/startup/sales/linkedin_recommendation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/sales/linkedin_recommendation.jpg -------------------------------------------------------------------------------- /pics/startup/sales/sales_conversations_phone.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/sales/sales_conversations_phone.jpg -------------------------------------------------------------------------------- /pics/startup/sales/sales_conversions.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/sales/sales_conversions.jpg -------------------------------------------------------------------------------- /pics/startup/sales/sales_cycle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/sales/sales_cycle.jpg -------------------------------------------------------------------------------- /pics/startup/sales/sales_expectations.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/sales/sales_expectations.jpg -------------------------------------------------------------------------------- /pics/startup/sales/sales_follow_up.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/sales/sales_follow_up.jpg -------------------------------------------------------------------------------- /pics/startup/sales/sales_map.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/sales/sales_map.jpg -------------------------------------------------------------------------------- /pics/startup/sales/sales_marketing-buyer-journey.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/sales/sales_marketing-buyer-journey.jpg -------------------------------------------------------------------------------- /pics/startup/sales/sales_process.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/sales/sales_process.jpg -------------------------------------------------------------------------------- /pics/startup/sales/sales_reality.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/sales/sales_reality.jpg -------------------------------------------------------------------------------- /pics/startup/sales/sales_time_spent.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/startup/sales/sales_time_spent.jpg -------------------------------------------------------------------------------- /pics/svelte/svelte_degit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/svelte/svelte_degit.jpg -------------------------------------------------------------------------------- /pics/svelte/svelte_vite.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/svelte/svelte_vite.jpg -------------------------------------------------------------------------------- /pics/uiux/uiux_fonts.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/uiux/uiux_fonts.jpg -------------------------------------------------------------------------------- /pics/vim/vim_graphical_cheat_sheet.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/pics/vim/vim_graphical_cheat_sheet.jpg -------------------------------------------------------------------------------- /topics/ai/apiChatGPT.md: -------------------------------------------------------------------------------- 1 | # GPT 4 2 | 3 | ```js 4 | const { Configuration, OpenAIApi } = require("openai"); 5 | 6 | const { apiKey } = require("./config"); 7 | 8 | const configuration = new Configuration({ 9 | apiKey: apiKey, 10 | }); 11 | 12 | const openai = new OpenAIApi(configuration); 13 | 14 | async function run() { 15 | const response = await openai.createChatCompletion({ 16 | model: "gpt-4", 17 | messages: [ 18 | { role: "system", content: "You are a helpful assistant." }, 19 | { role: "user", content: "Who won the world series in 2020?" }, 20 | { role: "assistant", content: "The Los Angeles Dodgers." }, 21 | ], 22 | max_tokens: 2000, 23 | n: 1, 24 | stop: null, 25 | temperature: 0, 26 | }); 27 | 28 | console.log(response.data.choices[0].message.content); 29 | } 30 | 31 | run(); 32 | ``` 33 | 34 | # GPT 3 35 | 36 | ```js 37 | const { Configuration, OpenAIApi } = require("openai"); 38 | 39 | const { organization, apiKey } = require("./config"); 40 | 41 | const configuration = new Configuration({ 42 | organization: organization, 43 | apiKey: apiKey, 44 | }); 45 | 46 | const openai = new OpenAIApi(configuration); 47 | 48 | async function run() { 49 | const completion = await openai.createCompletion({ 50 | model: "text-davinci-003", 51 | prompt: "Who won the world series in 2020?", 52 | max_tokens: 3000, 53 | temperature: 0, 54 | }); 55 | 56 | console.log(completion.data.choices[0].text); 57 | } 58 | 59 | run(); 60 | ``` 61 | 62 | # Notes 63 | 64 | Remember that the model predicts which text is most likely to follow the text preceding it. 65 | 66 | As a rough rule of thumb, 1 token is approximately 4 characters or 0.75 words for English text. 67 | 68 | temperature = randomness. Smaller = less random. Lowering temperature means it will take fewer risks, and completions will be more accurate and deterministic. Increasing temperature will result in more diverse completions. 69 | 70 | In the context of OpenAI's Chat API, the role and content parameters work together to define the conversation history. 71 | 72 | role: This parameter is used to specify the role of a message sender in the conversation. 73 | It can take one of three values: 'system', 'user', or 'assistant'. 74 | 75 | 'system': This role is typically used for instructions that set the behavior of the assistant. It often begins the conversation. 76 | 'user': This role is typically for the end user or human in the conversation. 77 | 'assistant': This role is for the AI model or assistant's responses. 78 | 79 | content: This parameter holds the actual text of the message from the role. 80 | For example, for the 'user' role, the content would be what the user said or asked. 81 | For the 'assistant', it would be the assistant's response. 82 | 83 | In the array of messages you provided: 84 | 85 | ``` 86 | messages: [ 87 | { role: "system", content: "You are a helpful assistant." }, 88 | { role: "user", content: "Who won the world series in 2020?" }, 89 | { role: "assistant", content: "The Los Angeles Dodgers." }, 90 | { role: "user", content: "Where was it played?" }, 91 | ] 92 | ``` 93 | 94 | The 'system' role is telling the assistant that its role is to be helpful. Then the 'user' asks a question about who won the World Series in 2020, the 'assistant' provides the answer, and then the 'user' asks another question. These messages together represent the conversation history. When a new message is added to the conversation history and a chat completion is created, the AI model will generate a response in the context of this history. 95 | -------------------------------------------------------------------------------- /topics/ai/concepts.md: -------------------------------------------------------------------------------- 1 | Forward propagation = Prediction 2 | Back propagation = Measuring i.e. learning 3 | 4 | # IDE 5 | 6 | jupyter - Online IDE 7 | 8 | # Datasets 9 | 10 | kaggle - datasets 11 | 12 | # Frameworks 13 | 14 | Wrappers to simplify using AI models to do tasks. Basically write and orchestrate prompts indirectly. 15 | 16 | OpenAI API is quite easy to use directly and gives you the most control, I don’t see much benefit of a wrapper langChain here tbh. 17 | 18 | Example: Langchain, Haystack, Microsoft Guidance 19 | 20 | # autoGPT 21 | 22 | An agent talking to itself. A recursive LLM. 23 | 24 | It’s a thinking AI basically, Chat GPT is just LLM. A LLM is like a baby without understanding, but using tools like Langchain and Pinecone you can teach the AI task. Auto GPT on has a few task, it’s really like a template to build your own thinking AI. 25 | 26 | Research Langchain and Pinecone to get a better understanding of the potential. 27 | 28 | # Agent 29 | 30 | An LLM with a predefined behavior, a personality. 31 | 32 | The word agent is being thrown around a lot to refer to an application that can execute multiple tasks according to a given control flow (see Control flows section). A task can leverage one or more tools. In the example above, SQL executor is an example of a tool. 33 | 34 | In broad terms, with the Agent model, the LLM becomes an orchestrator, taking a question, decomposing it into chunks, then using appropriate tools to pull together an answer. 35 | 36 | # Tools / Plugins 37 | 38 | Ways in which the agent can choose to do things ex. search the web, query a database. 39 | 40 | Tools and plugins are basically the same things. 41 | 42 | Ex. 43 | 44 | - search (e.g. by using Google Search API or Bing API) 45 | - web browser (e.g. given a URL, fetch its content) 46 | - bash executor 47 | - calculator 48 | 49 | # Transformer 50 | 51 | A transformer is a type of neural network, which have numbers as inputs. Both the input and output words need to be turned into numbers. 52 | 53 | There are many ways to do the conversion, with the most common being word embedding. 54 | 55 | # LLM 56 | 57 | LLMs (Large language models) are text completion engines 58 | 59 | Examples: gpt-3.5, gpt-4, hugginface, llama 60 | 61 | # Custom AI 62 | 63 | 2 ways to do this: 64 | 65 | 1. Finetune LLM (Behave a certain way ex. talk like Trump) - Re-train the model. More complex, saves cost. 66 | 2. Knowledge base. (Gain domain knowledge) - Create embeddings and store them in a vector database, which is the searched for and fed into an LLM prompt. 67 | -------------------------------------------------------------------------------- /topics/ai/embeddings.md: -------------------------------------------------------------------------------- 1 | One direction that I find very promising is to use LLMs to generate embeddings and then build your ML applications on top of these embeddings, e.g. for search and recsys. As of April 2023, the cost for embeddings using the smaller model text-embedding-ada-002 is $0.0004/1k tokens. If each item averages 250 tokens (187 words), this pricing means $1 for every 10k items or $100 for 1 million items. 2 | 3 | # Embeddings 4 | 5 | Embeddings are a numerical representation of text that can be used to measure the relatedness between two pieces of text. 6 | 7 | Turn data into a vector with hundreds of dimensions. 8 | 9 | Data, like words, converted into an array of numbers, known as a vector, which contains pattern of relationship between the data. 10 | 11 | Open AI ada = 8,191 tokens i.e. 32,764 characters ~ 10 pages of text. 12 | 13 | # Vector databases 14 | 15 | > What pieces of text in the database have similar vectors to the prompt. 16 | 17 | A vector database indexes and stores vector embeddings for fast retrieval and similarity search. It compares how close embeddings are. 18 | 19 | It turns the user's question into a vector, which is compared to the vectors in the database. 20 | 21 | Ex. Pinecone, Qdrant, Weaviate, Chroma, Faiss, Redis, Milvus, ScaNN. 22 | -------------------------------------------------------------------------------- /topics/ai/mcp.md: -------------------------------------------------------------------------------- 1 | # Model Context Protocol (MCP) 2 | 3 | A new standard for building APIs. 4 | 5 | Other standards include REST, RPC, SOAP and GraphQL. 6 | 7 | MCP is an API that calls other APIs. 8 | 9 | The clients sends a prompt, and MPC figures out which API to call next. 10 | 11 | To actually use MCP, you need a client that supports the MCP protocol, like Claude Desktop. 12 | -------------------------------------------------------------------------------- /topics/ansible.md: -------------------------------------------------------------------------------- 1 | # Ansible 2 | 3 | What should the server look like vs How to make it that way. 4 | 5 | We configure the state of a server, rather than the installation process with scripts, or god forbid manual installation by typing each command. 6 | 7 | More importantly, it offers built-in monitoring and alerting after deployment, instead of configuring our own for each machine. Ex. Which servers are running which version? 8 | 9 | The configuration scripts serve as documentation compared to reading cryptic bash scripts. 10 | 11 | Ansible is a **declarative** system. Instead of saying **Install something**, we say **I want something to be installed** i.e. if it's already isntalled, do nothing... Otherwise install it. 12 | 13 | Ansible commands are idempotent, meaning they always result in the same, no matter how many times they run. 14 | 15 | Ansible does not require anything to run on the remote servers, aside from SSH access with private/public RSA keys. 16 | 17 | Ansible uses the `jinja2` templating engine to inject variables with `{{variable}}`. 18 | 19 | ## Things needed 20 | 21 | #### Inventory 22 | 23 | A list of machines to do things on. Can be a simple text file. 24 | 25 | ```ansible 26 | server1.company.com 27 | server2.company.com 28 | ``` 29 | 30 | Machines can be grouped by using `[group]`. Machines can belong to several groups. 31 | 32 | ```ansible 33 | [database] 34 | db1.company.com 35 | db2.company.com 36 | ``` 37 | ## Commands 38 | 39 | `ansible database -i invetory -m ping` - Run the ping module (-m) on all the machines in the database group, located in the inventory (-i) list. 40 | 41 | `ansible database -i inventory -m apt -a "name=mysql-server state=present"` - If mysql is not installed, install it on all machines missing it in the database group. 42 | 43 | ## Playbook 44 | 45 | Instead of running commands one by one, we can define a playbook(.yml) with all the commands in one place. 46 | 47 | Each task should have a name, so that it's printed in the output as it runs, as well as serve as documentation. 48 | 49 | ```yml 50 | -- 51 | - hosts: all 52 | tasks: 53 | - name: Update package list 54 | apt: update_cache=yes cache_valid_time=36000 # last 10 hours. 55 | 56 | - hosts: database 57 | tasks: 58 | - name: Install MySQL 59 | apt: name=mysql-server state=present 60 | - name: Copy fixtures 61 | template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf 62 | ``` 63 | 64 | `ansible-playbook -i inventory playbook.yml` - Run the playbook. 65 | 66 | #### Variables 67 | 68 | To prevent repetition, we can define variables and inject them where needed. 69 | 70 | ```yml 71 | -- 72 | - hosts: database 73 | vars: 74 | fixture_name: fixtures.sql # Variable 75 | tasks: 76 | - name: Install MySQL 77 | apt: name=mysql-server state=present 78 | - name: Copy fixtures 79 | copy: src={{fixture_name}} dest=/tmp/{{fixture_name}} 80 | ``` 81 | 82 | #### Loops 83 | 84 | ```yml 85 | -- 86 | - hosts: all 87 | tasks: 88 | - name: Install packages 89 | apt: name={{item}} state=present 90 | with_items: # Loop 91 | - python 92 | - python-pip 93 | - vim 94 | ``` 95 | 96 | #### Loops with Variables 97 | 98 | ```yml 99 | -- 100 | - hosts: all 101 | vars: 102 | packages: # Variable 103 | - python 104 | - python-pip 105 | - vim 106 | tasks: 107 | - name: Install packages 108 | apt: name={{item}} state=present 109 | with_items: packages # Variable 110 | ``` 111 | 112 | ## File Organization Convention 113 | -------------------------------------------------------------------------------- /topics/assembly.md: -------------------------------------------------------------------------------- 1 | Assembly language is still taught for specific platforms like ARM and x86/64. You can do a lot of interesting close-to-hardware operations with assembly for embedded code, but most high level code bases like business logic code don't really use it directly. An assembler is generally always involved for higher level coding languages that compile down to machine code (e.g. C++/C, Go), because a compiler generally converts high level code to machine specific assembly before an assembler converts it to the final machine code. Something that says "ADD(Register_6, Register_13)" is much better to a human than say some fictitious machine code binary of "011010010111011101100000011000001101". 2 | 3 | C is pretty much a macro language for assembly. 4 | 5 | Assembly languages are low-level programming languages where you are giving instructiins like 6 | 7 | "load from memory location 123" "load from memory location 124" "add those together" "store the result at memory location 124" "compare to memory 77" "if that location equals 4, jump to instruction 60" 8 | 9 | Different processors have different assembly languages, so you can't run the same assembly programs on, say, x86 and ARM machines. 10 | 11 | But which assembly to choose? 12 | 13 | Whatever processor you're writing for? Different architectures use different instruction sets 14 | 15 | Let’s say I want one for an amd rizen 3200. Should I pick masm? Gas? Nasm? Yasm? 16 | 17 | They’re all x86_64 assemblers. There isn’t “assembly language” so much as a whole family of assembly languages. It’s not like saying it’s programmed in C is all I’m saying. 18 | 19 | For x86 there are two main dialects of assembly: AT&T and Intel. Personally I prefer Intel, I think it looks cleaner with less sigils, and putting the destination operator first makes more sense with instructions like `sub` and especially with comparison and jump. `sub eax 4` computes eax-4 and stores the result in eax, on AT&T syntax this is written `sub $4 %eax` so you have to read "subtract 4 from eax". And `cmp 4 eax; jl label` is simply "jump if 4 < eax" on Intel syntax, but in AT&T syntax the comparison is swapped to `cmp %eax $4`, but `jl` still means "jump if 4 < eax". It's very easy to get confused. 20 | 21 | Beyond this, the assemblers are mostly different in whether they support macros and what kind. So the choice isn't too important. 22 | -------------------------------------------------------------------------------- /topics/babel.md: -------------------------------------------------------------------------------- 1 | Babel is a transpiler (translator + compiler) and it converts modern code into old code, able to run in older browsers. 2 | 3 | ```bash 4 | npm install babel-cli babel-core babel-preset-env 5 | ``` 6 | 7 | `babel-cli` - Command line interface. Takes a js file and returns a transpiled one. 8 | `babel-core` - The transpiling logic. 9 | `babel-preset-env` - Each new javascript feature has a **separate** plugin. Intead of installing them one by one, we can install a preset containing all of them. 10 | 11 | To run the transpiler we can use: 12 | ```bash 13 | # Use the env preset to transpile index.js and put the output in the build folder in index.js. 14 | babel --presets env index.js -o build/index.js 15 | ``` 16 | This command is for one file. In order to transpile many files, a bundler like Webpack is needed. Here, every file is transpiler first, before being added to the bundle. 17 | 18 | We can add this in `package.json` for convenience: 19 | ```json 20 | { 21 | "scripts": { 22 | "babel": "babel --presets env index.js -o build/index.js" 23 | } 24 | } 25 | ``` -------------------------------------------------------------------------------- /topics/binary/bitwise.md: -------------------------------------------------------------------------------- 1 | # OR 2 | 3 | Sets each bit to 1 if one of two bits is 1. 4 | 5 | ```javascript 6 | // 1 = 00000001 7 | // 2 = 00000010 8 | 9 | console.log(1 | 2); 10 | // 3 = 00000011 11 | ``` 12 | 13 | # Bitwise AND 14 | 15 | Sets each bit to 1 if both bits are 1. 16 | 17 | ```javascript 18 | // 1 = 00000001 19 | // 2 = 00000010 20 | 21 | console.log(1 & 2); 22 | // 0 = 00000000 23 | ``` 24 | 25 | # Bitwise XOR 26 | 27 | Sets each bit to 1 if only one of two bits is 1. 28 | 29 | ```javascript 30 | // 10 = 00001010 31 | 32 | console.log(1 ^ 2); 33 | // 6 = 000000110 34 | ``` 35 | 36 | # Bitwise NOT 37 | 38 | Inverts all the bits. 39 | 40 | # Shift Left 41 | 42 | Add n zeros to the right i.e. remove n bits from the left. (binary to number) 43 | 44 | ``` 45 | 00000 111 (7) << 1 = 0000 111 0 (14) 46 | 00000 101 (5) << 3 = 00 101 000 (40) 47 | ``` 48 | 49 | # Shift Right 50 | 51 | Add n zeros to the left i.e. remove n bits from the right. (binary to number) 52 | 53 | ``` 54 | 00 101010 (42) >> 4 = 000000 10 (2) 55 | 00000 111 (7) >> 1 = 000000 11 (3) 56 | 00 110011 (51) >> 3 = 00000 110 (6) 57 | ``` 58 | -------------------------------------------------------------------------------- /topics/caching.md: -------------------------------------------------------------------------------- 1 | # Memcached 2 | 3 | It stores key-value pairs in memory for quick access. It doesn't persist data to disk as a database. 4 | 5 | Can be run on a separate machine, but usually it's on the app server. 6 | 7 | When an HTTP request hits the server, it first checks if memcached has the response stored and returns that. If not, it retireves the data from the database, generates the reposnse, and saves it in the cache for future use. 8 | 9 | ```bash 10 | sudo apt-get install memcached 11 | ``` 12 | 13 | ```bash 14 | # key (string) - value (string) 15 | set(key, value) 16 | get(key) 17 | delete(key) 18 | ``` -------------------------------------------------------------------------------- /topics/cryptojs.md: -------------------------------------------------------------------------------- 1 | # Hashing 2 | 3 | ```js 4 | const SHA256 = require("crypto-js/sha256"); 5 | 6 | console.log(SHA256("pass").toString()); 7 | 8 | // d74ff0ee8da3b9806b18c877dbf29bbde50b5bd8e4dad7a3a725000feb82e8f1 9 | 10 | console.log(SHA256("pass")); 11 | 12 | /* 13 | { 14 | words: [ 15 | -682626834, 16 | -1918649984, 17 | 1796786295, 18 | -604857411, 19 | -452240424, 20 | -455419997, 21 | -1490747377, 22 | -343742223 23 | ], 24 | sigBytes: 32 25 | } 26 | */ 27 | ``` 28 | 29 | # Encryption 30 | 31 | **encrypt** 32 | 33 | ```js 34 | const CryptoJS = require("crypto-js"); 35 | const readline = require("readline"); 36 | 37 | const rl = readline.createInterface({ 38 | input: process.stdin, 39 | output: process.stdout, 40 | }); 41 | 42 | rl.question("Enter string for encryption: ", (string) => { 43 | rl.question("Enter secret: ", (secret) => { 44 | let encrypted = CryptoJS.AES.encrypt(string, secret).toString(); 45 | console.log(`Encrypted string: ${encrypted}`); 46 | rl.close(); 47 | }); 48 | }); 49 | ``` 50 | 51 | **decrypt** 52 | 53 | ```js 54 | const CryptoJS = require("crypto-js"); 55 | const readline = require("readline"); 56 | 57 | const rl = readline.createInterface({ 58 | input: process.stdin, 59 | output: process.stdout, 60 | }); 61 | 62 | rl.question("Enter string for decryption: ", (string) => { 63 | rl.question("Enter secret: ", (secret) => { 64 | let bytes = CryptoJS.AES.decrypt(string, secret); 65 | let decrypted = bytes.toString(CryptoJS.enc.Utf8); 66 | console.log(`Decrypted string: ${decrypted}`); 67 | rl.close(); 68 | }); 69 | }); 70 | ``` 71 | -------------------------------------------------------------------------------- /topics/cybersecurity/csrf.md: -------------------------------------------------------------------------------- 1 | # Cross Site Request Forgery (CSRF) 2 | 3 | **A CSRF vulnerability enables an attacker to perform actions on a website via an authenticated user.** 4 | 5 | In a CSRF attack, the attacker makes a request to a third party page in the background, for instance by sending a POST request to your bank website. If you have a valid session with your bank, any website can make a request in the background that will be carried out unless your bank uses counter measures against CSRF. 6 | -------------------------------------------------------------------------------- /topics/cybersecurity/cybersecurity.md: -------------------------------------------------------------------------------- 1 | - **SSL** - Let's encrypt. 2 | - **Encryption** - Password hashing. 3 | - **JWT** - Tokens vs cookies. 4 | - **Reverse-proxy** - Localhost vs direct. 5 | - **User groups** - Linux permissions. 6 | -------------------------------------------------------------------------------- /topics/cybersecurity/jwt.md: -------------------------------------------------------------------------------- 1 | > You don't do any token validation on the client. The client shouldn't even be aware of the token. localStorage is bad. 2 | 3 | > Server middleware validates tokens, and redirects to login page if invalid. 4 | 5 | Storing JWTs in localStorage or sessionStorage in a browser can make them vulnerable to XSS attacks. Storing them in a secure, HttpOnly cookie is generally safer. 6 | 7 | After generating the JWT, send it to the client in an HttpOnly cookie. This ensures that the token cannot be accessed via JavaScript (protecting against XSS attacks). 8 | 9 | ```js 10 | const express = require("express"); 11 | const jwt = require("jsonwebtoken"); 12 | const app = express(); 13 | 14 | app.post("/login", (req, res) => { 15 | // Authenticate user (you'd typically check the credentials here) 16 | const userId = req.body.userId; // example user ID 17 | 18 | // Generate the JWT 19 | const token = jwt.sign({ userId }, "your_secret_key", { expiresIn: "1h" }); 20 | 21 | // Set the JWT in an HttpOnly cookie 22 | res.cookie("token", token, { 23 | httpOnly: true, // Prevents access to the cookie via JavaScript 24 | secure: true, // Ensures the cookie is sent over HTTPS (set to true in production) 25 | sameSite: "Strict", // Helps protect against CSRF attacks 26 | }); 27 | 28 | res.send("Logged in successfully"); 29 | }); 30 | ``` 31 | 32 | When the client makes requests to your server, the JWT will be automatically sent in the Cookie header. You can access and verify this token on the server to authenticate the request. 33 | 34 | ```js 35 | app.get("/protected-route", (req, res) => { 36 | const token = req.cookies.token; 37 | 38 | if (!token) { 39 | return res.status(401).send("Access denied. No token provided."); 40 | } 41 | 42 | try { 43 | const decoded = jwt.verify(token, "your_secret_key"); 44 | req.user = decoded; // Now you have access to the user info in req.user 45 | res.send("Protected data"); 46 | } catch (err) { 47 | res.status(400).send("Invalid token"); 48 | } 49 | }); 50 | ``` 51 | 52 | To log out a user, simply clear the cookie on the server. 53 | 54 | ```js 55 | app.post("/logout", (req, res) => { 56 | res.clearCookie("token"); 57 | res.send("Logged out successfully"); 58 | }); 59 | ``` 60 | 61 | If your front-end relies on the token to determine whether to display a login page or a content page, making an API request on app load to check the token is a common and effective approach. 62 | 63 | API Request on App Load: On the initial load of your front-end application, make an API request to a backend endpoint (e.g., /me, /profile, or /auth/check) that checks the validity of the token and returns the user’s information if the token is valid. 64 | 65 | ```js 66 | // Example using Fetch API 67 | function checkAuthStatus() { 68 | return fetch("/auth/check", { 69 | method: "GET", 70 | credentials: "include", // Include cookies in the request 71 | }).then((response) => { 72 | if (!response.ok) { 73 | throw new Error("Not authenticated"); 74 | } 75 | return response.json(); 76 | }); 77 | } 78 | 79 | // Call this function on app load 80 | checkAuthStatus() 81 | .then((user) => { 82 | // Token is valid; show content page 83 | console.log("User is authenticated:", user); 84 | showContentPage(user); 85 | }) 86 | .catch((error) => { 87 | // Token is invalid or not present; show login page 88 | console.log("User is not authenticated:", error); 89 | showLoginPage(); 90 | }); 91 | ``` 92 | 93 | credentials: 'include': This ensures that the cookie containing the JWT is sent with the request. 94 | -------------------------------------------------------------------------------- /topics/cybersecurity/sqlinjection.md: -------------------------------------------------------------------------------- 1 | # SQL Injection 2 | 3 | Password: 4 | 5 | ``` 6 | password 7 | ``` 8 | 9 | Result: 10 | 11 | ```sql 12 | SELECT * 13 | FROM users 14 | WHERE 15 | email = 'user@email.com' 16 | AND pass = 'password' LIMIT 1 17 | ``` 18 | 19 | --- 20 | 21 | Use this to check for vulnerability. 22 | 23 | Password: 24 | 25 | ``` 26 | ' 27 | ``` 28 | 29 | Result: 30 | 31 | ```sql 32 | SELECT * 33 | FROM users 34 | WHERE 35 | email = 'user@email.com' 36 | -- ERROR 37 | AND pass = ''' LIMIT 1 38 | ``` 39 | 40 | --- 41 | 42 | This returns a session / JWT token 43 | 44 | Password: 45 | 46 | ```sql 47 | ' or 1=1 -- 48 | ``` 49 | 50 | Result: 51 | 52 | ```sql 53 | SELECT * 54 | FROM users 55 | WHERE 56 | email = 'user@email.com' 57 | AND pass = '' or 1=1 --' LIMIT 1 58 | 59 | ``` 60 | -------------------------------------------------------------------------------- /topics/cybersecurity/xss.md: -------------------------------------------------------------------------------- 1 | # Cross Site Scripting (XSS) 2 | 3 | **An XSS vulnerability enables an attacker to inject JavaScript into a site.** 4 | 5 | Handling special characters properly by preventing them from being parsed as code. 6 | 7 | - Input validation 8 | 9 | - Limit allowed user inputs by blacklisting `>`, `<`, `"`, `<script>`... 10 | 11 | - Input transformation 12 | 13 | - Encoding input into HTML character enitites: 14 | - `<` into `<` 15 | - `>` into `>` 16 | 17 | - Escaping 18 | - Having an input of `" alert("hacked")` as the quote ends the string in code, and executes the `alert`. 19 | - Use backlashes to escape the quotes `\" alert("hacked")`. 20 | 21 | #### Example 22 | 23 | Let's say there's a website with an `input` form that: 24 | 25 | - Generates a query string. 26 | - Displays that string into the DOM. 27 | 28 | ```js 29 | function ready() { 30 | let query = new URL(window.location).searchParams.get("query"); 31 | document.getElementById("query-input").value = query; 32 | document.getElementById("query-output").innerHTML = query; 33 | } 34 | ``` 35 | 36 | ``` 37 | http://example.com/search?query=something 38 | ``` 39 | 40 | Now, putting this inside the input form... 41 | 42 | ```html 43 | <img src onerror="alert(document.cookie)" /> 44 | ``` 45 | 46 | Would inject the "string" via `innerHTML` as an image, which due to the missing `src`, would run the javascript code, which could be code sending the hacked the cookie via email. 47 | 48 | The danger is when hackers send disquised links to other users to click. 49 | 50 | To avoid this, use `innerText` instead! 51 | -------------------------------------------------------------------------------- /topics/database/conventions.md: -------------------------------------------------------------------------------- 1 | # Naming 2 | 3 | - **Singular form**. Both tables and columns. 4 | - Be consistent! Doesn't matter if you use camelCase or snake_case. Use whatever the front-end uses. 5 | - Avoid abbreviations or prefixes. 6 | - Use unique names that cannot collude with SQL/RDBMS reserved words (avoid name, order, percent...) **or** use a trailing underscore. 7 | - Do not use the table name followd by “id” (e.g. client_id) as your PK. id is more than enough and everyone will understand. 8 | - Never use capital letters in your table or field names. Ever. 9 | -------------------------------------------------------------------------------- /topics/database/node-mssql.md: -------------------------------------------------------------------------------- 1 | **server.js** 2 | 3 | ```js 4 | const express = require("express"); 5 | const http = require("http"); 6 | const sql = require("mssql"); 7 | 8 | const config = require("./config.js"); 9 | const middleware = require("./middleware.js"); 10 | 11 | let login = require("./api/auth/login"); 12 | let users = require("./api/auth/users"); 13 | 14 | let catalogue = require("./api/endpoints/catalogue"); 15 | let categories = require("./api/endpoints/categories"); 16 | let groups = require("./api/endpoints/groups"); 17 | let suppliers = require("./api/endpoints/suppliers"); 18 | 19 | const app = express(); 20 | 21 | app.use(express.json()); // Needed for POST and PATCH requests 22 | 23 | app.all("/api/*", middleware.authenticationMiddleware); 24 | 25 | // .use(middleware.requestsMiddleware) 26 | 27 | app.use(login) 28 | .use(users) 29 | 30 | .use(catalogue) 31 | .use(categories) 32 | .use(groups) 33 | .use(suppliers) 34 | 35 | .use(middleware.errorMiddleware); 36 | 37 | async function start() { 38 | // Initialize pool only once 39 | const connection = new sql.ConnectionPool(config.db); 40 | const pool = await connection.connect(); 41 | 42 | // pool available in routes via let request = req.app.locals.pool.request(); 43 | app.locals.pool = pool; 44 | app.locals.sql = sql; 45 | 46 | const server = http.createServer(app); 47 | 48 | server.listen(config.port, () => { 49 | console.log(`listening on port: ${config.port}`); 50 | }); 51 | } 52 | 53 | start(); 54 | ``` 55 | 56 | **users.js** 57 | 58 | ```js 59 | const express = require("express"); 60 | const router = express.Router(); 61 | 62 | router.get("/api/users/:userId", async (req, res, next) => { 63 | try { 64 | let userId = req.params.userId; 65 | 66 | let request = req.app.locals.pool.request(); 67 | let sql = req.app.locals.sql; 68 | 69 | request.input("userId", sql.Int, userId); 70 | 71 | let query = ` 72 | select * 73 | from user u 74 | where u.id = @userId 75 | ; 76 | `; 77 | 78 | let result = await request.query(query); 79 | 80 | let final = result.recordset[0]; 81 | 82 | res.send(final); 83 | } catch (err) { 84 | next(err); 85 | } 86 | }); 87 | 88 | module.exports = router; 89 | ``` 90 | -------------------------------------------------------------------------------- /topics/database/node-mysql.md: -------------------------------------------------------------------------------- 1 | ```js 2 | const express = require("express"); 3 | const util = require("util"); 4 | 5 | let databaseHandler = (pool) => { 6 | return (req, res, next) => { 7 | // let subodmain = req.subdomains[0]; 8 | // req.subdomains is [] in deployment due to the reverse_proxy 9 | // req.decoded comes from authenticationHandler 10 | let database = req.decoded.database; 11 | 12 | // Get a connection from the main pool in app.js 13 | pool.getConnection((err, conn) => { 14 | if (err) { 15 | console.log(err); 16 | return; 17 | } 18 | // Change the database for the connection 19 | conn.changeUser({ database: database }, function (err) { 20 | if (err) { 21 | console.log(err); 22 | return; 23 | } 24 | 25 | // Promisify for Node.js async/await. 26 | const asyncQuery = util.promisify(conn.query).bind(conn); 27 | 28 | // Pass the modified query method down the chain as a property of req, avaiable via next() 29 | // req.query is used for queryStrings, so we use asyncQuery to avoid overwriting it 30 | // connection.release() is called in the routes 31 | req.asyncQuery = asyncQuery; 32 | req.connection = conn; 33 | req.tenant = database; 34 | 35 | next(); 36 | }); 37 | }); 38 | }; 39 | }; 40 | 41 | module.exports = { databaseHandler }; 42 | ``` 43 | 44 | ```js 45 | router.get("/api/companies/:companyId", async (req, res, next) => { 46 | try { 47 | let companyId = req.params.companyId; 48 | 49 | let query = ` 50 | select * 51 | from company c 52 | where c.id = ? 53 | `; 54 | 55 | let rows = await req.query(query, [companyId]); 56 | let company = rows[0]; 57 | 58 | res.status(200).send(company); 59 | } catch (err) { 60 | next(err); 61 | } finally { 62 | req.connection.release(); 63 | } 64 | }); 65 | ``` 66 | -------------------------------------------------------------------------------- /topics/database/normalization.md: -------------------------------------------------------------------------------- 1 | # Table Relationships 2 | 3 | **Look both ways (From each perspective) when trying to determine the relationship.** 4 | 5 | ## One to Many - 90% 6 | 7 |  8 | 9 |  10 | 11 | ## Many to Many - 10% 12 | 13 |  14 | 15 |  16 | 17 | ## One to One - 0% 18 | 19 | Not a thing.If one row points to only one row, you might as well join the tables. 20 | 21 |  22 | 23 | Sometimes you think you have a one-to-one relationship, but you don’t. Look both ways (from each perspective) to avoid this. 24 | 25 |  26 | 27 | # Normalization 28 | 29 | Taking your database design through these 3 steps will vastly improve the quality of your data. 30 | 31 | There are more than 3 Normal Forms, but usually 3 is the norm. There are more than 6. 32 | 33 | ## First Normal Form (1NF) 34 | 35 | Each of the columns and tables should contain one and only one value without it repeating. 36 | 37 | Usually every 1NF problem is solved by creating a new table. One of the signs for the need is when columns start having the same name with a number differentiating them. Computer1, Computer2… 38 | 39 |  40 | 41 | ## Second Normal Form (2NF) 42 | 43 | Any non-key field should be dependent on the entire primary key i.e. “Can I figure out any of the values in the row from just part of the composite key?”. Only a problem when dealing with composite keys. 44 | 45 |  46 | 47 | ## Third Normal Form (3NF) 48 | 49 | No non-key field is dependent on any other non-key field i.e. “Can I figure out any of the values in this row from any of the other values?”. 50 | 51 |  52 | 53 | ## Denormalization 54 | 55 | Sometimes tables intentionally break normalization, and some only seem like they do. 56 | 57 | Creating a new table for phones and emails would complicate things needlessly. The same goes for the area codes. 58 | 59 |  60 | -------------------------------------------------------------------------------- /topics/database/optimizationQuerying.md: -------------------------------------------------------------------------------- 1 | # Best practices 2 | 3 | - Always foreign key to IDs, rather than column values. 4 | - Try to stick to `where` clauses on indexed columns, instead of `like`. 5 | - Don't go crazy with `joins`. 6 | - Don't use varchar(255). Try to use the lowest number possible. 7 | - Avoid using functions on the Left Hand-Side of the Operator. It's ok to have a function in the right hand. 8 | 9 | ```sql 10 | select * from users where upper(email) = 'foo@bar.com'; 11 | -- vs 12 | select * from users where created < now(); 13 | ``` 14 | 15 | - Avoid Wildcard Characters at the Beginning of a LIKE Pattern. MySQL won't use an index for wildcard searches. 16 | 17 | ```sql 18 | select * from users where email LIKE '%foo%'; 19 | -- vs 20 | select * from users where email LIKE 'foo%'; 21 | ``` 22 | 23 | - Avoid OR conditions and use UNION as an alternative. 24 | - Avoid sorting with a mixed order. 25 | - In where clause, compare a column to a value which matches the column’s type. 26 | 27 | ```sql 28 | select * from users where email = 101; 29 | -- vs 30 | select * from users where email = '101'; 31 | ``` 32 | 33 | - Columns on each side of ON clause of a join must be of the same type. 34 | - If columns on each side of ON clause of a join is VARCHAR, make sure the collations of each of the columns are identical. 35 | - You do not want to place too many indexes on tables that are frequently updated 36 | - Keep your table statistics up to date. Done with `ANALYZE TABLE table_name` 37 | 38 | # What if the query contains OR instead of AND? 39 | 40 | > In this case, MySQL won't be able to use the index on queries having an OR condition, even if the query contains lookup column and maintains the order of WHERE clause same as the index. 41 | 42 | Therefore, it's recommended to avoid such OR conditions and consider splitting the query to two parts, combined with a UNION DISTINCT (or even better, UNION ALL, in case you know there won't be any duplicate results) 43 | 44 | ```sql 45 | select status, category_id from users where status = 1 46 | UNION ALL 47 | select status, category_id from users where category_id = 3 48 | ``` 49 | 50 | # What if the query contains GROUP BY and ORDER BY? 51 | 52 | ```sql 53 | -- index(status, category_id, email) 54 | select * from users where status = 1 ORDER BY category_id 55 | ``` 56 | 57 | This will use the composite index for the WHERE clause. 58 | 59 | If you think this will narrow down the records with the status having value as 1, sadly you now need to perform a sort on these resulting records to get them sorted by category_id. 60 | 61 | This is because the index didn't sort the results by category_id in any meaningful way and ORDER BY clause lacks the lookup column. 62 | 63 | This is known as a File Sort (some of you might have noticed this in an explain result). This happens because the index that we created failed to satisfy for the ORDER BY clause. 64 | 65 | > File Sort: A sort that occurs after the query; it requires fetching the data into a temporary buffer and sorting it before finally returning. This wouldn't have been needed if the data was already sorted by the index in the way you wanted. 66 | 67 | ```sql 68 | select * from users where status = 1 ORDER BY status, category_id 69 | ``` 70 | 71 | This query can leverage the usage of the mentioned index because it qualifies for both the WHERE clause and ORDER BY clause. 72 | 73 | The same is also applicable to GROUP BY statements. if you run the following query with the composite index on (status, category_id, email): 74 | 75 | ```sql 76 | select * from users where status = 1 GROUP BY category_id 77 | ``` 78 | 79 | The records are already sorted by status, category_id and email. This allows you to quickly filter down all the records with status = 1. After these results are returned they are also then sorted based on category_id since the index orders the rows differently than required in the query. 80 | 81 | # What if the query contains JOINS? 82 | 83 | > You should have indexes on all the columns used in the JOIN clauses. i.e, columns on each side of ON clause of a join must be indexed. 84 | -------------------------------------------------------------------------------- /topics/database/queriesAdmin.md: -------------------------------------------------------------------------------- 1 | # Users 2 | 3 | ```sql 4 | -- Create user 5 | CREATE USER 'user'@'localhost' IDENTIFIED BY 'password'; 6 | 7 | -- Give access to certain areas. In this case, it's for everything as *.* stands for dbName.tableName i.e. all of them. 8 | GRANT ALL PRIVILEGES ON * . * TO 'user'@'localhost'; 9 | 10 | -- Fix errors 11 | ALTER USER 'user'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password' 12 | 13 | -- Reload the privileges. 14 | FLUSH PRIVILEGES; 15 | 16 | -- List all users. 17 | SELECT user FROM mysql.user; 18 | 19 | -- Show current user. 20 | SELECT CURRENT_USER(); 21 | 22 | -- Delete user. 23 | DROP USER 'user'@'localhost'; 24 | ``` 25 | 26 | ## Permissions 27 | 28 | **Options:** ALL PRIVILEGES, CREATE, DROP, DELETE, INSERT, SELECT, UPDATE, GRANT OPTION (User can give permissions). 29 | 30 | ```sql 31 | -- Give a specific permission, for a specific table. 32 | GRANT permission ON dbName.tableName TO '<user>'@'localhost'; 33 | 34 | -- Remove a permission. 35 | REVOKE permission ON dbName.tableName FROM '<user>'@'localhost'; 36 | ``` 37 | 38 | ## Change password 39 | 40 | ```sql 41 | ALTER USER 'root'@'localhost' IDENTIFIED BY 'MyNewPass'; 42 | FLUSH PRIVILEGES; 43 | 44 | ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'MyNewPass'; 45 | FLUSH PRIVILEGES; 46 | ``` 47 | -------------------------------------------------------------------------------- /topics/database/queriesAggregate.md: -------------------------------------------------------------------------------- 1 | # MAX, AVERAGE, SUM... Across columns 2 | 3 | ```sql 4 | select 5 | *, 6 | ( 7 | select max(v) 8 | from ( 9 | values 10 | (sales2017), 11 | (sales2018), 12 | (sales2019) 13 | ) as value(v) 14 | ) as maxSales 15 | from sales 16 | ``` 17 | 18 | # Multiple sums 19 | 20 | ```sql 21 | select 22 | mi.acIdent, 23 | m.acissuer, 24 | datediff(day, max(m.adDate), getdate()) lastSaleDays, 25 | sum(CASE WHEN m.adDate >= getdate() - 30 THEN mi.anQty ELSE 0 END) soldPastDaysQty, 26 | sum(CASE WHEN m.adDate between getdate() - (365 * 1) and getdate() - (365 * 1 - 30) THEN mi.anQty ELSE 0 END) soldNextDaysOneYearAgoQty, 27 | sum(CASE WHEN m.adDate between getdate() - (365 * 2) and getdate() - (365 * 2 - 30) THEN mi.anQty ELSE 0 END) soldNextDaysTwoYearsAgoQty, 28 | sum(CASE WHEN m.adDate between getdate() - (365 * 3) and getdate() - (365 * 3 - 30) THEN mi.anQty ELSE 0 END) soldNextDaysThreeYearsAgoQty, 29 | sum(CASE WHEN m.adDate between getdate() - (365 * 4) and getdate() - (365 * 4 - 30) THEN mi.anQty ELSE 0 END) soldNextDaysFourYearsAgoQty 30 | from the_moveitem mi 31 | left join the_move m on mi.acKey = m.acKey 32 | where 33 | m.adDate > getdate() - 365 * 4 34 | group by 35 | mi.acident, 36 | m.acIssuer 37 | ``` 38 | 39 | # STRING_AGG / mysql group_concat 40 | 41 | ```sql 42 | select 43 | sku, 44 | STRING_AGG(category, ', ') 45 | from categories 46 | group by 47 | sku 48 | ``` 49 | 50 | # Rollup (Total Row) 51 | 52 | `ROLLUP` is a subclause of the `GROUP BY` clause which provides a shorthand for defining multiple grouping sets. Unlike the `CUBE` subclause, `ROLLUP` does not create all possible grouping sets based on the dimension columns; the `CUBE` makes a subset of those. 53 | 54 | When generating the grouping sets, `ROLLUP` assumes a hierarchy among the dimension columns and only generates grouping sets based on this hierarchy. 55 | 56 | The `ROLLUP` is often used to generate subtotals and totals for reporting purposes. 57 | 58 | ```sql 59 | SELECT 60 | brand, 61 | category, 62 | SUM(sales) sales 63 | FROM 64 | sales.sales_summary 65 | GROUP BY 66 | ROLLUP(brand, category) 67 | ``` 68 | 69 | This will result in 70 | 71 | | brand | category | sales | | 72 | | ----- | -------- | ----- | ----------- | 73 | | Honda | cars | 100 | 74 | | Honda | bikes | 200 | 75 | | Honda | NULL | 300 | Subtotal | 76 | | BMW | cars | 400 | 77 | | BMW | bikes | 500 | 78 | | BMW | NULL | 900 | Subtotal | 79 | | NULL | NULL | 1200 | Grand Total | 80 | -------------------------------------------------------------------------------- /topics/database/queriesLogic.md: -------------------------------------------------------------------------------- 1 | # Coalesce 2 | 3 | The SQL Server `COALESCE` function handles `NULL` values. 4 | 5 | The expression accepts a number of arguments, evaluates them in sequence, and returns the first non-null argument. 6 | 7 | ```sql 8 | SELECT COALESCE (NULL,'A','B') -- A 9 | SELECT COALESCE (NULL,100,20,30,40) -- 100 10 | SELECT COALESCE (NULL,NULL,20,NULL,NULL) -- 20 11 | SELECT COALESCE (NULL,NULL,NULL,NULL,NULL,'foo') -- foo 12 | SELECT COALESCE (NULL,NULL,NULL,NULL,1,'foo') -- 1 13 | SELECT COALESCE (NULL,NULL,NULL,NULL,NULL,'foo',1) -- coversion failed when converting the varchar value 'foo' to data type int 14 | ``` 15 | 16 | # Recursion 17 | 18 | Dates generator from date to date (now). 19 | 20 | ```sql 21 | with recursive dates as ( 22 | select '2023-01-01' date -- start date 23 | union all 24 | select date_add(date, interval 1 day) 25 | from dates 26 | where date < curdate() -- end date 27 | ) 28 | select * from dates 29 | 30 | /* 31 | 2023-01-01 32 | 2023-01-02 33 | 2023-01-03 34 | ... 35 | */ 36 | ``` 37 | -------------------------------------------------------------------------------- /topics/database/queriesSchema.md: -------------------------------------------------------------------------------- 1 | # Database 2 | 3 | ```sql 4 | SHOW DATABASES; -- List databases. 5 | SELECT database(); -- Show current database. 6 | USE dbName; -- Select a database. 7 | 8 | CREATE DATABASE dbName; -- Create a database. 9 | DROP DATABASE dbName; -- Delete a database. 10 | ``` 11 | 12 | # Tables 13 | 14 | ### Create 15 | 16 | ```sql 17 | SHOW TABLES; -- List all tables. 18 | DESCRIBE tableName; -- Display columns and types. 19 | 20 | -- Shows the query that creates the table. 21 | SHOW CREATE TABLE tableName; 22 | 23 | -- Create a table. 24 | CREATE TABLE tableName (column1 DATATYPE, column2 DATATYPE); 25 | 26 | -- Example 27 | CREATE TABLE user ( 28 | id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, -- Important 29 | name VARCHAR(255), 30 | pass VARCHAR(255) 31 | ); 32 | ``` 33 | 34 | ### Modify 35 | 36 | ```sql 37 | -- Rename a table. 38 | RENAME TABLE tableName1 TO tableName2; 39 | 40 | -- Change a column's datatype. 41 | ALTER TABLE tablename MODIFY columnname DATATYPE; 42 | 43 | -- Add a column at end. 44 | ALTER TABLE tableName ADD columnName DATATYPE; 45 | 46 | -- Add a column at certain location. 47 | ALTER TABLE tableName ADD columnName DATATYPE AFTER columnName; 48 | 49 | -- Delete a column. 50 | ALTER TABLE tableName DROP columnName; 51 | 52 | -- Change a column name. Has to be backticks. 53 | ALTER TABLE tableName CHANGE `oldcolname` `newcolname` datatype(length); 54 | 55 | -- Reset AUTO_INCREMENT id. For this to work, the table must be empty. 56 | ALTER TABLE table AUTO_INCREMENT = 1; 57 | ``` 58 | 59 | # Foreign Keys 60 | 61 | They are used for **data integrity** i.e. they prevent entering values that don't exist in the linked table (gives an error). 62 | 63 | A FOREIGN KEY is a field in one table that refers to the PRIMARY KEY in another table. 64 | 65 | The table containing the foreign key is called the child table, and the table containing the candidate key is called the referenced or parent table. 66 | 67 | ```sql 68 | -- Foreign key definition during table creation. 69 | CREATE TABLE user ( 70 | id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, 71 | name VARCHAR(255), 72 | pass VARCHAR(255), 73 | phoneId INT, 74 | FOREIGN KEY (phoneId) REFERENCES phone(id) 75 | ); 76 | 77 | -- Add foreign key. 78 | ALTER TABLE table1 ADD FOREIGN KEY (idColumn) REFERENCES table2(idColumn); 79 | 80 | -- Remove foreign key. 81 | ALTER TABLE tableName DROP FOREIGN KEY FK_columnName; 82 | ``` 83 | 84 | ```sql 85 | -- List foreign keys. 86 | SELECT 87 | tableName, 88 | COLUMNNAME, 89 | CONSTRAINT_NAME, 90 | REFERENCED_tableName, 91 | REFERENCED_COLUMNNAME 92 | FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE 93 | WHERE 94 | REFERENCED_tableName = 'my_table'; 95 | 96 | -- One-liner. 97 | SELECT tableName, COLUMNNAME, CONSTRAINT_NAME, REFERENCED_tableName, REFERENCED_COLUMNNAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE REFERENCED_tableName = 'my_table'; 98 | ``` 99 | 100 | # Delete 101 | 102 | Be **VERY** careful with this one. **ALWAYS** select first, delete second. 103 | 104 | ```sql 105 | DROP TABLE tableName; 106 | ``` 107 | -------------------------------------------------------------------------------- /topics/database/queriesVarious.md: -------------------------------------------------------------------------------- 1 | # Declare Variables 2 | 3 | ```sql 4 | -- regular 5 | DECLARE @date DATETIME = '07.01.2019' 6 | 7 | -- from select 8 | DECLARE @count INT; 9 | SET @count = (SELECT COUNT(sku) FROM product) 10 | SELECT @count; 11 | ``` 12 | 13 | # YYYY-MM date format 14 | 15 | ```sql 16 | -- 2.5 million rows 17 | 18 | -- 12 sec 19 | select date 20 | from sales 21 | 22 | -- 13 sec 23 | select concat(year(date), '-', RIGHT('00' + CONVERT(varchar(2), DATEPART(MONTH, date)), 2)) ym 24 | from sales 25 | 26 | -- 15 sec 27 | select CAST(YEAR(date) AS VARCHAR(4)) + '-' + RIGHT('00' + CAST(MONTH(date) AS VARCHAR(2)), 2) as ym 28 | from sales 29 | 30 | -- 29 sec 31 | select FORMAT(date, 'yyyy-MM') as ym 32 | from sales 33 | ``` 34 | 35 | # Only numbers 36 | 37 | ```sql 38 | select barcode 39 | from barcodes 40 | where barcode not like '%[^0-9]%' 41 | ``` 42 | 43 | # Remove trailing zeros 44 | 45 | ```sql 46 | select cast(barcode as int) 47 | ``` 48 | 49 | # Order a sub-query 50 | 51 | Using `top 99.9999 percent` is a hack to achieve the ordering. 52 | 53 | Note that `top 100 percent` won't work. 54 | 55 | ```sql 56 | select 57 | sku, 58 | STRING_AGG(attribute, ', ') attributes 59 | from ( 60 | select top 99.9999999999999 percent 61 | sku, 62 | attribute 63 | from attributes 64 | order by 65 | sku asc, 66 | attribute asc 67 | ) t1 68 | group by sku 69 | ``` 70 | 71 | # Previous value 72 | 73 | ```sql 74 | select 75 | lag(value) over (order by created) -- returns the previous row's value 76 | from sales 77 | ``` 78 | 79 | # CTE - Common Table Expression 80 | 81 | It defines a temporary result set which can be used in a SELECT statement. 82 | 83 | ```sql 84 | WITH 85 | salesrep AS ( 86 | SELECT 87 | employeeNumber, 88 | CONCAT(firstName, ' ', lastName) AS salesrepName 89 | FROM 90 | employees 91 | WHERE 92 | jobTitle = 'Sales Rep' 93 | ), 94 | customer_salesrep AS ( 95 | SELECT 96 | customerName, salesrepName 97 | FROM 98 | customers 99 | INNER JOIN 100 | salesrep ON employeeNumber = salesrepEmployeeNumber 101 | ) 102 | SELECT 103 | * 104 | FROM 105 | customer_salesrep 106 | ORDER BY customerName; 107 | ``` 108 | -------------------------------------------------------------------------------- /topics/database/queriesWindow.md: -------------------------------------------------------------------------------- 1 | # Partition By 2 | 3 | We use this to make a "sub-query" i.e. select n-th item from a table for further use. 4 | 5 | ### Data 6 | 7 | ```sql 8 | SELECT 9 | clientID, 10 | invoiceDate, 11 | revenue 12 | FROM sales 13 | ``` 14 | 15 | | clientID | invoiceDate | revenue | 16 | | -------- | ----------- | -------- | 17 | | 1017 | 2019-01-31 | 6574.65 | 18 | | 116 | 2018-02-05 | 5593.22 | 19 | | 1211 | 2018-01-15 | 3637.80 | 20 | | 116 | 2018-02-16 | 1848.00 | 21 | | 1211 | 2018-01-09 | 15615.65 | 22 | | 1017 | 2019-02-14 | 1386.00 | 23 | | 1211 | 2018-02-09 | 16145.72 | 24 | | 116 | 2018-02-13 | 2784.51 | 25 | | 1211 | 2018-03-28 | 8844.64 | 26 | 27 | ### Data with PARTITION BY 28 | 29 | In this case, we want to have the latest sale for each client. We can achieve this by partitioning the data i.e. ordering the sales for each client in descending order based on the date. We can then select only the desired row with `rowNumber`. 30 | 31 | ```sql 32 | SELECT 33 | ROW_NUMBER() OVER (PARTITION BY clientID ORDER BY invoiceDate DESC) rowNumber, 34 | clientID, 35 | invoiceDate, 36 | revenue 37 | FROM sales 38 | ``` 39 | 40 | | rowNumber | clientID | invoiceDate | revenue | 41 | | --------- | -------- | ----------- | -------- | 42 | | 1 | 1017 | 2019-02-14 | 1386.00 | 43 | | 2 | 1017 | 2019-01-31 | 6574.65 | 44 | | 1 | 116 | 2018-02-16 | 1848.00 | 45 | | 2 | 116 | 2018-02-13 | 2784.51 | 46 | | 3 | 116 | 2018-02-05 | 5593.22 | 47 | | 1 | 1211 | 2018-03-28 | 8844.64 | 48 | | 2 | 1211 | 2018-02-09 | 16145.72 | 49 | | 3 | 1211 | 2018-01-15 | 3637.80 | 50 | | 4 | 1211 | 2018-01-09 | 15615.65 | 51 | 52 | ### Result 53 | 54 | ```sql 55 | SELECT 56 | lastSale.clientID, 57 | lastSale.invoiceDate, 58 | lastSale.revenue 59 | FROM ( 60 | SELECT 61 | ROW_NUMBER() OVER (PARTITION BY clientID ORDER BY invoiceDate DESC) rowNumber, 62 | clientID, 63 | invoiceDate, 64 | revenue 65 | FROM sales 66 | ) lastSale 67 | WHERE lastSale.rowNumber = 1 68 | ``` 69 | 70 | We only get the first row for each client i.e. the last sale (sorted by descending invoice date). 71 | 72 | | acReceiver | adDate | sales | 73 | | ---------- | ---------- | ------- | 74 | | 1017 | 2019-02-14 | 1386.00 | 75 | | 116 | 2018-02-16 | 1848.00 | 76 | | 1211 | 2018-03-28 | 8844.64 | 77 | 78 | # Row Number 79 | 80 | ```sql 81 | SELECT 82 | ROW_NUMBER() OVER (ORDER BY profit DESC) rowNumber 83 | FROM sales 84 | ``` 85 | 86 | # Column sum / Running total 87 | 88 | This one is better because it can be based on all data... 89 | 90 | ```sql 91 | select 92 | sum(value) over (partition by client order by date desc) runningTotal -- the `order by` turns this into a running sum. 93 | from sales; 94 | ``` 95 | 96 | ...instead of just filtered. 97 | 98 | ```sql 99 | SELECT 100 | isnull(profit, 0) profit, 101 | SUM(profit) OVER(ORDER BY profit desc ROWS UNBOUNDED PRECEDING) AS profitRunning, -- cummulative sum of profit 102 | SUM(profit) OVER () AS profitTotal, -- sum of profit column 103 | SUM(profit) OVER(ORDER BY profit desc ROWS UNBOUNDED PRECEDING) / SUM(profit) OVER () profitShare 104 | FROM sales 105 | ``` 106 | 107 | # Duplicates 108 | 109 | ```sql 110 | SELECT 111 | sku 112 | FROM ( 113 | SELECT 114 | ROW_NUMBER() OVER (PARTITION BY sku ORDER BY sku asc) rowNumber, 115 | sku 116 | FROM product 117 | ) duplicates 118 | WHERE rowNumber > 1 119 | ``` 120 | -------------------------------------------------------------------------------- /topics/database/sqlserver.md: -------------------------------------------------------------------------------- 1 | ```sql 2 | -- tables 3 | SELECT * FROM INFORMATION_SCHEMA.TABLES; 4 | 5 | -- columns 6 | SELECT * FROM INFORMATION_SCHEMA.COLUMNS; 7 | ``` 8 | -------------------------------------------------------------------------------- /topics/database/terminology.md: -------------------------------------------------------------------------------- 1 | - SQL Server Instance = The running process of SQL Server, which manages databases. 2 | - Database = A collection of data inside an instance. 3 | - Schema = A logical namespace inside a database to organize objects. 4 | 5 | --- 6 | 7 | - SQL Server (the program) runs instances. 8 | - Each instance can manage multiple databases. 9 | - Each database can have multiple schemas. 10 | 11 | --- 12 | 13 | | **Concept** | **Explanation** | 14 | | ----------------------- | ------------------------------------------------------------------------------------------- | 15 | | **SQL Server (RDBMS)** | The software you install that allows you to create, manage, and query relational databases. | 16 | | **SQL Server Instance** | A running process of SQL Server that can manage one or more databases. | 17 | | **Database** | A collection of tables, views, and objects managed by an instance. | 18 | | **Schema** | A logical namespace inside a database to organize tables and other objects. | 19 | 20 | ``` 21 | SQL Server (RDBMS) 22 | └── Instance: MSSQLSERVER 23 | ├── Database: ERP_DB 24 | │ ├── Schema: hr 25 | │ │ ├── Table: hr.employees 26 | │ ├── Schema: finance 27 | │ ├── Table: finance.invoices 28 | ├── Database: Retail_DB 29 | ├── Schema: store 30 | ├── Table: store.products 31 | ``` 32 | 33 | | **RDBMS** | **Instance** | **Schemas** | 34 | | -------------- | ------------------- | ------------------- | 35 | | **SQL Server** | Yes (Named/Default) | Yes | 36 | | **PostgreSQL** | Yes (Cluster-based) | Yes | 37 | | **MySQL** | No (Single process) | No (Databases only) | 38 | -------------------------------------------------------------------------------- /topics/dotenv.md: -------------------------------------------------------------------------------- 1 | In order to use different parameters in our app depending on the enviroment such as... 2 | 3 | - Server ports 4 | - Database credentials 5 | - API keys 6 | 7 | ...we can declare environment variables. 8 | 9 | We do this by having a `.env` file to store the variables. 10 | 11 | **NEVER COMMIT THIS FILE. PUT IT IN .gitignore!** 12 | 13 | ``` 14 | DBNAME=database 15 | DBUSER=root 16 | DBPASSWORD=root 17 | ``` 18 | 19 | Which we can read with the `dotenv` package like so. 20 | 21 | ```js 22 | // config.js 23 | const dotenv = require("dotenv").config({ 24 | path: `${__dirname}/.env`, 25 | }); 26 | 27 | const database = process.env.DBNAME; 28 | const user = process.env.DBUSER; 29 | const password = process.env.DBPASSWORD; 30 | 31 | module.exports = { 32 | db: { 33 | server: "localhost", 34 | database: database, 35 | user: user, 36 | password: password, 37 | }, 38 | }; 39 | ``` 40 | 41 | **NOTE:** `__dirname` is required because the variables are `undefined` when accessing the `.env` file outside the root folder. 42 | 43 | We can then have one `.env` file for development in the local machine, and one for production on the live server. This way we can just set the variables and not touch the code. 44 | 45 | **NEVER COMMIT THIS FILE. PUT IT IN .gitignore!** 46 | 47 | We can also pass in the variables without a `.env` file and run the script. 48 | 49 | ``` 50 | DBNAME=database DBUSER=root DBPASSWORD=root node server.js 51 | ``` 52 | -------------------------------------------------------------------------------- /topics/dotnet.md: -------------------------------------------------------------------------------- 1 | # .NET Framework 2 | 3 | It's a computing framework for building applications on Windows, and it serves as an environment in which computer programs can run. 4 | 5 | It is composed of: 6 | - **Assemblies**, which are typically `.exe` or `.dll` files that contain compiled code which requires .NET to run. 7 | - **The Common Language Runtime (CLR)**. This is a set of Windows libraries whose job is to run assemblies. It's essentially a Virtual Machine. 8 | - **Class libraries**. A set of object-oriented APIs which can be used by assemblies. 9 | 10 | It's possible for anyone to create a compiler that compiles a language for .NET, but the most common languages that use .NET are C# and VB.NET. 11 | 12 | If you write your code to the framework, you can be sure it will work on anything that the framework says it can run on. In the case of Windows .NET, that means 'any' version of Windows. In the case of .NET Core, that's starting to mean 'any' modern device. 13 | 14 | ### CLR 15 | 16 | It's an application sitting in memory, whose job is to translate IL Code (Intermediate Language) into Machine Code i.e. JIT (Just-in-time-compilation). 17 | 18 | Java's "CLR" is called "JVM". 19 | 20 | C/C++ > Machine Code 21 | Java > ByteCode (JVM) > Machine Code 22 | C# > IL Code (CLR) > Machine Code 23 | 24 | ### .dll 25 | 26 | Basically a module i.e. a collection of reusable code for other programs to call. 27 | 28 | ### .bat 29 | 30 | A script file, equivalent to a Linux shell/bash script. 31 | 32 | ### Class Library 33 | 34 | Applications consist of the building block classes. 35 | 36 | Related classes are organized in containers called Namespaces. 37 | 38 | Namespaces are organized in an Assembly, either an EXE (Executable) or DLL (Dynamically Linked Library) 39 | 40 | When the application is compiled, one or more Assemblies are made. 41 | 42 | # For Development 43 | 44 | 1. .NET contains a large set of programs which you can call through your program. These are the programs which contain simple functions like join two arrays to complex functions like translate voice to text /or recognize red object in a image(image analyses) etc, Provide functionality to make a internet application, mobile application etc, alot of them are provided(you can call those functions from your program). The .NET libraries are soo vast that you can program Robots/Arduino etc to develop signal processing, image analysis, large set of web application frameworks, etc. 45 | 46 | 2. It maintains a common language underneath and allows you to program in different higher level languages like C#, VB, IronPython etc. When you compile it convert to a common language. It provides different set of build tools to develop applications, integrate, add other frameworks, allow others to easily write frameworks, etc. 47 | 48 | # For End User: 49 | 50 | When you develop a program in .NET (or you can say using .NET) to run this program on many other computers you need to have a corresponding .NET framework available on that computer. So you have to install the .NET framework before you run your program. The .NET framework which you install on different computers have all the functionality your program needs but it wont have the tools for compile/build/develop .NET applications (because those are not needed on the end user machines. They also ported this framework to Linux so you can run .NET applications on Linux platform. -------------------------------------------------------------------------------- /topics/electronics/arduino.md: -------------------------------------------------------------------------------- 1 | # Arduino 2 | 3 | **Arduino** is a development board utilizing an **AVR ATMEGA328** MCU (microcontroller). An MCU can't do much unless it's in a circuit. 4 | 5 | The more professional option is to use a separate development board/launchpad for the MCUs. The idea is to plug in the MCU into it, program it, and take it out to be soldered in a circuit, rather than use the whole board like the Arduino. 6 | 7 | Other popular microcontrollers: 8051, PIC, AVR, ARM, MSP 8 | 9 | Microcontrollers have application specific small processing power while microprocessors have general purpose large processing power. 10 | 11 | Microcontrollers have built in RAM, ROM and other peripherals in a single chip. Microprocessors have only the CPU, and other peripherals, RAM, ROM should be connected externally. 12 | 13 | # Programming 14 | 15 | Unlike most previous programmable circuit boards, the Arduino does not need a separate piece of hardware (called a programmer) in order to load new code onto the board – you can simply use a USB cable. 16 | 17 | The Arduino IDE uses a simplified version of C++. 18 | 19 | Arduino basically works by setting something upfront once and then by trapping execution in an infinite loop. 20 | 21 | The code **will not** compile without `setup()` and `loop()`. 22 | 23 | ```c 24 | void setup() { 25 | // Setup code, run once 26 | } 27 | 28 | void loop() { 29 | // Main code, run repeatedly 30 | } 31 | ``` 32 | 33 | # Setup 34 | 35 | We can select the type of board we are working with at tools > board, or add ones with the boards manager. 36 | 37 | We define the way we are connecting to the board via a port at tools > port. It changes each time the board is disconnected. 38 | 39 | # Upload 40 | 41 | The code is compiled and uploaded into the chip via the USB cable. The built-in small LED light will blink in the frequency of the loop to indicate that it's working. 42 | 43 | # Serial Monitor 44 | 45 | We can see what Arduino outputs via tools > serial monitor. If we are getting weird characters, we need to set the **baud** value to the correct one. 46 | 47 | # Pull-up resistor 48 | 49 | Instead of adding resistors manually, we can use the built-in functionality. 50 | 51 | ```c 52 | pinMode(button, INPUT_PULLUP) 53 | ``` 54 | 55 | # digitalWrite vs analogWrite 56 | 57 | `digitalWrite` will set the specified pin to one of two states - HIGH/LOW, which equate to 5v (3.3v on some boards) and ground respectively. 58 | 59 | `analogWrite` can vary by the type of output used. It will set the pin to a periodic high/low signal, where the percentage of the signal spent high is proportional to the value written. Ex. `analogWrite(PIN, 255)`. 60 | 61 | pinMode(buzzerPin, OUTPUT); 62 | 63 | # Simple blinking LED example 64 | 65 | ```c 66 | int LED = 12; 67 | 68 | void setup() { 69 | pinMode(LED, OUTPUT); 70 | } 71 | 72 | void loop() { 73 | digitalWrite(LED, HIGH); 74 | delay(100); 75 | digitalWrite(LED, LOW); 76 | delay(100); 77 | } 78 | ``` 79 | 80 |  81 | 82 | # Cop Car 83 | 84 | ```c 85 | int LED_RED = 12; 86 | int LED_BLUE = 13; 87 | int BUZZER = 10; 88 | 89 | void setup() { 90 | pinMode(LED_RED, OUTPUT); 91 | pinMode(LED_BLUE, OUTPUT); 92 | pinMode(BUZZER, OUTPUT); 93 | } 94 | 95 | void loop() { 96 | tone(BUZZER, 200, 250); 97 | digitalWrite(LED_RED, HIGH); 98 | delay(500); 99 | digitalWrite(LED_RED, LOW); 100 | 101 | tone(BUZZER, 400, 250); 102 | digitalWrite(LED_BLUE, HIGH); 103 | delay(500); 104 | digitalWrite(LED_BLUE, LOW); 105 | } 106 | ``` 107 | -------------------------------------------------------------------------------- /topics/electronics/raspberrypi.md: -------------------------------------------------------------------------------- 1 | # Raspberry Pi 2 | 3 | It's a micro-computer. 4 | -------------------------------------------------------------------------------- /topics/electronics/rfid.md: -------------------------------------------------------------------------------- 1 | # Standards 2 | 3 | | Family | AKA | Frequency | Protocol | Storage | Writable | Reader | 4 | | ------------------- | ---- | --------- | -------------- | ----------- | -------- | -------------- | 5 | | Low Frequency (LF) | RFID | 125 kHz | EM4100 | UID 4 bytes | No | RDM6300, RC522 | 6 | | High Frequency (HF) | NFC | 13.56 MHz | Mifare Classic | UID 4 bytes | 1 KB | PN532 | 7 | 8 | The UIDs are hard-coded by the manufacturer and cannot be changed. 9 | 10 | All cards contain a chip and an antenna. They are passive i.e. get the energy from the reader. 11 | 12 | # Wiegand 13 | 14 | This is a transmission protocol which connects the RFID reader with a controller. 15 | 16 | The Wiegand interface has two data lines, DATA0 and DATA1. These lines are normally held high at 5V. 17 | 18 | - When a 0 is sent, DATA0 drops to 0V for a few µs. 19 | - When a 1 is sent, DATA1 drops to 0V for a few µs. 20 | 21 | There are a few ms between the pulses. 22 | 23 | It transmits the UID in 2 formats: 24 | 25 | - W26 - Transports only first 3 bytes of the UID. 26 | - W34 - Transports the whole UID (4 bytes). Connect brown wire to ground to get this format. 27 | 28 | If the correct UIDs are not transported via serial, the D0 and D1 may need to be swapped. 29 | 30 |  31 | 32 | # Read Wiegand 33 | 34 | ```javascript 35 | function bitCount(int_type) { 36 | let count = 0; 37 | while (int_type) { 38 | int_type &= int_type - 1; 39 | count += 1; 40 | } 41 | return count; 42 | } 43 | 44 | let raw = 0x21a6616; // 10000110100110011000010110 45 | 46 | let FAC_PAR_MASK = 0x2000000; // 10000000000000000000000000 47 | let FACILITY_MASK = 0x1fe0000; // 01111111100000000000000000 48 | let CARD_MASK = 0x1fffe; // 00000000011111111111111110 49 | let CARD_PAR_MASK = 1; // 00000000000000000000000001 50 | 51 | let facility = (raw & FACILITY_MASK) >> 17; 52 | let card = (raw & CARD_MASK) >> 1; 53 | 54 | let fac_par = (raw & FAC_PAR_MASK) >> 25; 55 | // even parity 56 | let fac_par_ok = (bitCount(facility) + fac_par) % 2 == 0; 57 | 58 | let card_par = raw & CARD_PAR_MASK; 59 | // odd parity 60 | let card_par_ok = (bitCount(card) + card_par) % 2 == 1; 61 | 62 | if (fac_par_ok && card_par_ok) { 63 | console.log("Both parity bits ok, successful read."); 64 | console.log("Facility:", facility); 65 | console.log("Card:", card); 66 | } else { 67 | if (!fac_par_ok) console.log("Facility parity check failed!"); 68 | if (!card_par_ok) console.log("Card parity check failed!"); 69 | } 70 | ``` 71 | -------------------------------------------------------------------------------- /topics/excel.md: -------------------------------------------------------------------------------- 1 | # Insert pictures from URL 2 | 3 | This code gets images from URLs and inserts them in the column to the right of the URL. 4 | 5 | 1. Have a column with the image URLs, usually in range `A:A`. Leave an empty column on the right i.e. `B:B`. 6 | 2. Open the Developer/Visual Basic tab. 7 | 3. Paste the below code in a new module. (Insert/Module) 8 | 4. Edit the `Rng` value in the code i.e. the range with image URLs ex. `A1:A100`. 9 | 5. Click run and wait for the images to be populated in the adjacent column i.e. column `B:B`. 10 | 11 | It takes around 2 seconds per image. 12 | 13 | ```vbnet 14 | Sub URLPictureInsert() 15 | Dim xCol As Long 16 | Dim xRg As Range 17 | Dim w As Integer 18 | Dim h As Integer 19 | On Error Resume Next 20 | Set Rng = ActiveSheet.Range("A1:A100") 21 | w = 100 22 | h = 100 23 | For Each cell In Rng 24 | xCol = cell.Column + 1 25 | Set xRg = Cells(cell.Row, xCol) 26 | xRg.ColumnWidth = 20 27 | xRg.RowHeight = 100 28 | ActiveSheet.Shapes.AddPicture Filename:=cell, LinkToFile:=msoFalse, SaveWithDocument:=msoCTrue, Left:=xRg.Left + (xRg.Width - w) / 2, Top:=xRg.Top + (xRg.Height - h) / 2, Width:=w, Height:=h 29 | Next 30 | End Sub 31 | ``` 32 | 33 | # Google Sheets Cell Update Timestamp 34 | 35 | 1. Modify code with corresponding sheet, cells and update cells. 36 | 2. Go to Tools/Script Editor. 37 | 3. Paste the code and click save. 38 | 39 | ```javascript 40 | function onEdit(e) { 41 | var sh = e.source.getActiveSheet(); 42 | var sheets = ['Sheet1']; // Which sheets to run the code. 43 | 44 | // Columns with the data to be tracked. 1 = A, 2 = B... 45 | var ind = [1, 2, 3].indexOf(e.range.columnStart); 46 | 47 | // Which columns to have the timestamp, related to the data cells. 48 | // Data in 1 (A) will have the timestamp in 4 (D) 49 | var stampCols = [4, 5, 6] 50 | 51 | if(sheets.indexOf(sh.getName()) == -1 || ind == -1) return; 52 | 53 | // Insert/Update the timestamp. 54 | var timestampCell = sh.getRange(e.range.rowStart, stampCols[ind]); 55 | timestampCell.setValue(typeof e.value == 'object' ? null : new Date()); 56 | } 57 | ``` -------------------------------------------------------------------------------- /topics/express.md: -------------------------------------------------------------------------------- 1 | # npm mssql 2 | 3 | Connections are expensive. Use them for one time open/close operations. Otherwise, use a pool when executing a series of queries. 4 | 5 | **Async/Await** 6 | 7 | ```Javascript 8 | router.get("/api", async (req, res) => { 9 | 10 | let id = req.query.id; 11 | 12 | try { 13 | const connection = await sql.connect(db); 14 | const request = await connection.request() 15 | 16 | request.input("id", sql.Int, id); 17 | 18 | let query = ` 19 | select * 20 | from products 21 | where id = @id 22 | ` 23 | 24 | let result = await request.query(query) 25 | 26 | res.send(result) 27 | 28 | } catch (err) { 29 | console.log("Error: " + err); 30 | } finally { 31 | sql.close(); 32 | }; 33 | }) 34 | ``` 35 | 36 | **Promise** 37 | 38 | ```js 39 | new sql.ConnectionPool(db) 40 | .connect() 41 | .then((pool) => { 42 | return pool.request().query("SELECT * FROM product"); 43 | }) 44 | .then((result) => { 45 | let rows = result.recordset; 46 | res.setHeader("Access-Control-Allow-Origin", "*"); 47 | res.status(200).json(rows); 48 | sql.close(); 49 | }) 50 | .catch((err) => { 51 | res.status(500).send({ message: "${err}" }); 52 | sql.close(); 53 | }); 54 | ``` 55 | 56 | **Callback** 57 | 58 | ```js 59 | sql.connect(db, function (err) { 60 | if (err) console.log(err); 61 | var request = new sql.Request(); 62 | request.query("SELECT * FROM product", function (err, recordset) { 63 | if (err) console.log(err); 64 | 65 | let rows = recordset.recordsets[0]; 66 | res.send(rows); 67 | sql.close(); // Important 68 | }); 69 | }); 70 | ``` 71 | 72 | # JSON 73 | 74 | JSON is used to transfer data via a string. 75 | 76 | An object from one programming language can be transferred to another by encoding it in JSON and then decoding it, even though they cannot understand each others' objects. 77 | 78 | ```Javascript 79 | // Javascript object literal. 80 | var personObject = { 81 | firstName:"John", 82 | lastName:"Doe", 83 | age:50, 84 | eyeColor:"blue" 85 | }; 86 | 87 | // Convert object to JSON. 88 | var personJSON = JSON.stringify(personObject); 89 | 90 | // personJSON. 91 | { 92 | "firstName":"John", 93 | "lastName":"Doe", 94 | "age":50, 95 | "eyeColor":"blue" 96 | } 97 | 98 | // Convert JSON to object. 99 | JSON.stringify(personJSON); 100 | ``` 101 | -------------------------------------------------------------------------------- /topics/ftp.md: -------------------------------------------------------------------------------- 1 | # File Transfer Protocol (FTP) 2 | 3 | Used to transfer computer files between a remote and a local machine. 4 | 5 | > `FTP` is insecure. Use `SFTP` instead. 6 | 7 | `SFTP` is part of the SSH (Secure Shell) service, which is usually already installed and running on Linux. 8 | 9 | As long as the server has `sshd` running and the user has `SSH` access, you can connect via `SFTP`. 10 | 11 | ### **Server** 12 | 13 | 1. Create an FTP user (just a normal Linux user). 14 | 15 | ```bash 16 | sudo adduser john 17 | ``` 18 | 19 | You can check the existing users with `less /etc/passwd`. 20 | 21 | 2. Add password. 22 | 23 | ```bash 24 | sudo passwd john 25 | ``` 26 | 27 | 3. Limit user access to a specific directory. 28 | 29 | ```bash 30 | sudo usermod -d /home/user/folder john 31 | ``` 32 | 33 | 4. Give read/write permissions (Might not be needed). 34 | 35 | ```bash 36 | sudo chown john:john /home/user/folder 37 | sudo chmod -R 755 /home/user/folder 38 | ``` 39 | 40 | ### **Client** 41 | 42 | You can now access the directory remotely with an `FTP` client. A popular one is Filezilla. 43 | 44 | Just add you server's IP address in the `host` filed, along with the username and password created above. 45 | 46 | Make sure you are using `SFTP` and port `22` (default SSH port) for the connection. It should use it automatically. 47 | -------------------------------------------------------------------------------- /topics/googleapi.md: -------------------------------------------------------------------------------- 1 | # Sheets API 2 | 3 | 1. Go to `console.developers.google.com` 4 | 2. Create a project. 5 | 3. Go to `console.developers.google.com/apis/credentials` and create API key for the project. 6 | 4. Set the sheet to public for the request to work. 7 | 8 | The sheet can be public i.e. `Anyone who has the link can view`, and be only editable privately. This avoids the OAuth part. 9 | 10 | ```javascript 11 | let sheet = "c750833d5021f60a1b8ff8bf0a21bb9dc74cff12"; 12 | let range = "Sheet 1!A:B"; 13 | let apiKey = "6e0ece719a48d5334369bd881b4324aa957e4407"; 14 | 15 | let url = `https://sheets.googleapis.com/v4/spreadsheets/${sheet}/values/${range}?key=${apiKey}`; 16 | 17 | // https://sheets.googleapis.com/v4/spreadsheets/c750833d5021f60a1b8ff8bf0a21bb9dc74cff12/values/Sheet 1!A:B?key=6e0ece719a48d5334369bd881b4324aa957e4407 18 | 19 | fetch(url) 20 | .then((res) => res.json()) 21 | .then((data) => { 22 | console.log(data); 23 | }) 24 | .catch((err) => err); 25 | ``` 26 | 27 | ### Private sheet 28 | 29 | With private user data you would need to use OAuth. 30 | 31 | 1. Go to `console.developers.google.com/apis/library` and pick Sheets. 32 | 2. Configure OAuth. 33 | -------------------------------------------------------------------------------- /topics/googling.md: -------------------------------------------------------------------------------- 1 | # Googling 2 | 3 | These are called advanced search operators. 4 | 5 | ```bash 6 | # Keywords 7 | 8 | "keyword" # Must include keyword 9 | "foo bar baz" # Must include phrase 10 | 11 | -keyword # Must exclude keyword 12 | -foo -bar -baz # Must exclude keywords 13 | 14 | # Content 15 | 16 | intitle: foo # Single 17 | allintitle: foo bar # Multiple 18 | 19 | inurl: foo # Single 20 | allinurl: foo bar # Multiple 21 | 22 | intext: foo # Single 23 | allintext: foo bar # Multiple 24 | 25 | # Specific website 26 | 27 | website.com: query 28 | site:website.com query 29 | link:example.com # Sites linking to example.com 30 | 31 | # Files 32 | 33 | filetype: pdf 34 | ext: pdf 35 | 36 | # Period 37 | 38 | after: 2017 39 | before: 2018 40 | 41 | 2017..2018 # Between dates 42 | 43 | # Utilities 44 | 45 | define: meaning 46 | weather: berlin 47 | map: place 48 | stocks: aapl 49 | ``` 50 | 51 | Google Dorking, also known as Google Hacking, is a technique that utilizes advanced search operators to uncover information on the internet that may not be readily available through standard search queries. 52 | 53 | Examples: 54 | 55 | ```bash 56 | intitle: webcampxp 5 57 | 58 | filetype:env "DB_PASSWORD" 59 | ``` 60 | -------------------------------------------------------------------------------- /topics/graphql.md: -------------------------------------------------------------------------------- 1 | It's a query language for APIs. 2 | 3 | GraphQL solves a people problem, not a technical one. If you don't have the problem of too many people working with the same data model, you don't need GraphQL 4 | 5 | GraphQL sounds like the ORM of HTTP APIs. 6 | 7 | --- 8 | 9 | GraphQL is an alternative to REST API. It's a typed query language. 10 | 11 | It allows flexible querying from the front-end i.e. client. 12 | 13 | It solves the problem of needing **just** a piece of data, without getting all the data from an end-point. 14 | 15 | REST API would handle this for a `GET /user` request with: 16 | 17 | - `GET /user-slim` - Lots of routes and updating. 18 | - `GET /user?data=slim` - The API becomes complex 19 | 20 | GraphQL would handle this with `POST /user` by sending this query expression in the body. 21 | 22 | ```js 23 | { 24 | query { // operation type 25 | user { // operation end-point 26 | name // requested field 27 | age 28 | } 29 | } 30 | } 31 | ``` 32 | 33 | GraphQL **always** uses `POST` because it sends the query expression. 34 | 35 | | REST API | GraphQL | 36 | | ------------------------ | ------------------------- | 37 | | GET | `query` operation type | 38 | | POST, PUT, PATCH, DELETE | `mutation` operation type | 39 | | Routes | Query definitions | 40 | | Controllers | Resolvers | 41 | -------------------------------------------------------------------------------- /topics/javascript/basics.md: -------------------------------------------------------------------------------- 1 | # Hoisting 2 | 3 | Both variable and function declarations are hoisted to the top on code execution, meaning that their order is irrelevant i.e functions can be called before they are declared. 4 | 5 | # Variables 6 | 7 | ```javascript 8 | var a; // Regular. 9 | let c; // Block scoped. 10 | const b; // Immutable. 11 | ``` 12 | 13 | # Functions 14 | 15 | Functions are first class objects - a function is a regular object of type `function`. The function object type has a constructor: `Function`. 16 | 17 | There are several ways to declare a function. 18 | 19 | The difference is how the function interacts with the external components (the outer scope, the enclosing context, object that owns the method, etc) and the invocation type (regular function invocation, method invocation, constructor call, etc). 20 | 21 | ## Function declaration 22 | 23 | **Hoisted**. Available immediately after parsing, before any code is executed. 24 | 25 | The function declaration creates a variable in the current scope with the identifier equal to function name. This variable holds the function object. 26 | 27 | ```javascript 28 | function foo() {} 29 | foo(); 30 | ``` 31 | 32 | Use them when a function expression is not appropriate or when it is important that that a function is hoisted. 33 | 34 | ## Function expression 35 | 36 | **Not hoisted.** Available only after the variable assignment is executed. 37 | 38 | ```javascript 39 | // Named 40 | let bar = function foo() {}; 41 | bar(); 42 | foo(); // undefined 43 | ``` 44 | 45 | Use them when you are doing recursion or want to see the function name in the debugger. 46 | 47 | ```javascript 48 | // Anonymous 49 | let foo = function () {}; 50 | foo(); 51 | 52 | let bar = foo(); 53 | bar(); // Error: not a function. 54 | ``` 55 | 56 | Use them when you want to pass a function as an argument to another function or you want to form a closure. 57 | 58 | ## IIFE - immediately Invoked Function Expression 59 | 60 | ```javascript 61 | (function () { 62 | // ... 63 | })(); 64 | ``` 65 | 66 | Use them for the module pattern. 67 | 68 | ## ES6 69 | 70 | Binds `this` automatically. 71 | 72 | ```javascript 73 | let foo = () => {}; 74 | ``` 75 | 76 | Use them when you want to lexically bind the `this` value. 77 | 78 | ## Function constructor (Avoid this) 79 | 80 | ```javascript 81 | let foo = new Function(); 82 | ``` 83 | 84 | ## Other 85 | 86 | - Use function declaration generators `function* foo(){}` when you want to exit and then re-enter a function. 87 | - Use function expression generators `let foo = function* [name](){}` when you want to exit and then re-enter a nested function. 88 | 89 | ## Function parameters vs arguments 90 | 91 | An argument is the value supplied to the parameter. 92 | 93 | ```javascript 94 | function foo(bar) { 95 | // bar is a parameter 96 | console.log(bar); 97 | } 98 | 99 | foo("baz"); // baz is an argument. 100 | ``` 101 | 102 | # Useful 103 | 104 | ## Truthy / Falsy 105 | 106 | Strings with at least one letter and numbers larger than zero are `truthy`. 107 | 108 | ```javascript 109 | console.log(true && "foo"); // foo 110 | console.log(true && "foo" && 1); // 1 111 | ``` 112 | -------------------------------------------------------------------------------- /topics/javascript/debugging.md: -------------------------------------------------------------------------------- 1 | # Log 2 | 3 | ```js 4 | // Write to console 5 | console.log(); 6 | 7 | // Show DOM element 8 | console.dir(); 9 | 10 | // Display a table. Takes an array of objects. 11 | console.table(array); 12 | ``` 13 | 14 | # Execution 15 | 16 | ```js 17 | // Display the call stack of a function 18 | console.trace(); 19 | 20 | // Track execution time 21 | console.time("point"); // undefined 22 | console.timeEnd("point"); // point: 1337.42 ms 23 | 24 | // Count the number of executions 25 | console.count("foo"); // foo: 1 26 | console.count("foo"); // foo: 2 27 | console.countReset("foo"); // undefined 28 | console.count("foo"); // foo: 1 29 | ``` 30 | 31 | # Memory 32 | 33 | ```js 34 | // Heap size 35 | console.memory; 36 | 37 | // Show memory usage 38 | setInterval(() => { 39 | const used = process.memoryUsage().heapUsed / 1024 / 1024; 40 | console.log(`Script uses ${Math.round(used * 100) / 100} MB`); 41 | }, 1000); 42 | ``` 43 | 44 | # Test 45 | 46 | ```js 47 | // Avoid if-else statements 48 | function greaterThan(a, b) { 49 | console.assert(a > b, { message: "a is not greater than b", a: a, b: b }); 50 | } 51 | 52 | greaterThan(2, 1); // a is not greater than b, a: 2, b: 1 53 | ``` 54 | -------------------------------------------------------------------------------- /topics/javascript/language.md: -------------------------------------------------------------------------------- 1 | # Language 2 | 3 | The complete JavaScript implementation is made up of three distinct parts: 4 | 5 | - The Core (based on ECMAScript spec) 6 | - The Document Object Model (DOM) 7 | - The Browser Object Model (BOM) 8 | 9 | # ECMAScript 10 | 11 | ECMA-262 describes it like this: 12 | 13 | ``` 14 | ECMAScript can provide core scripting capabilities for a variety of host environments, and therefore the core scripting language is specified... apart from any particular host environment. 15 | ``` 16 | 17 | A Web browser is considered a host environment for ECMAScript, but it is not the only host environment. A list of other host environments listed here. 18 | 19 | Apart from DOM and BOM, each browser has its own implementation of the ECMAScript interface. 20 | 21 | # Document Object Model (DOM) 22 | 23 | The Document Object Model (DOM) is an application programming interface (API) for HTML as well as XML. 24 | 25 | The DOM maps out an entire page as a document composed of a hierarchy of nodes like a tree structure and using the DOMAPI nodes can be removed, added, and replaced. 26 | 27 | ### DOM level 1 28 | 29 | Consisted of two modules: the DOM Core, which provided a way to map the structure of an XML-based document to allow for easy access to and manipulation of any part of a document, and the DOM HTML, which extended the DOM Core by adding HTML-specific objects and methods. 30 | 31 | ### DOM Level 2 32 | 33 | Introduced several new modules of the DOM to deal with new types of interfaces: 34 | 35 | - DOM Views — describes interfaces to keep track of the various views of a document (that is, the document before CSS styling and the document after CSS styling) 36 | - DOM Events — describes interfaces for events 37 | - DOM Style — describes interfaces to deal with CSS-based styles 38 | - DOM Traversal and Range — describes interfaces to traverse and manipulate a document tree 39 | 40 | ### DOM Level 3 41 | 42 | Further extends the DOM with the introduction of methods to load and save documents in a uniform way (contained in a new module called DOM Load and Save) as well as methods to validate a document (DOM Validation). In Level 3, the DOM Core is extended to support all of XML 1.0, including XML Infoset, XPath, and XML Base. 43 | 44 | Note that the DOM is not JavaScript-specific, and indeed has been implemented in numerous other languages. For Web browsers, however, the DOM has been implemented using ECMAScript and now makes up a large part of the JavaScript language. 45 | 46 | Other DOMs 47 | 48 | - Scalable Vector Graphics (SVG) 49 | - Mathematical Markup Language (MathML) 50 | - Synchronized Multimedia Integration Language (SMIL) 51 | 52 | # Browser Object Model (BOM) 53 | 54 | Browsers feature a Browser Object Model (BOM) that allows access and manipulation of the browser window. Using the BOM, developers can move the window, change text in the status bar, and perform other actions that do not directly relate to the page content. 55 | 56 | Because no standards exist for the BOM, each browser has its own implementation. 57 | 58 | # Event Loop 59 | 60 | The Javascript runtime only knows of the `heap` and `call stack`. 61 | 62 | The rest of the functionality, like async stuff, is provided in the form of `WebAPIs` by the browser/Node. 63 | 64 | For async operations, the `callback` is offloaded into a separate `queue`, which is emptied by the `event loop` one by one as soon as the `stack` becomes empty. 65 | 66 | Without the `event loop` the stack would be blocked during the whole duration of the async operaiton, basically freezing the app. 67 | 68 |  69 | 70 | Based on [Philip Roberts' talk](https://www.youtube.com/watch?v=8aGhZQkoFbQ). 71 | -------------------------------------------------------------------------------- /topics/libraries-frontend.md: -------------------------------------------------------------------------------- 1 | # Calendar 2 | 3 | https://github.com/fullcalendar/fullcalendar 4 | 5 | https://ui.toast.com/tui-calendar 6 | https://github.com/nhn/tui.calendar 7 | 8 | # React 9 | 10 | https://marmelab.com/react-admin/ 11 | https://github.com/marmelab/react-admin 12 | 13 | https://ant.design/ 14 | https://github.com/ant-design/ant-design/ 15 | -------------------------------------------------------------------------------- /topics/linux/cron.md: -------------------------------------------------------------------------------- 1 | # Troubleshooting 2 | 3 | 1. **LEAVE AN EMPTY NEW LINE AT THE END OF THE FILE!** 4 | 5 | - Cron jobs may fail to execute correctly if there's no newline at the end of the crontab file because the cron daemon expects each line to end with a newline character. If the last line does not end with a newline, the cron daemon might not read it properly, which can result in that job not being executed. 6 | 7 | 2. Not using absolute paths 8 | 9 | ```bash 10 | * * * * * /bin/echo "cron works" >> /tmp/file 11 | ``` 12 | 13 | 3. Not using a PATH variable 14 | 15 | ```bash 16 | PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 17 | * * * * * echo "cron works" >> /tmp/file 18 | ``` 19 | 20 | 4. Not escaping characters 21 | 22 | ```bash 23 | # mysqldump --databases db > /home/user/backup-$(date +%Y%m%d-%H%M%S) 24 | mysqldump --databases db > /home/user/backup-$(date +\%Y\%m\%d-\%H\%M\%S) 25 | ``` 26 | 27 | NOTE: `echo` won't work because `cron` runs in its own shell. 28 | 29 | # Cron 30 | 31 | Each user has his own crontab i.e. cron table i.e table of scheduled processes. 32 | 33 | **List** 34 | 35 | ```bash 36 | # list of tasks for current user 37 | crontab -l 38 | 39 | # list of tasks for specific user 40 | crontab –u username –l 41 | ``` 42 | 43 | **Edit** 44 | 45 | ```bash 46 | # edit crontabs for current user 47 | crontab -e 48 | 49 | # edit tasks for specific user 50 | crontab –u username –e 51 | 52 | # edit tasks for root user 53 | sudo crontab -e 54 | ``` 55 | 56 | **Jobs** 57 | 58 | ```bash 59 | # list of crontabs 60 | sudo less /var/spool/cron/crontabs 61 | 62 | # root systemwide crontab 63 | sudo less /etc/crontab 64 | ``` 65 | 66 | # Format 67 | 68 | **NOTE: Cron doesn't do seconds. Minimum is every minute.** 69 | 70 | ``` 71 | .---------------- minute (0 - 59) 72 | | .------------- hour (0 - 23) 73 | | | .---------- day of month (1 - 31) 74 | | | | .------- month (1 - 12) OR jan, feb, mar, apr... 75 | | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun, mon, tue, wed, thu, fri, sat 76 | | | | | | 77 | * * * * * command to be executed 78 | 79 | * all 80 | , list of values 81 | x-y range of values 82 | /x recurring i.e. every x times 83 | ``` 84 | 85 | **NOTE: The timing doesn't overlap, meaning it happens in both cases, not a combination of the two.** 86 | 87 | ```bash 88 | # Every minute 89 | * * * * * 90 | 91 | # Every hour 92 | 0 * * * * 93 | 94 | # Every 2 hours 95 | 0 */2 * * * 96 | 97 | # Every day @ 23:59 98 | 59 23 * * * 99 | 100 | # Sunday @ 23:59 101 | 59 23 * * 0 102 | 103 | # At every minute past every hour from 7 through 18 on every day-of-week from Monday through Friday 104 | * 7-18 * * 1-5 105 | 106 | # At every 20th minute past hour 22 on day-of-month 1 and 15 107 | */20 22 1,15 * * 108 | 109 | # At 10:15 on every 2nd day-of-month from 1 through 10 and on Friday 110 | 15 10 1-10/2 * 5 111 | 112 | # Every 2 hours between 06:00 and 18:00, on Monday - Friday. 113 | 0 6-18/2 * * 1-5 114 | ``` 115 | -------------------------------------------------------------------------------- /topics/linux/filesystem.md: -------------------------------------------------------------------------------- 1 | # Files 2 | 3 | **On a UNIX system, everything is a file. If something is not a file, it is a process.** 4 | 5 | File extensions are meaningless. They are there for the user's sake. 6 | 7 | Ubuntu is simply a collection (repository) of pre-compiled packages, running over a **kernel** (Big pile of software that knows how to make hardware do stuff). 8 | 9 | ``` 10 | Package = Plain text file > Compilation > Binary (.exe) 11 | ``` 12 | 13 | ## File types 14 | 15 | - **File**. Images, text, config... 16 | - **Directory**. File pointing to files. 17 | - **Link**. Shortcut/Redirect. 18 | - **Pipe**. Use a process output as input for another. 19 | - **Character Device**. Input/Output files Ex. Teminal. 20 | - **Block**. Used for block devices. Ex. Hard Disk. 21 | - **Socket**. Used for Interprocess Communication. 22 | - **Unix Socket**. Local machine only (Superfast). Ex. Nginx communicates with a PHP interpreter. 23 | - **TCP Socket**. Exposed to network (Slower). Ex. Nginx communicates with a website visitor. 24 | 25 | ## Interprocess Communication (IPC) 26 | 27 | Special files like **sockets** that allow processes to communicate with each other without dangerously sharing memory. 28 | 29 | **Sockets** are files where processes can write stuff, and other processes can listen in real time. 30 | 31 | # Filesystem 32 | 33 | ### OS 34 | 35 | ```bash 36 | /boot # Bootloaders - Everything the OS needs to boot. 37 | /run # Runtime - Information stored in RAM i.e. not written to disk. 38 | /sys # System - Kernel interaction. Similar to /run. 39 | /proc # Processes - Pseudo files with information for system processes, created by the kernel. Every process has a directory named by the PID (process ID). Ex. cat /proc/cpuinfo gives CPU info. 40 | ``` 41 | 42 | ### Devices 43 | 44 | ```bash 45 | /dev # Devices ex. mouse - Other programs and drivers use this. 46 | /dev/sda # Hard disk (main). `sda1` would be a partition. 47 | /media # Device mounting (Automatic) - External hard drives, USBs. 48 | /mnt # Device mounting (Manual) 49 | /cdrom # Mounting point for CDs. 50 | ``` 51 | 52 | ### Programs 53 | 54 | ```bash 55 | # System 56 | 57 | /bin # Binaries - Programs like ls, cat, grep... 58 | /sbin # System binaries - Admin only programs. 59 | /lib # Libraries - Used by bin and sbin. 60 | 61 | # User 62 | 63 | /usr # Applications installed and used by the user. 64 | /opt # Optional - Manually installed software from other vendors. 65 | /tmp # Temp - Temporary files ex. auto-saves. 66 | ``` 67 | 68 | ### Configuration 69 | 70 | ```bash 71 | /etc # Etcetera - System wide cofiguration files. 72 | /var # Variable - Files expected to grow in size ex. logs, databases. 73 | ``` 74 | 75 | ### Users 76 | 77 | ```bash 78 | /root # - Home folder for root users. 79 | /home #. Home folders for each user, storing personal files. 80 | ``` 81 | 82 | ### Other 83 | 84 | ```bash 85 | /srv # Service - Web server files accessible by external users. 86 | /snap # Self-contained Ubuntu apps. 87 | ``` 88 | -------------------------------------------------------------------------------- /topics/linux/fzf.md: -------------------------------------------------------------------------------- 1 | # fzf (Fuzzy Finder) 2 | 3 | Download 4 | 5 | ```bash 6 | git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf 7 | ``` 8 | 9 | Install 10 | 11 | ```bash 12 | ~/.fzf/install 13 | ``` 14 | 15 | Add this line to `~/.bashrc`. 16 | 17 | ``` 18 | [ -f ~/.fzf.bash ] && source ~/.fzf.bash 19 | ``` 20 | 21 | # fzf-cd 22 | 23 | Navigate folders with `CTRL + f`. 24 | 25 | Add this to `.bashrc`. 26 | 27 | ```bash 28 | fzf_cd() { 29 | dir=$(find /mnt/c/user/dev/lab \( -name "node_modules" -o -name ".git" -o -name "android" \) -prune -o -type d -print | fzf --no-preview) 30 | cd "$dir" 31 | } 32 | 33 | bind -x '"\C-f": "fzf_cd"' 34 | ``` 35 | -------------------------------------------------------------------------------- /topics/linux/grep.md: -------------------------------------------------------------------------------- 1 | # grep 2 | 3 | ```bash 4 | grep STRING FILE_NAME # Find string in specific file. 5 | grep -r STRING . # Find string in all directory files. 6 | grep -i STRING # Search without case sensitivity. 7 | command | grep "foo" # Search output of a command. 8 | ``` 9 | 10 | # fzf 11 | -------------------------------------------------------------------------------- /topics/linux/gzip.md: -------------------------------------------------------------------------------- 1 | # gzip 2 | 3 | This package creates a `.gz` compressed file, much like `.rar` or `.zip`. 4 | 5 | ## Compression 6 | `gzip <file>` - Compress a file. *Deletes original file*. 7 | `gzip -k <file>` - Compress without deletion. 8 | 9 | `gzip -9 <file>` - Compression quality 1-9. *Default is 5*. 10 | 11 | 12 | ## Extraction 13 | `gzip -d <file>` or `gunzip <file>`- Extract. 14 | -------------------------------------------------------------------------------- /topics/linux/rsync.md: -------------------------------------------------------------------------------- 1 | Transfer files over SSH. 2 | 3 | Only transfer the files that have changes or are missing. Much faster and secure than FTP. 4 | 5 | # Options 6 | 7 | ```bash 8 | -a # Recursion and preserve everything. 9 | -v # Transfer log. 10 | -h # Display the output numbers in a human-readable format. 11 | -e # Specify remote shell. 12 | -W # Copy whole file, without checking for changes. 13 | 14 | --progress # Show the sync progress during transfer 15 | ``` 16 | 17 | # Exclude files/folders 18 | 19 | ``` 20 | rsync -av ./file1 ./folder1 --exclude 'folder1/node_modules/*' user@123.456.789.255:folder/ 21 | ``` 22 | 23 | # Local > Remote 24 | 25 | ```bash 26 | # Transfer everything from the current directory to a new folder in the remote home directory. 27 | rsync -av . user@123.456.789.255:folder/ 28 | 29 | # Transfer folder1 and its content to remote home directory 30 | rsync -av ./folder1 user@123.456.789.255: 31 | 32 | # Transfer everything from folder1 without the folder itself to remote folder2 in remote home directory. 33 | rsync -av ./folder1/ user@123.456.789.255:folder2/ 34 | 35 | # Transfer multiple files and folders. 36 | rsync -av ./file1 ./file2 ./folder1 user@123.456.789.255:folder2/ 37 | 38 | # Another way 39 | rsync -av -e 'ssh' ./folder1/ user@123.456.789.255:~/folder1/ 40 | ``` 41 | 42 | # Remote > Local 43 | 44 | Runs from local 45 | 46 | ```bash 47 | rsync -av user@123.456.789.255:folder/ /path/to/local/storage 48 | ``` 49 | 50 | # Freezing 51 | 52 | When the terminal freezes, fix it with this in a **new** terminal... 53 | 54 | ```bash 55 | while sudo killall -CHLD ssh; do sleep 0.1; done; 56 | ``` 57 | 58 | # Virtual Machine 59 | 60 | ```bash 61 | rsync -av -e "ssh -p PORT_NUMBER" <SOURCE> <DESTINATION>:<PATH> 62 | 63 | rsync -av -e 'ssh -p 3022' . user@127.0.0.1:~/make-this_folder 64 | ``` 65 | 66 | # Backup 67 | 68 | To copy multiple files, the command must be a string. This will copy the content from the locations to the single location the command is called from. 69 | 70 | ```bash 71 | rsync -av -e 'ssh' 'root@123.456.789.255:/etc/nginx/nginx.conf /etc/letsencrypt/keys' . 72 | ``` 73 | 74 | This command will copy the `nginx.conf` file and the letsencrypt folder with the keys. The command must run as root for the keys. 75 | -------------------------------------------------------------------------------- /topics/linux/services.md: -------------------------------------------------------------------------------- 1 | # service 2 | 3 | `service` is an "high-level" command used for starting and stopping services in different unixes and linuxes. 4 | 5 | ```bash 6 | sudo service <service> <command> 7 | 8 | # Commands 9 | status # Shows the status and last lines of log. 10 | start # Starts a service. 11 | stop # Stops a service. 12 | 13 | reload # Re-read the configuration files. 14 | restart # Restart the service and re-read config files. 15 | 16 | # List 17 | service --status-all 18 | ``` 19 | 20 | Depending on the "lower-level" service manager, service redirects to different binaries: 21 | 22 | - For CentOS 7 it redirects to `systemctl`. 23 | - For CentOS 6 it directly calls the relative `/etc/init.d` script. 24 | - In older Ubuntu releases it redirects to `upstart`. 25 | 26 | `service` is adequate for basic service management, while directly calling `systemctl` give greater control options. 27 | 28 | # systemctl 29 | 30 | `systemctl` is a command-line tool that interacts with `systemd`. It is used to control the `systemd` system and service manager. 31 | 32 | ```bash 33 | sudo systemctl <command> <service> 34 | 35 | # Commands 36 | enable # Enable start on BOOT. 37 | disable # Disable start on BOOT. 38 | 39 | # List 40 | systemctl list-units 41 | ``` 42 | 43 | # systemd 44 | 45 | > `systemd` handles initializing everything that needs to launch behind the scenes when starting up Linux. 46 | 47 | Anything that ends in a "d" is a daemon i.e. a process that works in the background. 48 | 49 | Systemd is the daddy of processes. Process ID number 1. It starts all other processes/daemons at boot. It has integrated tools that manage, for example, wifi, bluetooth, suspend/shutdown, etc. 50 | 51 | The original way of starting everything when a linux system boots was to just run each thing, one after another with scripts. 52 | 53 | Systemd started as a more intelligent way of doing things, which could handle starting multiple things at the same time and thought about dependencies - you can't start things that need the network until you've started the network devices, for example. It mostly seemed like a good idea. 54 | 55 | Systemd has since grown considerably, taking over other tasks. This has been controversial. Some people feel that systemd is forcing its way into things that an init system has no business touching. 56 | 57 | So, at it's core Systemd is an init system, which is the first program that runs at boot, it launches all your daemons, and just performs general boot processes. People dislike it because it is getting pretty large, and some worry that it will become the next Xorg, in that it will become a chore to maintain, and it would be difficult to audit, along with Lenart Poeterring (creator of Systemd) being known for dismissing some potential problems. 58 | 59 | This tool is used for managing services (units). 60 | 61 | Service/Daemon is an on-going process that provides a service, usually designed to interact with something outside of it. Ex. web server, monitoring tool, database... 62 | 63 | # journalctl 64 | 65 | Manages logs. 66 | 67 | ```bash 68 | journalctl -u SERVICE # Log from a service. 69 | journalctl --since "10 min ago" # Log from last 10 minutes. 70 | ``` 71 | -------------------------------------------------------------------------------- /topics/linux/ssh.md: -------------------------------------------------------------------------------- 1 | # Install 2 | 3 | ```bash 4 | sudo apt-get install openssh-server 5 | ``` 6 | 7 | # Connect 8 | 9 | ```bash 10 | ssh -p PORT USER@SERVER_IP 11 | 12 | # Execute one command and exit. 13 | ssh -p PORT USER@SERVER_IP ls 14 | ``` 15 | 16 | SSH in Virtual Machine needs a port forwarding rule in network settings for the VM. Name `ssh`, host port `3022`, guest port `22`. 17 | 18 | ```bash 19 | # SSH to local VM via port forwarding. 20 | ssh -p 3022 user@127.0.0.1 21 | ``` 22 | 23 | # sudo command 24 | 25 | ```bash 26 | # It will ask for the root password in the remote machine 27 | ssh -t user@255.255.255.255 "sudo command" 28 | ``` 29 | 30 | # Alias 31 | 32 | ```bash 33 | /etc/ssh/ssh_config # system-wide 34 | ~/.ssh/config # per user (better) 35 | 36 | # Add this in the config. 37 | Host server_name 38 | Port 22 39 | User user 40 | HostName 123.456.789.255 41 | 42 | # Connect with this now. 43 | ssh server_name 44 | ``` 45 | 46 | # SSH with RSA key 47 | 48 | Access servers with a **public/private** key instead of a password. This is a **much** more secure method. 49 | 50 | Transfer the **public** key `id_rsa.pub` to the remote server, in the `~/.ssh/authorized_keys` file, with this command: 51 | 52 | ```bash 53 | ssh-copy-id -i ~/.ssh/id_rsa.pub user@123.456.789.255 54 | ``` 55 | 56 | **If the keys don't exist** on local machine, generate them: 57 | 58 | ```bash 59 | ssh-keygen 60 | 61 | # keys are stored in /home/user/.ssh 62 | ls ~/.ssh 63 | ``` 64 | 65 | The **private** key `id_rsa` stays in the local machine. 66 | -------------------------------------------------------------------------------- /topics/linux/terminology.md: -------------------------------------------------------------------------------- 1 | # Terminology 2 | 3 | - **Relational Database Management System (RDBMS)** - MySQL, SQL Serverm Postgresql 4 | - **schema** - database creation blueprint with column definitions. 5 | - **database** - company_name 6 | - **namespace** - client1.orders, client2.orders... sales.documents, legal.documents... 7 | - **table** - orders, documents... 8 | - **row** 9 | -------------------------------------------------------------------------------- /topics/linux/tmux.md: -------------------------------------------------------------------------------- 1 | # Basic 2 | 3 | ```bash 4 | tmux # Start tmux. 5 | CTRL + B # Command mode. 6 | SHIFT + select # Select/Paste text. 7 | ``` 8 | 9 | # Windows (tabs) 10 | 11 | ```bash 12 | c # New window. 13 | numbers # Change window. 14 | , # Name window. 15 | w # List windows. 16 | . # Move window. Asks for a number. 17 | & # Close window. 18 | CTRL + D # Close window. 19 | ``` 20 | 21 | # Panes (splits) 22 | 23 | ```bash 24 | % # Split horizontally (left/right). 25 | \" # Split vertically (top/bottom). 26 | arrows # Change pane. Resize if holding command. 27 | x # Close pane. 28 | q # Show pane numbers 29 | space # Toggle between layouts 30 | ``` 31 | 32 | # Scrolling 33 | 34 | ```bash 35 | [ # Scrolling mode with arrows or PageUp/PageDown. 36 | CTRL + C # Exit scrolling mode. 37 | ``` 38 | 39 | # Mouse scrolling 40 | 41 | In order to configurate tmux, a `.tmux.conf` file is needed, as it doesn't exist. We can create this with `sudo touch /etc/.tmux.conf`, or `sudo touch ~/.tmux.conf` for a user specific one. 42 | 43 | **.tmux.conf** 44 | 45 | ```bash 46 | # Activate mouse (Scrolling, selecting, re-sizing) 47 | set -g mouse on 48 | 49 | bind-key -T copy-mode-vi MouseDragEnd1Pane send -X copy-pipe-and-cancel "xclip -selection clipboard" 50 | ``` 51 | 52 | **IMPORTANT:** You must reload the configuration. 53 | 54 | ```bash 55 | tmux source-file ~/.tmux.conf 56 | 57 | # Inside tmux (CTRL + B + :) 58 | source-file ~/.tmux.conf 59 | ``` 60 | 61 | # Setup script 62 | 63 | Create a `tmux.sh` file to automate the setup. 64 | 65 | ```bash 66 | # Start a new tmux session 67 | tmux new-session -d \; \ 68 | 69 | # Split the window vertically: left and right 70 | tmux split-window -h \; \ 71 | 72 | # Split the right pane vertically: left and right 73 | tmux split-window -h \; \ 74 | 75 | # Adjust the panes to be of equal width 76 | tmux select-layout even-horizontal 77 | 78 | # Run a script in the first pane (left) 79 | tmux send-keys -t 0 'cd ~/project/app && npm run dev' C-m \; \ 80 | 81 | # Run a script in the second pane (middle) 82 | tmux send-keys -t 1 'cd ~/project/server/nodemon server.js' C-m \; \ 83 | 84 | # Move focus to the third pane (right) 85 | tmux select-pane -t 2 \; \ 86 | 87 | # Attach to the tmux session to see the panes 88 | tmux attach-session 89 | ``` 90 | -------------------------------------------------------------------------------- /topics/logging.md: -------------------------------------------------------------------------------- 1 | Winston, log4js, bunyan are logging libraries. 2 | 3 | The act of persisting the log is called: 4 | 5 | - Winston: Transports 6 | - Bunyan: Streams 7 | - Log4js: Appenders 8 | 9 | In Winston 3, a "transport" is a storage device for your logs, a writable stream i.e. carrying the data from the app to the console or file. 10 | 11 | **Don't go crazy with logging. Use it to know what came in and out of the system. You can figure out almost everything with those two.** 12 | 13 | # Winston 14 | 15 | ```js 16 | ``` 17 | -------------------------------------------------------------------------------- /topics/messageBrokers.md: -------------------------------------------------------------------------------- 1 | Message brokers are also called queues, busses. 2 | 3 | Kafka, RabbitMQ, MQtt 4 | 5 | https://www.youtube.com/watch?v=aj9CDZm0Glc&ab_channel=IBMTechnology 6 | https://www.youtube.com/watch?v=Ch5VhJzaoaI&ab_channel=JamesCutajar 7 | https://www.youtube.com/watch?v=W4_aGb_MOls&ab_channel=HusseinNasser 8 | https://www.youtube.com/watch?v=PzPXRmVHMxI&ab_channel=StephaneMaarek 9 | https://www.youtube.com/watch?v=7rkeORD4jSw&ab_channel=IBMTechnology 10 | -------------------------------------------------------------------------------- /topics/microservices.md: -------------------------------------------------------------------------------- 1 | # Caveat 2 | 3 | > **DO NOT start building new application as microservices!** 4 | 5 | > Micro-\* is largely about separating deployment for big teams. 6 | 7 | Focus on building a modular, decoupled, easy to change application first. 8 | 9 | When we have semi-stable decoupled modules - and there is a real business need - only then we should think about breaking it into microservices. 10 | 11 | The process of breaking down the application into microservices is really nuanced, and to do it right requires a lot of knowledge and experience in managing software architecture. 12 | 13 | > This is what happens when you read all those Kubernetes / orchestration / microservices / highscalability blog posts starting about 3 years ago, and come to the realization that you don't have Google-scale problems... 14 | 15 | Microservices is more of an organizational structure than a software architecture. Basically you more or less HAVE to do Domain Driven Design to separate 'pieces' of the business between many teams. 16 | 17 | As I hear stories about teams using a microservices architecture, I've noticed a common pattern. 18 | 19 | - Almost all the successful microservice stories have started with a monolith that got too big and was broken up 20 | - Almost all the cases where I've heard of a system that was built as a microservice system from scratch, it has ended up in serious trouble. 21 | 22 | This pattern has led many of my colleagues to argue that you shouldn't start a new project with microservices, even if you're sure your application will be big enough to make it worthwhile. 23 | 24 | [Martin Fowler](https://martinfowler.com/bliki/MonolithFirst.html) 25 | 26 | # Microservices 27 | 28 | Developing a single application as a suite of small services, each running its own process and communicating with lightweight mechanisms, often an HTTP resource API. 29 | 30 | Think of it like an organs system, where each organ has a purpose, the organs form a system, which form an organism. 31 | 32 | ``` 33 | Microservice > Container > Virtual Machine > Hypervisor > Server > Rack > Datacenter > Cloud 34 | ``` 35 | 36 | The other thing that I'd like to point out is that a microservices architecture is only great when the application becomes too large and complex. A microservices architecture requires more resources as it has some additional overhead. Start with a monolithic first. 37 | 38 | A microservice can be a complete application including its own UI, business logic and data. **Usually it's just backend and data.** 39 | 40 | Each microservice is a team. 41 | 42 | # Misconceptions 43 | 44 | - _Micro services enable our teams to choose the best programming languages and frameworks for their tasks_. - Reality: It's super expensive to do this. Team size and investment are critical inputs. 45 | 46 | - _Code generation is evil_ - What's important is creating a defined schema that is 100% trusted. 47 | 48 | - _The event log must be the source of truth_. - Events are critical parts of an interface. But it's okay for services to be the system of record for their resources. 49 | 50 | - _Developers can maintain no more than 3 services each._ Wrong metric. 51 | -------------------------------------------------------------------------------- /topics/mobileCordova.md: -------------------------------------------------------------------------------- 1 | # Apache Cordova 2 | 3 | Mobile apps can be created with HTML, CSS and Javascript. 4 | 5 | The mobile app is a website running in a webview, like Electron for desktop. A webview is a wrapper i.e. a shell browser, without the menus, tabs etc. 6 | 7 | The native device features can be accessed through the wrapper, not directly. Also, The UI components automatically adjust to the platform. 8 | 9 | ## History 10 | 11 | - PhoneGap was previously a product of Adobe. 12 | - To keep it open-source always and follow standards, PhoneGap codebase was handed over to Apache. 13 | - At Apache, it got a name change as Cordova. 14 | - And now it’s better known as Apache Cordova. 15 | - Ionic sits on top of Cordova as a UI library with Angular, to give the web app a native feel. 16 | 17 | PhoneGap is paid. 18 | Cordova is open source. 19 | The codebase is the same. 20 | 21 | If you use phonegap/Cordova you are using plain JavaScript (and can therefore choose to add any framework, including Angular, to that) whereas if you're using ionic then you're an AngularJs developer. 22 | 23 | ## Install 24 | 25 | To run Cordova, node is required. NPM is used for intalling Cordova, along with the plarforms and plugins. 26 | 27 | ```bash 28 | sudo npm i cordova -g 29 | ``` 30 | 31 | When the app is compiled, the target platform SDK is required. 32 | 33 | - Adroid Stuido for Android SDK. 34 | - Xcode for iPhone SDK. 35 | 36 | ## Create app 37 | 38 | ```bash 39 | #cordova folder_name package_name app_name 40 | cordova create myApp com.domain.app AppName 41 | ``` 42 | 43 | This will create the following: 44 | 45 | - `config.xml` - Old configuration (Don't use) 46 | - `hooks` - Special build tools go here. 47 | - `package.json` - Configuration 48 | - `platforms` - SKDs are stored here. 49 | - `plugins` - Like node_modules 50 | - `res` - Additional resources, like icons. 51 | - `www` - The web app lives here. 52 | - css 53 | - img 54 | - js 55 | - index.html 56 | 57 | The phone doesn't call the apps by name. It uses a special internal name to reference them. 58 | 59 | Reverse domain name notation is used as the naming convention for the packages. They are based on registered domain names, and are only reversed for sorting purposes. 60 | 61 | For example, if a company making a product called `MyProduct` has the registered domain name `example.com`, they could use the reverse-DNS string `com.example.MyProduct` to describe it. 62 | 63 | Reverse-DNS names are a simple way of reducing name-space collisions, since any domain name is registered by only one party at a time. 64 | 65 | ## Add platform 66 | 67 | ```bash 68 | cordova platform add android 69 | ``` 70 | 71 | ## Emulate app 72 | 73 | This will load the app inside the emulator. You first need to create it with a system image for the target platform with AVD. 74 | 75 | ```bash 76 | cordova emulate android 77 | ``` 78 | 79 | ## Build app 80 | 81 | This will build the app i.e. `.apk` file, which can be installed on an android device. 82 | 83 | ```bash 84 | cordova build android 85 | ``` 86 | -------------------------------------------------------------------------------- /topics/mobilePWA.md: -------------------------------------------------------------------------------- 1 |  2 | 3 | Technology developed by Google in 2015 enables mobile devices to add a website or web application to a smartphone's home screen and be able to interact with it like a native app, which can work offline. 4 | 5 | PWAs use the browser technology from the browser it was installed from. 6 | 7 | Mobile app users spend 87% of time in native apps, compared to 13% in browser apps. 8 | 9 | This happens because: 10 | 11 | - Push notifications help engagement. 12 | - Icons for fast access. 13 | - Access native devices like camera. 14 | - Offline work. 15 | 16 | PWA's live on the web, have native capabilities i.e installable and push notifications. 17 | 18 | A progressive web application (PWA) is a type of application software delivered through the web, built using common web technologies including HTML, CSS and JavaScript. It is intended to work on any platform that uses a standards-compliant browser, including both desktop and mobile devices. 19 | 20 | PWA's offer: 21 | 22 | - Offline work 23 | - Push notifications 24 | - Phone app 25 | 26 | They have no access to the phone capabilities, such as camera. 27 | 28 | Browser > Add to home screen 29 | 30 | To become a PWA, the app needs: 31 | 32 | - Service worker - js program serving as a mediator between the app vs network and cache. 33 | - Manifest - JSON file containing the settings for the phone app (icon, name...). 34 | 35 | Direct deployment. Send the app directly to the user, rather than have them download it from a store. 36 | -------------------------------------------------------------------------------- /topics/mobileiOS.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8483/notes/df1c7ab62a3f0e36a87063bea77eed15c3bd5886/topics/mobileiOS.md -------------------------------------------------------------------------------- /topics/mvc.md: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /topics/networkingDevices.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | Hubs and switches create networks. 4 | Routers connect networks. 5 | 6 | ``` 7 | PC 1 -----| |----- Router 8 | | | 9 | PC 2 -----|----- Router --- Modem -----|----- Router 10 | | | 11 | Phone ----| |----- Router 12 | 13 | ---------------------------------- ------------- 14 | Local network Internet 15 | ``` 16 | 17 | # Connect Networks 18 | 19 | ## **Modem** 20 | 21 | Converts the internet's analog signals to digital ones for your computer, and vice-versa. 22 | 23 | Establishes a connection to your ISP, and bings the internet into your home or business. 24 | 25 | Comes before the router, usually bundled together. 26 | 27 | You can connect directly to the modem, but a router is needed for multiple devices. 28 | 29 | Short for modulator/demodulator. 30 | 31 | ## **Router** 32 | 33 | The **gateway** of a network. 34 | 35 | Routes data from one network to another based on their IP address. 36 | 37 | It determines if the data is for its own network and receives it, or forwards it to another one if it's not. 38 | 39 | Comes after the modem, usually bundled together. 40 | 41 | Passes your internet connection to all your devices via its built in switch for wired connections or access point for wireless ones. 42 | 43 | # Create and expand networks 44 | 45 | These devices do not read IP addresses, only MAC. 46 | 47 | ## **Switch** 48 | 49 | Detects and identifies **specific** devices connected to it. 50 | 51 | Routes a signal to a specific device connected via ethernet, by storing its MAC address. 52 | 53 | Routers have one built in. 54 | 55 | It's a smart hub. 56 | 57 | ## **Hub** 58 | 59 | Only detects devices connected to it. 60 | 61 | Routes a signal to **all** connected devices via ethernet. 62 | 63 | # Drivers 64 | 65 | Drivers act like a translator between the device they control, and the other programs in your system. 66 | 67 | For instance, lets say you want to print "hello world" on a piece of paper. So you type that in to notepad, and click print. 68 | Windows passes the printer driver the document and says "Print this." 69 | The printer driver takes the information it gets, then turns to the printer and says "I want you to print out the following letters 'h' then 'e' then 'l' and so on. 70 | 71 | Except it's all a lot more complicated than that because we don't send individual letters to a printer any more, we send a lot more detailed information about where to put ink or toner down, how to mix and layer ink or toner to get finely detailed pictures to come out clearly, and a lot of printers actually are smart enough to do these things on their own under certain conditions (like printing out pictures stored on a USB drive plugged directly to a printer) 72 | -------------------------------------------------------------------------------- /topics/networkingLayer2LinkMAC.md: -------------------------------------------------------------------------------- 1 | # MAC 2 | 3 | Physical address of a device. 4 | 5 | IP address locates the device, MAC identifies it. 6 | 7 | Devices need it to communicate on the local network. 8 | 9 | They get it with ARP. 10 | 11 | # ARP - Address Resolution Protocol 12 | 13 | Used to resolve IP addresses to MAC addresses. 14 | 15 | The broadcast does not go beyond the router. 16 | 17 | ``` 18 | Device A - Who is 10.0.0.4? I need the MAC address. 19 | 20 | Device B - I am 10.0.0.4. I will send you the MAC address. 21 | ``` 22 | 23 | This is all cached to avoid sending the signal again. 24 | 25 | ``` 26 | arp -a 27 | ``` 28 | 29 | IP addresses can be matched to MAC manually. 30 | 31 | ``` 32 | arp -s 10.0.0.4 90-02-7b-c2-c0-67 33 | ``` 34 | -------------------------------------------------------------------------------- /topics/networkingLayer4TransferTCP.md: -------------------------------------------------------------------------------- 1 | # TCP - Transmission Control Protocol 2 | 3 | TCP is implemented in the operating system. 4 | 5 | All traffic is split up into messages called packets, sent between two computers in a stream, with the addresses of the sender and recipient in each one. 6 | 7 | TCP just provides "envelopes" that can transfer bytes around the network. 8 | 9 | An application protocol assigns structure and meaning to the contents of the envelopes. 10 | 11 | **If you speak English and I send you a letter written in French, you'll still get the letter, but you won't understand it.** 12 | 13 | # Ports 14 | 15 | IP addresses locate devices. Ports locate programs on the devices. 16 | 17 | ```bash 18 | netstat -n 19 | 20 | Proto Local addresses Foreign addresses State 21 | 22 | TCP 92.168.0.12:52913 215.114.85.17:80 ESTABLISHED # HTTP Web server 23 | TCP 92.168.0.12:52920 215.114.85.17:21 ESTABLISHED # FTP server 24 | ``` 25 | 26 | Ports are like "IP addresses" for programs/services we want to use i.e. locating where they are running on a device, which has an actual IP address to locate it. 27 | 28 | | Location | Type | Range | Example | 29 | | :------: | :---------------: | :-------------: | :---------------------------------------------------------: | 30 | | Server | System/Well-known | 0 - 1,023 | 80 (HTTP), 443 (SSL), 25 (SMTP), 21 (FTP) | 31 | | Server | User/Registered | 1,024 - 49,151 | 1433 (MSSQL), 1527 (Oracle), 1102 (Adobe) | 32 | | Client | Dynamic/Private | 49,152 - 65,535 | Termporarily assigned for client while using above services | 33 | 34 | Listening on a port is like waiting for a phone call on a specific phone number. 35 | 36 | Ports let servers distinguish one service from another on the same host and wait for someone to connect. 37 | 38 | Ports are not physical, but logical. 39 | 40 | Ports are always associated with an IP address, allowing programs to exchange data over the network. 41 | 42 | Normally a server has well known ports for it's applications. The client initiates a connection, and it's associated with an arbitrary port on its end. 43 | 44 | **Only one program can listen to a port in a given moment**. Once started, the program can start child processes to listen for multiple connections on the same port i.e. a web server. 45 | 46 | The port range that a normal (non-root) user can listen on is `1024 - 65535`. Root access (including sudo) can listen on ports down to 1. 47 | 48 | If the other side doesn't pick up, an RST (Reset packet) error message is sent back. 49 | -------------------------------------------------------------------------------- /topics/networkingModelOSI.md: -------------------------------------------------------------------------------- 1 | # OSI Model 2 | 3 | OSI/IP : Used to identify the devices corresponding to the protocols , and their relationships, that are involved during this communication 4 | 5 | ## 1. Physical layer 6 | 7 | This is mostly Ethnernet cables i.e. "The wire". It has no intelligence, as the datalink determines how it's used. 8 | 9 | ## 2. Datalink layer 10 | 11 | Transforms the layers above into signals transmitter over the wire, called `frames`. Most environments use Ethernet as the datalink layer. 12 | 13 | IPv4: 14 | 15 | - Media Access Control (MAC) 16 | - Address Resolution Protocol (ARP) 17 | 18 | IPv6: 19 | 20 | - MAC 21 | - Neighbor Discovery (ND) 22 | 23 | ## 3. Network layer 24 | 25 | Maps connectivity between hosts. i.e. "Can I and how do I get to this other host?" 26 | 27 | Provides a consistent interface to network programs. 28 | 29 | A single chunk of network data is called a `packet`. 30 | 31 | The Internet uses the `Internet Protocol (IP)` which gives each host one or more unique IP addresses, so other hosts can find it. 32 | 33 | Network Address Translation (NAT) screws around with the "unique address" rule, but ultimately, you have a globally unique IP address on your or provider's network. 34 | 35 | ## 4. Transport layer 36 | 37 | The data you care about, called `segments`, flows here. 38 | 39 | ### ICMP - Internet Control Message Protocol 40 | 41 | Low-level connectivity messages between hosts i.e. `ping`, re-routing traffic, Datalink layer errors... 42 | 43 | ### TCP - Transmission Control Protocol 44 | 45 | Rich (reliable) transmission of application data between hosts. Has error checking, congestion control, retransmission of lost data. 46 | 47 | ### UDP - User Diagram Protocol 48 | 49 | Simple (unreliable) transmission of application data between hosts. Reliability is handled in the application, rather than layer. Usually video games. 50 | 51 | ## 5. Application layer 52 | 53 | For simplicity and more realistic use, it bundles the OSI layers above it: 54 | 55 | - **Session layer** - open/close transport layer connections. 56 | - **Presentation layer** - Lets programs exchange data. 57 | - **Application layer** - Actual protocol spoken over these connections. 58 | 59 | The `TCP/IP` model calls everything above the transport layer the application layer. It includes protocols like HTTP, SMTP, LDAP... 60 | -------------------------------------------------------------------------------- /topics/networkingOverview.md: -------------------------------------------------------------------------------- 1 | # ELI5 2 | 3 | Create a basic program that sends a string to the specified ip/port. 4 | 5 | Create a second program that listens on that ip/port and prints out any received strings. 6 | 7 | Congratulations you now know how every network works. The rest is security, data verification/validation, optimization. 8 | 9 | # Analogy 10 | 11 | ### **Highway** 12 | 13 | Think of IP as a sort of high-way that allows other protocols to get on and find their way to other computers. TCP and UDP are the "trucks" on the highway, and the "load" they are carrying are protocols such as HTTP, File Transfer Protocol (FTP) and more. 14 | 15 | IP is required to connect all networks; 16 | 17 | TCP is a mechanism that allows us to transfer data safely and 18 | 19 | HTTP which utilizes TCP to transfer its data, is a specific protocol used by Web servers and clients. 20 | 21 | ### **Postal service** 22 | 23 | One might regard TCP or UDP as the equivalent of the US Postal Service, while HTTP is the equivalent of one business letter template. 24 | 25 | If you are writing to an unknown person, as business letter format is a good, generic way to transmit the "WHO, HOW, WHAT, WHEN, AND WHERE" of your message, but it is NOT the only format that is allowed by the USPS. 26 | 27 | That is, if you are writing to a business associate or loved one, you might forgo the formalities and instead go with a more efficient format, like a billing invoice or love letter or greeting card, but the USPS, like TCP or UDP, will still be there for you, carrying the letters back and forth. 28 | 29 | # Models 30 | 31 | The OSI Model is a logical and conceptual model that defines network communication used by systems open to interconnection and communication with other systems. On the other hand, TCP/IP helps you to determine how a specific computer should be connected to the internet and how you can be transmitted between them. 32 | 33 | OSI model helps you to standardize router, switch, motherboard, and other hardware, whereas TCP/IP helps you to establish a connection between different types of computers. 34 | 35 | Each layer handles a very specific task and interacts only with layers directly above or below. When a layer breaks, it takes all the above with it. Always try to specify the problematic layer for better support. 36 | 37 | # OSI 38 | 39 | Textbook 7 layer model - Open Systems Interconnect (OSI) 40 | 41 | 1. Physical 42 | 2. Data Link 43 | 3. Network 44 | 4. Transport 45 | 5. Session 46 | 6. Presentation 47 | 7. Application 48 | 49 | # TCP/IP 50 | 51 | Real-world 5 layer model 52 | 53 | 1. Physical 54 | 2. Datalink 55 | 3. Network 56 | 4. Transport 57 | 5. Application 58 | 59 | # Diagrams 60 | 61 |  62 |  63 |  64 |  65 | -------------------------------------------------------------------------------- /topics/networkingRoles.md: -------------------------------------------------------------------------------- 1 | Every sysadmin, database admin, web admin, developer, and IT professional should understand the basics of networking. 2 | 3 | It's **much** easier to teach a system administrator the basics of networking, than to teach a network administrator the basics of system administration. 4 | 5 | # System Administrators 6 | 7 | Responsible for managing servers i.e. computers, running an OS, whose main task is providing services to other servers or users, rather than the network. 8 | 9 | They should: 10 | 11 | - Learn the basics of networking 12 | 13 | # Network Administrators 14 | 15 | Responsible for managing network equipment, such as routers. 16 | 17 | They should: 18 | 19 | - Learn basics of how servers operate. 20 | - Understand the basics of: 21 | - user access control and privileges 22 | - processes 23 | - services and daemons 24 | - install/remove software 25 | -------------------------------------------------------------------------------- /topics/nodemailer.md: -------------------------------------------------------------------------------- 1 | ```js 2 | const nodemailer = require("nodemailer"); 3 | 4 | async function sendMail() { 5 | try { 6 | let mailOptions = { 7 | from: '"Vendor Name" <info@vendor.com>', 8 | to: ["info@clientOne.com", "contact@clientTwo.com"], 9 | subject: `Message from vendor`, 10 | // text: // plain text body 11 | html: ` 12 | <h1>Some Title</h1> 13 | <br><br> 14 | <p>Some text</p> 15 | `, 16 | }; 17 | 18 | // create reusable transporter object using the default SMTP transport 19 | let transporter = nodemailer.createTransport({ 20 | name: "subdomain.vendor.com", // needed to send to gmail, yahoo 21 | host: "mail.vendor.com", // email provider SMTP server 22 | port: 465, 23 | secure: true, // true for 465, false for other ports 24 | auth: { 25 | user: "info@vendor.com", // has to be the same as mailOptions.from 26 | pass: "emailPassword", 27 | }, 28 | }); 29 | 30 | // send mail with defined transport object 31 | // transporter.sendMail does not return a promise, it uses a callback function. 32 | transporter.sendMail(mailOptions, async (error, info) => { 33 | if (error) { 34 | res.send({ 35 | success: false, 36 | message: "Sending failed.", 37 | }); 38 | } else { 39 | res.send({ 40 | success: true, 41 | message: "Sent mail.", 42 | }); 43 | } 44 | }); 45 | } catch (err) { 46 | console.log("Error: " + err); 47 | } 48 | } 49 | ``` 50 | 51 | # Promise response 52 | 53 | ```js 54 | return new Promise((resolve, reject) => { 55 | transporter.sendMail(mailOptions, (error, info) => { 56 | if (error) { 57 | reject({ 58 | success: false, 59 | type: "error", 60 | message: "Sending failed.", 61 | }); 62 | } else { 63 | resolve({ 64 | success: true, 65 | type: "success", 66 | message: "Sent mail.", 67 | }); 68 | } 69 | }); 70 | }); 71 | ``` 72 | -------------------------------------------------------------------------------- /topics/notifications.md: -------------------------------------------------------------------------------- 1 | Push API is the W3C standard for web push notification protocol. 2 | 3 | Push API is a web-push, unlike a native-push. 4 | 5 | `Push` and `notification` use different, but complementary, APIs: 6 | 7 | - `push` is invoked when a server supplies information to a service worker. 8 | - `notification` is the action of a service worker or web page script showing information to a user. 9 | 10 | Service workers (core for PWAs) are needed for the browsers to handle push notifications. 11 | 12 | 1. Backend endpoint is needed 13 | 2. Clients sends subscription object to server endpoint 14 | 3. Client shows notification 15 | 16 | Running the front end Javascript to subscribe to your notifications, and getting the device token returned. 17 | Granting a client access to your notifications is very simple using Javascript. If a valid push package is returned, access will be granted and a device token is given in a JSON response. A device token is a unique identifier for each Mac that subscribes to the notification service. When sending a notification, the device token determines which Mac the notification will be sent to. 18 | -------------------------------------------------------------------------------- /topics/optimization/algorithms.md: -------------------------------------------------------------------------------- 1 | # Useful Algorithms 2 | 3 | ## Dummy data 4 | 5 | ```javascript 6 | let data = [ 7 | { id: 1, name: "a" }, 8 | { id: 2, name: "b" }, 9 | { id: 3, name: "c" }, 10 | { id: 4, name: "d" }, 11 | { id: 5, name: "e" }, 12 | ]; 13 | ``` 14 | 15 | ## Shuffle array 16 | 17 | ```javascript 18 | function shuffleArray(array) { 19 | for (var i = array.length - 1; i > 0; i--) { 20 | var j = Math.floor(Math.random() * (i + 1)); 21 | var temp = array[i]; 22 | array[i] = array[j]; 23 | array[j] = temp; 24 | } 25 | return array; 26 | } 27 | 28 | let shuffled = shuffleArray(data); 29 | console.log(shuffled); 30 | ``` 31 | 32 | ## Sort array 33 | 34 | ```javascript 35 | // true desc, false asc 36 | let dynamicSort = function (field, reverse, primer) { 37 | let key = primer 38 | ? function (x) { 39 | return primer(x[field]); 40 | } 41 | : function (x) { 42 | return x[field]; 43 | }; 44 | 45 | reverse = !reverse ? 1 : -1; 46 | 47 | return function (a, b) { 48 | return (a = key(a)), (b = key(b)), reverse * ((a > b) - (b > a)); 49 | }; 50 | }; 51 | 52 | let sorted = data.sort(dynamicSort("id", false)); 53 | console.log(sorted); 54 | ``` 55 | -------------------------------------------------------------------------------- /topics/optimization/codeGolf.md: -------------------------------------------------------------------------------- 1 | # Swap numbers 2 | 3 | ```js 4 | [a, b] = [b, a]; 5 | ``` 6 | 7 | # Unique array values 8 | 9 | ```js 10 | let unique = [...new Set(array)]; 11 | ``` 12 | 13 | # Sum 14 | 15 | ```js 16 | array.reduce((accumulator, item) => accumulator + item.value, 0); 17 | ``` 18 | 19 | # Max value of object property in array 20 | 21 | ```js 22 | Math.max(...array.map((object) => object[property])); 23 | ``` 24 | 25 | # Longest string in an array 26 | 27 | ```js 28 | array.reduce((a, b) => (a.length > b.length ? a : b), ""); 29 | ``` 30 | -------------------------------------------------------------------------------- /topics/optimization/comments.md: -------------------------------------------------------------------------------- 1 | # Don't write comments 2 | 3 | ``` 4 | code > comments 5 | ``` 6 | 7 | Comments get bugs like code. When code is updated, usually the comment is not. 8 | 9 | Use comments only when there is some non-obvious code optimization, explaining why the code is weird, or if it references some specific math or algorithm. 10 | 11 | # Write documentation 12 | 13 | Comments = How code works 14 | Documentation = How code is used 15 | 16 | # Use constants 17 | 18 | ```js 19 | // A status of 5 signals message sent 20 | if (status == 5) { 21 | message.markSent(); 22 | } 23 | ``` 24 | 25 | ```js 26 | CONST MESSAGE_SENT = 5 27 | if (status == MESSAGE_SENT) { 28 | message.markSent(); 29 | } 30 | ``` 31 | 32 | # Refactor with constants 33 | 34 | ```js 35 | /* 36 | You can update a message IF the current user is the author of the message and the message was delivered less 5 minutes ago OR if the current user is an administrator. You can also edit the message if the message wasn't delivered yer. 37 | */ 38 | 39 | if ((message.user.id == currentUser.id && (!message.deliveredTime() || datetime.now() - message.deliveredTime() < 300)) || currentUser.type == "administrator") { 40 | message.updateText(text); 41 | } 42 | ``` 43 | 44 | ```js 45 | const FIVE_MINUTES = 5 * 60; 46 | 47 | let userIsAuthor = message.user.id == currentUser.id; 48 | let isRecent = !message.deliveredTime() || datetime.now() - message.deliveredTime() < FIVE_MINUTES; 49 | let userIsAdmin = currentUser.type == "administrator"; 50 | 51 | if ((userIsAuthor && isRecent) || userIsAdmin) { 52 | message.updateText(text); 53 | } 54 | ``` 55 | 56 | ```js 57 | function canEditMessage(currentUser, message) { 58 | const FIVE_MINUTES = 5 * 60; 59 | 60 | let userIsAuthor = message.user.id == currentUser.id; 61 | let isRecent = !message.deliveredTime() || datetime.now() - message.deliveredTime() < FIVE_MINUTES; 62 | let userIsAdmin = currentUser.type == "administrator"; 63 | 64 | return (userIsAuthor && isRecent) || userIsAdmin; 65 | } 66 | 67 | if (canEditMessage(currentUser, message)) { 68 | message.updateText(text); 69 | } 70 | ``` 71 | -------------------------------------------------------------------------------- /topics/optimization/dependencyInjection.md: -------------------------------------------------------------------------------- 1 | https://www.youtube.com/watch?v=J1f5b4vcxCQ 2 | 3 | > A piece of code using another piece of code that is passed in, instead of used directly. 4 | 5 | The act of passing things to be used is called `injection` i.e. We inject the dependent code into the code that uses it. 6 | 7 | **Before** 8 | 9 | ```js 10 | export class Storage(){ 11 | private database: Database 12 | 13 | constructor(){ 14 | this.database = New Database("db.sqlite"); 15 | 16 | this.database.run(` 17 | CREATE TABLE IF NOT EXISTS user ( 18 | id INTEGER PRIMARY KEY, 19 | username TEXT, 20 | group_id INTEGER, 21 | creation_time TIMESTAMP 22 | ) 23 | `); 24 | } 25 | } 26 | ``` 27 | 28 | **After** 29 | 30 | ```js 31 | export class Storage(){ 32 | private database: Database 33 | 34 | constructor(database: Database){ 35 | this.database = database; 36 | 37 | this.database.run(` 38 | CREATE TABLE IF NOT EXISTS user ( 39 | id INTEGER PRIMARY KEY, 40 | username TEXT, 41 | group_id INTEGER, 42 | creation_time TIMESTAMP 43 | ) 44 | `); 45 | } 46 | } 47 | ``` 48 | -------------------------------------------------------------------------------- /topics/optimization/naming.md: -------------------------------------------------------------------------------- 1 | # 1. Don't abbreviate names 2 | 3 | ```js 4 | function relScore(m1, m2) {} 5 | 6 | function movieRelationScore(movie1, movie2) {} 7 | ``` 8 | 9 | # 2. Use Endiannes / Smurfing / Molds 10 | 11 | ```bash 12 | # big-endian = Most significant word FIRST 13 | profitMonthlyMax 14 | 15 | # little-endian = Most significant word LAST 16 | maxMonthlyProfit 17 | ``` 18 | 19 | # 3. Don't use single letters 20 | 21 | ```js 22 | let x = 1; 23 | 24 | let someValue = 1; 25 | ``` 26 | 27 | # 4. Don't put types in the name (Hungarian notation) 28 | 29 | ```c 30 | bool bIsValid; 31 | int32_t iSpeed; 32 | uint32_t uNumUsers; 33 | char szUserName; 34 | ``` 35 | 36 | # 5. Add units to variables. 37 | 38 | ```js 39 | function execute(delay) {} 40 | 41 | function execute(delaySeconds) {} 42 | ``` 43 | 44 | # 6. Refactor if you find yourself using `utils`. 45 | 46 | ```js 47 | // utils.js 48 | function assignDefaults() {} 49 | function relationScore() {} 50 | function moviesOnPage() {} 51 | function topMoviesByRating() {} 52 | function moviesByDirector() {} 53 | function parseCookie() {} 54 | function assignCookie() {} 55 | ``` 56 | 57 | ```js 58 | // movies.js 59 | function assignDefaults() {} 60 | function relationScore() {} 61 | 62 | // pager.js 63 | function moviesOnPage() {} 64 | 65 | // movieCollection.js 66 | function topMoviesByRating() {} 67 | function moviesByDirector() {} 68 | 69 | // cookie.js 70 | function parseCookie() {} 71 | function assignCookie() {} 72 | ``` 73 | -------------------------------------------------------------------------------- /topics/optimization/nesting.md: -------------------------------------------------------------------------------- 1 | # Never nest beyond 3 levels 2 | 3 | ```js 4 | function calculate(bottom, top) { 5 | // One 6 | if (top > bottom) { 7 | // Two 8 | let sum = 0; 9 | 10 | for (let number = bottom; number <= top; number++) { 11 | // Three 12 | if (number % 2 == 0) { 13 | // Four 14 | sum += number; 15 | } 16 | } 17 | 18 | return sum; 19 | } else { 20 | return 0; 21 | } 22 | } 23 | ``` 24 | 25 | # **Methods of denesting** 26 | 27 | - **Extraction** - Move code into a separate function 28 | - **Inversion** - Early termination of conditions 29 | 30 | ```js 31 | // Extraction i.e. Separate function 32 | function filterNumber(number) { 33 | // One 34 | if (number % 2 == 0) { 35 | // Two 36 | return number; 37 | } 38 | return 0; 39 | } 40 | 41 | function calculate(bottom, top) { 42 | // One 43 | 44 | // Inversion i.e. Early termination 45 | if (top < bottom) return 0; 46 | 47 | let sum = 0; 48 | 49 | for (let number = bottom; number <= top; number++) { 50 | // Two 51 | sum += filterNumber(number); 52 | } 53 | 54 | return sum; 55 | } 56 | ``` 57 | -------------------------------------------------------------------------------- /topics/optimization/premature.md: -------------------------------------------------------------------------------- 1 | # Premature Optimization 2 | 3 | > _"Premature optimization is the root of all evil"_ - Donald Knuth 4 | 5 | You're writing code to solve a real world problem. Getting to a solution faster is more important than a fast solution. 6 | 7 | - Macro performance (Design level) - system wide decisions ex. sql vs nosql 8 | - Micro performance (Fine tuning) - modules, functions... 9 | 10 | 1. Have a **real** performance problem. 11 | 2. Make 80% moves (what change leads to an 80% reduction? usually data structures). 12 | 3. Use a profiler to fix hot spots. 13 | 4. Get under the hood (meomry). 14 | 15 | # Quotes 16 | 17 | > A sentence I stole online and sometimes tell my classmates is "If your code doesn't work, we don't care how fast it doesn't work". I think it's a great piece of advice. 18 | 19 | > My data structures and algorithms lecturer said something similar, an anecdote about him replacing a broken algorithm. The exchange was along the lines of 'But your algorithm takes 3 times as long as my algorithm!' 'Yes, but my algorithm gets the right answer' 20 | 21 | > Correctness comes before efficiency. Sometimes people also say “I can make it run a bit faster if it doesn’t have to handle all these edge cases”. Or, in other words, if it doesn’t have to be correct. 22 | 23 | > That's a clever adaptation of the shorter one they use often when training devs: "It's easier to make working code go faster than it is to make fast code work" 24 | 25 | > One lesson that always stuck with me since college was that software engineering doesn’t just have one time-cost. It has three: runtime cost, development time cost, and repair/maintenance cost. Which happen to be a perfect allegory to the performance, velocity, adaptability triangle 26 | -------------------------------------------------------------------------------- /topics/puppeteer.md: -------------------------------------------------------------------------------- 1 | # Install 2 | 3 | ```bash 4 | npm i puppeteer --save 5 | 6 | # This is needed for the dependencies 7 | sudo apt install chromium-browser 8 | ``` 9 | 10 | # Scraping 11 | 12 | 13 | # PDF 14 | 15 | ```javascript 16 | const express = require("express"); 17 | const puppeteer = require('puppeteer') 18 | 19 | var app = express(); 20 | 21 | // Allow requests from all domains and localhost 22 | app.all("/*", function (req, res, next) { 23 | res.header("Access-Control-Allow-Origin", "*"); 24 | res.header( 25 | "Access-Control-Allow-Headers", 26 | "X-Requested-With, Content-Type, Accept" 27 | ); 28 | res.header("Access-Control-Allow-Methods", "POST, GET"); 29 | next(); 30 | }); 31 | 32 | app.get('/pdf/:id', function (req, res) { 33 | 34 | let id = req.params.id; 35 | 36 | async function printPDF() { 37 | const browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'] }); 38 | const page = await browser.newPage(); 39 | await page.goto(`http://localhost:4000/${id}`, { waitUntil: 'networkidle0' }); 40 | const pdf = await page.pdf({ format: 'A4' }); 41 | 42 | await browser.close(); 43 | return pdf 44 | } 45 | 46 | printPDF().then(pdf => { 47 | res.set({ 'Content-Type': 'application/pdf', 'Content-Length': pdf.length }) 48 | res.send(pdf) 49 | }) 50 | 51 | }); 52 | 53 | app.get('/offer', function (req, res) { 54 | 55 | html = `<h1>Hello World!</h1>` 56 | res.send(html) 57 | 58 | }); 59 | 60 | var server = app.listen(4000, function () { 61 | var host = server.address().address; 62 | var port = server.address().port; 63 | console.log("app listening at http://%s:%s", host, port); 64 | }); 65 | ``` 66 | 67 | -------------------------------------------------------------------------------- /topics/reddit.md: -------------------------------------------------------------------------------- 1 | # 1. Create app 2 | 3 | https://old.reddit.com/prefs/apps 4 | 5 | # 2. Install dependencies 6 | 7 | ``` 8 | npm i snoowrap express --save 9 | ``` 10 | 11 | # 3. Scraper 12 | 13 | ```js 14 | var snoowrap = require("snoowrap"); 15 | const express = require("express"); 16 | const app = express(); 17 | const port = 6000; 18 | 19 | // (async () => { 20 | app.get("/", async (req, res) => { 21 | // https://old.reddit.com/prefs/apps/ 22 | const r = new snoowrap({ 23 | userAgent: "A random string.", 24 | clientId: "APP_ID", 25 | clientSecret: "APP_SECRET", 26 | username: "REDDIT_USER", 27 | password: "REDDIT_PASSWORD", 28 | }); 29 | 30 | const subreddit = await r.getSubreddit("cscareerquestions"); 31 | const topPosts = await subreddit.search({ query: "Salary Sharing thread for EXPERIENCED DEVS", time: "all", sort: "new" }); 32 | 33 | console.log("topPosts"); 34 | 35 | let posts = topPosts.filter((post) => post.title.includes("EXPERIENCED DEVS")); 36 | 37 | console.log("posts"); 38 | 39 | let data = []; 40 | 41 | /* 42 | submisson 43 | comments 44 | comment 45 | replies 46 | replies 47 | comment 48 | replies 49 | replies 50 | */ 51 | 52 | for (let i = 0; i < posts.length; i++) { 53 | let post = posts[i]; 54 | let id = post.id; 55 | 56 | let submission = await r.getSubmission(id).expandReplies({ limit: 1, depth: 1 }); 57 | 58 | console.log("submission"); 59 | 60 | let comments = submission.comments; 61 | 62 | comments.forEach((comment) => { 63 | let region = comment.body.split("**")[1]; 64 | 65 | if (!region) return; 66 | 67 | comment.replies.forEach((reply) => { 68 | let foo = { region, permalink: `https://old.reddit.com/${reply.permalink}` }; 69 | 70 | let lines = reply.body.split("\n"); 71 | 72 | lines.forEach((line) => { 73 | let parts = line.split(": "); 74 | let key = ""; 75 | let value = parts[1]; 76 | 77 | if (parts[0].includes("Experience")) key = "experience"; 78 | if (parts[0].includes("Tenure")) key = "tenure"; 79 | if (parts[0].includes("Industry")) key = "industry"; 80 | if (parts[0].includes("Title")) key = "title"; 81 | if (parts[0].includes("Location")) key = "location"; 82 | if (parts[0].includes("Salary")) key = "salary"; 83 | if (parts[0].includes("Total")) key = "total"; 84 | 85 | if (key && value) foo[key] = value; 86 | }); 87 | 88 | data.push(foo); 89 | }); 90 | }); 91 | } 92 | 93 | console.log(data); 94 | 95 | console.log("done"); 96 | 97 | res.send(data); 98 | }); 99 | 100 | app.listen(port, () => { 101 | console.log(`Example app listening at http://localhost:${port}`); 102 | }); 103 | // })(); 104 | ``` 105 | -------------------------------------------------------------------------------- /topics/serverless.md: -------------------------------------------------------------------------------- 1 | Where microservices break up monolithic apps... Serveless breaks up microservices into independent functions. 2 | 3 | # AWS Lambda/Serverless 4 | 5 | ```bash 6 | # Install 7 | npm install -g serverless 8 | 9 | # Initialize (Setup AWS credentials) 10 | serverless 11 | 12 | # Deploy code 13 | serverless deploy 14 | 15 | # Call API 16 | curl https://pv2vfelg5j.execute-api.us-east-1.amazonaws.com/dev/api 17 | ``` 18 | 19 | # Code 20 | 21 | ```bash 22 | npm install express aws-serverless-express 23 | ``` 24 | 25 | **api.js** 26 | 27 | ```js 28 | const express = require("express"); 29 | 30 | router.get("/", (req, res) => { 31 | res.status(200).json({ foo: "bar" }); 32 | }); 33 | 34 | module.exports = router; 35 | ``` 36 | 37 | **app.js** 38 | 39 | ```js 40 | const express = require("express"); 41 | const cors = require("cors"); 42 | 43 | let api = require("./api"); 44 | 45 | const app = express(); 46 | 47 | app 48 | .use(cors()); 49 | .use(express.json()) 50 | .use(api); 51 | 52 | module.exports = app; 53 | ``` 54 | 55 | **handler.js** 56 | 57 | ```js 58 | const awsServerlessExpress = require("aws-serverless-express"); 59 | const app = require("./app"); 60 | 61 | const server = awsServerlessExpress.createServer(app); 62 | 63 | exports.handler = (event, context) => { 64 | return awsServerlessExpress.proxy(server, event, context); 65 | }; 66 | ``` 67 | 68 | **serverless.yml** 69 | 70 | ```yml 71 | service: api 72 | 73 | provider: 74 | name: aws 75 | runtime: nodejs12.x 76 | 77 | functions: 78 | app-api: 79 | handler: handler.handler 80 | events: 81 | - http: 82 | path: / 83 | method: get 84 | cors: true 85 | ``` 86 | -------------------------------------------------------------------------------- /topics/sheetjs.md: -------------------------------------------------------------------------------- 1 | ```html 2 | <!DOCTYPE html> 3 | <html> 4 | <head> 5 | <title>SheetJS Demo</title> 6 | <meta charset="UTF-8" /> 7 | <script src="https://oss.sheetjs.com/sheetjs/xlsx.full.min.js"></script> 8 | </head> 9 | 10 | <body> 11 | <div id="app"></div> 12 | <script type="module" src="/app.min.js"></script> 13 | </body> 14 | </html> 15 | ``` 16 | 17 | ```js 18 | let excelButton = document.getElementById("button-excel"); 19 | excelButton.addEventListener("click", () => { 20 | let now = new Date(); 21 | let timestamp = `${now.toISOString().split("T")[0]} ${now.toLocaleTimeString("en-GB")}`; // 2020-04-18 14_03_05 22 | activitiesTable.download("xlsx", `Exel report - ${timestamp}.xlsx`); 23 | }); 24 | ``` 25 | -------------------------------------------------------------------------------- /topics/startup/marketingFacebookPixel.md: -------------------------------------------------------------------------------- 1 | Pixels don't work without adding permissions to them. 2 | -------------------------------------------------------------------------------- /topics/startup/marketingGoogleTagManager.md: -------------------------------------------------------------------------------- 1 | [Source](https://youtu.be/DiAgCihHW58) 2 | 3 | Without coding: 4 | 5 | 1. Embed/inject javascript code. 6 | 2. Track events across many websites. 7 | 8 | Super useful, even if you are a developer. 9 | 10 | # Account 11 | 12 |  13 | 14 | Container = Property in Google Analytics 15 | 16 | Create a separate container for each website. 17 | 18 | # Components 19 | 20 |  21 | 22 | - **Event** - An actual generic event like button click. 23 | - **Tag** - Micro code injections/embeds. 24 | - Any javascript code, without actually coding it. 25 | - Google Analytics. 26 | - Facebook Pixel. 27 | - Chatbot... 28 | - Can send event meta-data to 3rd parties. Paired with Google Analytics properties. 29 | - Google Analytics GA4 Event - Dedicated for Google Analytics. 30 | - ~~Google Tag - General purpose, works for other Google services.~~ 31 | 32 | ``` 33 | tags > new > tag configuration > Google Analytics > Google Analytics GA4 Event > Insert Tag ID (found in Google Analytics data stream) 34 | 35 | triggering > Initialization - All Pages 36 | ``` 37 | 38 | - **Trigger** - Tags are code just sitting there, waiting for directions what to do i.e. listen for the desired events to activate the tag script, while matching the conditions. Ex. specific button (.class_name). Triggers are not enabled by default, they need to be created, and then linked to tags. 39 | 40 | ``` 41 | triggers > new > trigger configuration > trigger type 42 | ``` 43 | 44 | - **Variables** - Static content (URL pattern) or dynamically set values (order total). 45 | - **Templates** - Custom tags with specific fields for them. 46 | 47 | Triggers and tags work together. Triggers listen for the specific signal, and the tag then performs the specific function. 48 | 49 | # Settings 50 | 51 | Enable all link clicks (not available by default). You can add other data (variables) to tags as well. 52 | 53 | ``` 54 | Variables > configure > clicks (tick checkboxes) 55 | ``` 56 | 57 | Put the measurement ID (data stream) into a variable. 58 | 59 | # Workflow 60 | 61 | 1. Configure tags, triggers, variables. 62 | 2. Click preview (tag assistant) to verify events fire. 63 | 3. Check Google Analytics DebugView to verify events fired. 64 | 4. Submit and name the container configuration version. 65 | 66 | # Manual event sending 67 | 68 | 1. Ask developer to push a custom event to the Google Analytics data layer. 69 | 70 | ```js 71 | gtag("event", "sign_up"); 72 | ``` 73 | 74 | 2. Check if the event is avaliable in the Tag Manager preview. 75 | 3. Create a custom trigger to use the custom event as a triggering condition. 76 | 4. Create a tag to send the event to Google Analytics, link it to the custom trigger. 77 | 5. Verify the event is sent via Google Analytics DebugView 78 | -------------------------------------------------------------------------------- /topics/startup/marketingLandingPage.md: -------------------------------------------------------------------------------- 1 | [SOURCE](https://youtu.be/g3cmNDlwGEg) 2 | 3 | # 1. Navigation 4 | 5 |  6 | 7 | Keep it simple, people are used to this layout. Make it sticky as you scroll. Logo, few links and CTA button. 8 | 9 | # 2. Hero 10 | 11 | 1. **Headline** - What do you do? The big result your clients get. 12 | 2. **Sub-headline** - How do you make their lives better? 13 | - What the service is 14 | - Who is it for 15 | - How it's delivered 16 | 3. **Call to action (CTA)** - What do they need to do to get it? Be really clear what happens when it's clicked. 17 | 4. **Image** - Ideally show your client in their happy state. "This could be you if you use our service" 18 | 19 | Clear and direct, don't be cute or clever. 20 | 21 |  22 | 23 | # 3. Problem 24 | 25 | What does your sevice fix? 26 | 27 |  28 | 29 | It isn't about being negative, but showing that you unserstand them. 30 | 31 |  32 | 33 | # 4. Solution 34 | 35 | Focus on how you can help, not just who you are. 36 | 37 | - Briefly highlight your qualifications and experience. 38 | - Share a personal story how you understand their problem. 39 | - Really short explanations how your service solves their problem. 40 | - Showing your face here really helps. 41 | 42 |  43 | 44 |  45 | 46 | # 5. Benefits 47 | 48 | Show exactly what your users get. Focus on results, not just features. 49 | 50 | Each benefit should paint a picture how your client's life is going to improve. 51 | 52 | Benefit structure: 53 | 54 | - Title 55 | - Short description 56 | - Image 57 | 58 |  59 | 60 |  61 | 62 | # 5. Action plan 63 | 64 | Don't skip this! 65 | 66 |  67 | 68 |  69 | 70 | # 6. Testimonials 71 | 72 | Prove your worth. 73 | 74 | Testimonial structure: 75 | 76 | - Short headline 77 | - Description. 78 | - Before I was struggling with X. 79 | - Now after using the service, I've achieved Y, and I feel Z. 80 | - Picture of client 81 | - 5-star graphic 82 | 83 | Show 3rd party review website scores. 84 | 85 |  86 | 87 | # 7. FAQ 88 | 89 | Handle objections, by turning them into questions, and answering them. 90 | 91 |  92 | 93 | # 8. Call to action (CTA) 94 | 95 | Repeat the same CTA from the hero. 96 | 97 |  98 | -------------------------------------------------------------------------------- /topics/startup/startupProblemSolving.md: -------------------------------------------------------------------------------- 1 | # XY Problem 2 | 3 | The XY problem is a communication problem encountered in help desk, technical support, software engineering, or customer service situations where the question is about an end user's attempted solution (X) rather than the root problem itself (Y or Why?). 4 | 5 | The XY problem obscures the real issues and may even introduce secondary problems that lead to miscommunication, resource mismanagement, and sub-par solutions. The solution for the support personnel is to ask probing questions as to why the information is needed in order to identify the root problem Y and redirect the end user away from an unproductive path of inquiry. 6 | 7 | # Elon Musk's 5 step process 8 | 9 | [Elon Musk on problem-solving](https://youtu.be/CDZ9REOh2xA) 10 | 11 | First priniples critical thinking 12 | 13 | > Whatever the people at the front-lines are doing, try to do it yourself a couple of times. 14 | 15 | ## 1. Ask the right question 16 | 17 | Question the requirements. Make them simpler. 18 | 19 | No matter how good the requirements are, they are still dumb to some degree. 20 | 21 | You start here because you can get the perfect answer to the wrong question. 22 | 23 | Try to make the question the least wrong possible. 24 | 25 | ## 2. Try to delete the process 26 | 27 | If you're not forced to put back 10% in, you are not deleting enough. 28 | 29 | People think they've succeeded by not being forced to put things back, but in fact they are overly conservative and kept things in that should have been deleted. 30 | 31 | People are afraid to do this because they remember the last time they had to put things back, but what happened was they over-corrected by leaving too much stuff in and over-complicating things. 32 | 33 | Deliberately delete more than you should. 34 | 35 | ## 3. Optimize/simplify it 36 | 37 | Go back to step 1 and try to improve the process. 38 | 39 | The most common engineering mistake is to optimize something that shouldn't exist. 40 | 41 | ## 4. You can always speed things up 42 | 43 | No matter how good the process it, it can always be done faster. 44 | 45 | Even if you don't change the process, you can use better machines, people... 46 | 47 | ## 5. Automate it 48 | 49 | Find a way to automate the process. 50 | -------------------------------------------------------------------------------- /topics/statistics.md: -------------------------------------------------------------------------------- 1 | # Probability 2 | 3 | Probability of happening 4 | ``` 5 | 1 / possible outcomes 6 | 1 / 4 = 25% 7 | ``` 8 | 9 | Happening in a row (3 times) 10 | ``` 11 | Probability ^ instances 12 | 0.25 ^ 3 = 0.0156 ~ 1.5% 13 | ``` 14 | 15 | **NOT** happening 16 | ``` 17 | 1 - probability 18 | 1 - 0.25 = 0.75 19 | ``` 20 | 21 | **NOT** happening in a row (15 times) 22 | ``` 23 | Probability NOT ^ instances 24 | (1 - 0.25) ^ 15 25 | 0.75 ^ 15 = 0.133 ~ 13% 26 | ``` 27 | 28 | Happening after **NOT** happening (15 times) 29 | ``` 30 | 1 - (1 - 0.25) ^ 15 31 | 1 - 0.75 ^ 15 32 | 1 - 0.133 = 0.867 ~ 87% 33 | ``` 34 | 35 | -------------------------------------------------------------------------------- /topics/tagify.md: -------------------------------------------------------------------------------- 1 | ```html 2 | <!DOCTYPE html> 3 | <html> 4 | <head> 5 | <title>Tagify Demo</title> 6 | <meta charset="UTF-8" /> 7 | 8 | <script src="https://cdnjs.cloudflare.com/ajax/libs/tagify/3.21.0/tagify.min.js" integrity="sha512-YKRkB65j3s2S05MOobXwnLQvUw0asCy+5Dt8aIVK6rPqI4RxJmGLLExUObcGjn0K8/kQDNXXwSeLFkqXwXYtfA==" crossorigin="anonymous"></script> 9 | <script src="https://cdnjs.cloudflare.com/ajax/libs/tagify/3.21.0/tagify.polyfills.min.js" integrity="sha512-SvqV96Tz5KzauECowu+oMXacoJXm29uMw9GBl3sNW8nQZXxnLUzFP27dGn9SOSFuugSmXL6PedEbWdijxPkDVg==" crossorigin="anonymous"></script> 10 | <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tagify/3.21.0/tagify.min.css" integrity="sha512-91wa7heHLbuVdMrSXbWceVZva6iWDFlkFHnM+9Sc+oXFpTgw1FCqdnuaGBJfDVuNSNl0DwDmeGeJSORB0HyLZQ==" crossorigin="anonymous" /> 11 | </head> 12 | 13 | <body> 14 | <script src="src/index.js"></script> 15 | </body> 16 | </html> 17 | ``` 18 | 19 | ```js 20 | let tagsInput = document.createElement("input"); 21 | tagsInput.className = "activity-entity-tags"; 22 | document.body.append(tagsInput); 23 | 24 | let tags = [ 25 | { 26 | id: 1, 27 | value: "foo 1", 28 | searchBy: "foo 1", 29 | }, 30 | { 31 | id: 2, 32 | value: "bar 2", 33 | searchBy: "bar 2", 34 | }, 35 | { 36 | id: 3, 37 | value: "baz 3", 38 | searchBy: "baz 3", 39 | }, 40 | ]; 41 | 42 | let tags = new Tagify(tagsInput, { 43 | templates: { 44 | tag: function (tagData) { 45 | try { 46 | return ` 47 | <tag 48 | title='${tagData.value}' 49 | contenteditable='false' 50 | spellcheck="false" 51 | class='tagify__tag ${tagData.class ? tagData.class : ""}' 52 | ${this.getAttributes(tagData)} 53 | > 54 | <x title='remove tag' class='tagify__tag__removeBtn'></x> 55 | <div> 56 | <span class='tagify__tag-text'>${tagData.value}</span> 57 | </div> 58 | </tag> 59 | `; 60 | } catch (err) { 61 | console.log(err); 62 | } 63 | }, 64 | 65 | dropdownItem: function (tagData) { 66 | try { 67 | return ` 68 | <div 69 | class='tagify__dropdown__item ${tagData.class ? tagData.class : ""}' 70 | style="font-size: 8pt;" 71 | > 72 | <span class="tags-dropdown-value">${tagData.searchBy}</span> 73 | </div> 74 | `; 75 | } catch (err) { 76 | console.log(err); 77 | } 78 | }, 79 | }, 80 | enforceWhitelist: true, 81 | whitelist: tags, 82 | backspace: false, 83 | editTags: false, 84 | delimiters: ";", 85 | dropdown: { 86 | // fuzzySearch: true, 87 | maxItems: 500, 88 | // searchKeys: ["searchBy"], 89 | enabled: 0, // suggest tags after a single character input, zero i show on focus 90 | classname: "extra-properties", // custom class for the suggestions dropdown 91 | }, // map tags' values to this property name, so this property will be the actual value and not the printed value on the screen 92 | }); 93 | 94 | tags.addTags([tags[0]]); 95 | 96 | tags.on("dropdown:show", (e) => { 97 | console.log("showing"); 98 | }); 99 | 100 | tags.on("dropdown:select", (e) => { 101 | console.log("selecting"); 102 | console.log(e.detail); 103 | }); 104 | ``` 105 | -------------------------------------------------------------------------------- /topics/testing/testing.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | The idea is to automate the manual testing of code, with code. 4 | 5 | This requires an initial time investment, which is quickly paid back in the time saved by making sure the application is stable. 6 | 7 | # Test types 8 | 9 | - **Unit tests** 10 | Testing single functions with no dependencies (thousands). 11 | 12 | - **Integration test** 13 | Testing single functions with dependencies i.e. functions that call other functions (couple). Does the combination of single functions work? 14 | 15 | - **End-to-end (E2E) / UI test** 16 | Testing by simulating a literal manual UI interaction (few). 17 | 18 | # Setup 19 | 20 | The following is needed to test code. 21 | 22 | 1. **Test runner** - Executes tests and summarizes results. Ex. `Jest`, `Mocha`. 23 | 2. **Assertion library** - Define testing logic and conditions. Ex. `Jest`, `Chai`. 24 | 3. **Headless browser** - E2E testing - Simulate browser interactions. Ex. `Puppeteer`, `Cypress`. 25 | 26 | `Jest` is both a test runner and an assertion library. 27 | -------------------------------------------------------------------------------- /topics/uiux.md: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /topics/vagrant.md: -------------------------------------------------------------------------------- 1 | # Vagrant 2 | 3 | Vagrant is used to avoid the tedious provisioning of Virtual Machines. Instead of manually installing the OS for every machine, VMs can be spun up instantly by downloading an image (box) from the hub, and running it. 4 | 5 | Vagrant **is not** like Docker. Vagrant is used to start VMs fast, while Docker is used to containerize packages within the VMs. Vagrant avoids installing an OS, Docker avoids installing packages i.e. they just run them. This significantly speeds things up by allowing to quickly create and destroy whole environments. 6 | 7 | In other words, use Vagrant for just the OS and Docker install, and run everything else as a Docker container. 8 | 9 | **Host** = Main Machine. **Guest** = Virtual Machine. 10 | 11 | ## Install 12 | `wget "URL"` - Download Vagrant. 13 | `sudo dpkg -i FILENAME` - Install Vagrant. 14 | `sudo apt-get install virtualbox` - Download VirtualBox. 15 | 16 | ## Virtual Machine 17 | `vagrant box add BOX_NAME` - Download a box. 18 | `vagrant init BOX_NAME` - Create Vagrantfile i.e. VMs live here. 19 | `vagrant up` - Start a box (VM). 20 | -------------------------------------------------------------------------------- /topics/vm.md: -------------------------------------------------------------------------------- 1 | # Virtualbox 2 | 3 | 1. Create VM. 4 | 2. Mount and install Guest Additions. 5 | 3. **Reboot.** 6 | 4. Add clipboard settings. 7 | 5. Add host shared folder. It is under `/media/user/sf_folder_name`. 8 | 6. `sudo adduser username vboxsf` to access shared folder. 9 | 7. **Reboot.** 10 | -------------------------------------------------------------------------------- /topics/vue.md: -------------------------------------------------------------------------------- 1 | # Hello World 2 | 3 | ```html 4 | <script src="https://cdn.jsdelivr.net/npm/vue"></script> 5 | 6 | <div id="app"> 7 | <p>{{ title }}</p> 8 | </div> 9 | ``` 10 | ```javascript 11 | new Vue({ 12 | el: "#app", 13 | data: { 14 | title: "Hello World!" 15 | } 16 | }); 17 | ``` 18 | `Vue` instances are at the core of every Vue app, as they control their own HTML template rendered to the screen. 19 | 20 | # Component Anatomy 21 | 22 | All the code is encapsulated in the component. 23 | 24 | **Output - HTML** 25 | ```html 26 | <template> 27 | <div class="user"> 28 | <h1>{{ user.name }}</h1> 29 | </div> 30 | </template> 31 | ``` 32 | 33 | **Functionality - Javascript** 34 | 35 | A default object is exported i.e. component with a name of "User". The `data()` method returns the state of the component. 36 | ```html 37 | <script> 38 | export default { 39 | name: "User", 40 | data() { 41 | return { 42 | user: { name: "Foo" } 43 | } 44 | } 45 | } 46 | </script> 47 | ``` 48 | 49 | **Style - CSS** 50 | ```html 51 | <style scoped> 52 | h1 { 53 | font-size: 2 rem; 54 | } 55 | </style> 56 | ``` 57 | 58 | The main page served is `index.html` located in the `public` folder. 59 | 60 | The entry point for a vue app is `main.js`, located in `src`. There we import the `Vue` app object (where we mount the instance to the `index.html`), and the `App` component. 61 | 62 | # Install 63 | 64 | ```bash 65 | sudo npm i -g vue 66 | 67 | vue --version 68 | ``` 69 | 70 | The framework can also be referenced with a CDN. 71 | 72 | # Vue-CLI 73 | 74 | Qucik SPA scaffolding. It provides build setups for a modern frontend workflow, with hot-reload, lint-on-save, and production-ready builds. 75 | 76 | ```bash 77 | vue create app-name 78 | 79 | cd app-name 80 | nom run serve 81 | ``` 82 | 83 | Chrome extension for debugging: Vue.js Devtools 84 | VS Code Syntax highlighting: Vetur 85 | 86 | # vue-router 87 | 88 | **Installing it overwrites the `App.vue` file**s 89 | 90 | # vuex 91 | 92 | State management library similar to Redux. -------------------------------------------------------------------------------- /topics/wasm.md: -------------------------------------------------------------------------------- 1 | Native apps, distributed in the browser. 2 | 3 | Run "almost machine" code in the browser. 4 | 5 | Lets browsers compete with app stores and installers. 6 | 7 | Write C++, Rust... Compile it to WebAssembly... Run the code as a "web app". 8 | 9 | You can play video games directly in the browser. 10 | 11 | Ex. Open Photoshop in the browser, and send a link of the current project to someone to continue working. No sharing of files and installations. -------------------------------------------------------------------------------- /topics/webpack.md: -------------------------------------------------------------------------------- 1 | Webpack is a bundler, which combines many javascript files into a single bundle file. 2 | 3 | It also uglifies (shortens identifier names) and minifies (gets rid of whitespace) the code. 4 | 5 | ```bash 6 | sudo npm install webpack webpack-cli --save-dev 7 | ``` 8 | 9 | ## Simple Default Example 10 | 11 | **Webpack needs an `src` directory with the entry `index.js` file.** 12 | 13 | Without this, we get `ERROR in Entry module not found: Error: Can’t resolve ‘./src’ in 'folder'`. The entry point can be changed in a `webpack.config.js` file. 14 | 15 | We need to add a webpack scripts in `package.json`, which gets all the dependencies from `./src/index.js`, and bundles all the code into a `./dist/main.js` file. 16 | 17 | ```json 18 | { 19 | "scripts": { 20 | "build": "webpack" 21 | }, 22 | "devDependencies": { 23 | "webpack": "4.x.x" 24 | } 25 | } 26 | ``` 27 | We then simply run 28 | ```bash 29 | npm run build 30 | ``` 31 | 32 | These can also be used in `package.json`, where production minifies, and development doesn't. 33 | ```json 34 | "scripts": { 35 | "dev": "webpack --mode development", 36 | "build": "webpack --mode production" 37 | } 38 | ``` 39 | 40 | ## Configuration 41 | 42 | Instead of a `package.json` script, we can use a detailed `webpack.config.js` configuration file, which can be generated with the command below and by answering questions. 43 | 44 | ```bash 45 | webpack init 46 | ``` 47 | Example : 48 | 1. Will your application have multiple bundles? **No** 49 | 2. Which module will be the first to enter the application? [example: './src/index.js'] **./src/index.js** 50 | 3. Which folder will your generated bundles be in? [default: dist] **Enter** 51 | 4. Are you going to use this in production? **No** 52 | 5. Will you be using ES2015 (ES6)? **Yes** 53 | 6. Will you use one of the below CSS solutions? **No** 54 | 7. Name your `webpack.[name].js`? [default: 'config'] **Enter** 55 | 56 | This will install: 57 | - webpack-cli 58 | - uglifyjs-webpack-plugin 59 | - babel-core 60 | - babel-loder 61 | - babel-preset-env 62 | - webpack 63 | 64 | It will also generate the `webpack.config.js` file: 65 | ```javascript 66 | const webpack = require("webpack"); 67 | const path = require("path"); 68 | 69 | const UglifyjsJSPlugin = require("uglifyjs-webpack-plugin"); 70 | 71 | module.exports = { 72 | entry: './src/index.js', 73 | output: { 74 | filename: '[name].bundle.js', 75 | path: path.resolve(__dirname, dist) 76 | }, 77 | module: { 78 | rules: [ 79 | { 80 | test: /\.js$/, 81 | exclude: /node_modules/, 82 | loader: 'babel-loader', 83 | options: { 84 | presets: ['env'] 85 | } 86 | } 87 | ] 88 | }, 89 | plugins: [new UglifyJSPlugin()] 90 | }; 91 | ``` 92 | We can add this in `package.json` watch for changes and rebuild: 93 | ```json 94 | { 95 | "scripts": { 96 | "build": "webpack -w" 97 | } 98 | } 99 | ``` -------------------------------------------------------------------------------- /topics/workflow/deployment.md: -------------------------------------------------------------------------------- 1 | # Server 2 | 3 | - Buy server. 4 | - Find out IP address. 5 | - [Setup SSH public and private key for remote connections.](../ssh.md) 6 | - [Create users and setup the environment.](./environment.md) 7 | 8 | # Interoperability 9 | 10 | If you server connects to a database on another server, instead of using a VPN, ask the admins to add your server's IP address to their firewall. 11 | 12 | # Deploy code 13 | 14 | Use `rsync` to upload new files, and replace existing ones. 15 | 16 | Deploy the front-end static files, as well as the server ones. 17 | 18 | ``` 19 | npm run build --prefix app/ \ 20 | && rsync -av -e 'ssh' ./server ./app/dist --exclude 'server/node_modules' user@123.456.789.255:~/project/ \ 21 | && ssh user@123.456.789.255 pm2 reload /home/user/project/server/server.js --name "project" 22 | ``` 23 | 24 | # Domain 25 | 26 | If someone else owns the domain... 27 | 28 | - Tell them to create an A record for the domain/subdomain, which points to your server. 29 | 30 | If you own it... 31 | 32 | - Find the nameservers of your server's host. 33 | - Configure the domain's nameservers i.e. which DNS to use for further configuration. This is done in your registrar's admin panel, or you can tell the admin to manually set them up. They look like this: 34 | 35 | ``` 36 | ns1.host.com 37 | ns2.host.com 38 | ns3.host.com 39 | ``` 40 | 41 | # DNS 42 | 43 | - Add the domain. 44 | - Create A record for the domain/subdomain, which points to your server. 45 | - Create CNAME record for `www > domain.com` to handle `www.domain.com`. 46 | 47 | # SSL 48 | 49 | - Add a letencrypt SSL certificate with certbot. 50 | 51 | # Web server -nginx 52 | 53 | - Add the new configuration, which has SSL and a reverse proxy. 54 | 55 | ```nginx 56 | events {} 57 | 58 | http { 59 | include mime.types; 60 | 61 | server { 62 | listen 80; 63 | # IMPORTANT: Add CNAME record for www > domain.com 64 | # www.domain.com won't work without this 65 | server_name domain.com www.domain.com; 66 | return 301 https://domain.com$request_uri; 67 | } 68 | 69 | server { 70 | listen 443 ssl; 71 | server_name domain.com; 72 | ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem; 73 | ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem; 74 | 75 | root /home/ivan/wms/dist; 76 | index index.html; 77 | 78 | location / { 79 | try_files $uri /index.html; # Fixes refreshing resulting in 404 error for single page apps 80 | } 81 | 82 | location /auth { 83 | proxy_pass 'http://127.0.0.1:9999'; 84 | } 85 | 86 | location /api { 87 | proxy_pass 'http://127.0.0.1:9999'; 88 | } 89 | 90 | location /socket.io/ { 91 | proxy_pass 'http://127.0.0.1:9999'; 92 | } 93 | } 94 | } 95 | ``` 96 | 97 | # Start server script 98 | 99 | Use daemons such as `pm2` to run the script continuously. You can also use `nodemon` for running it temporarily. 100 | 101 | ``` 102 | pm2 start server.js --name "project" 103 | ``` 104 | 105 | # Test 106 | 107 | Visit the domain from multiple devices and be aware of caching, which might show something else than the real things. 108 | 109 | # Email 110 | 111 | Use a service like `migadu` or `mxroute` for low volume, and `mailgun` for high volume. 112 | -------------------------------------------------------------------------------- /topics/workflow/development.md: -------------------------------------------------------------------------------- 1 | # tmux 2 | 3 | Use to start development quickly: 4 | 5 | - Start front-end dev server. 6 | - Start MySQL server. 7 | - Start back-end API server. 8 | 9 | ``` 10 | tmux new-session \; \ 11 | send-keys 'cd /home/user/dev/project/app && npm run dev' C-m \; \ 12 | split-window -h -p 50 \; \ 13 | send-keys 'echo password | sudo -S service mysql start && cd /home/user/dev/project/server && nodemon server.js' C-m \; \ 14 | ``` 15 | 16 | # localhost Proxy 17 | 18 | During development, the front-end and back-end run on different ports. In order to avoid messy "manual/env" `localhost` URLs, use a proxy configuration in the front-end dev server. 19 | 20 | ```js 21 | // Vite example 22 | server: { 23 | proxy: { 24 | "/api": "http://localhost:9010", 25 | "/auth": "http://localhost:9010", 26 | "/socket.io": { 27 | target: "ws://localhost:9010", 28 | ws: true, 29 | }, 30 | }, 31 | esbuild: { 32 | drop: ["console", "debugger"], 33 | }, 34 | } 35 | ``` 36 | 37 | # VPN 38 | 39 | When working with databases that aren't yours, you can connect to them by establishing a VPN connection and using the local IP address of the machine hosting the database, example `192.168.10.4,1434` where `1434` is the port. 40 | 41 | You can ping the IP address to see if the connection works. 42 | 43 | # Build 44 | 45 | The front-end is bundled in static files, meaning they no longer run on a port. This means we can simply upload them to the live server to be used like any regular file. 46 | -------------------------------------------------------------------------------- /topics/workflow/environment.md: -------------------------------------------------------------------------------- 1 | # User 2 | 3 | ```bash 4 | # Login as root with password 5 | ssh root@123.456.789.255 6 | 7 | # Add user 8 | adduser <user> 9 | 10 | # Add sudo access 11 | usermod -aG sudo <user> 12 | 13 | # Switch to user 14 | su - <user> 15 | ``` 16 | 17 | # SSH 18 | 19 | ```bash 20 | # Transfer the public key id_rsa.pub to the remote server 21 | ssh-copy-id -i user@123.456.789.255 22 | 23 | # If they private/public keys don't exist 24 | ssh-keygen 25 | 26 | # Connect to server 27 | ssh user@123.456.789.255 28 | ``` 29 | 30 | # System 31 | 32 | ```bash 33 | # Update OS 34 | sudo apt update && sudo apt upgrade; 35 | 36 | # Check version 37 | lsb_release -a 38 | 39 | # Check timezone 40 | timedatectl 41 | 42 | # Change timezone 43 | sudo timedatectl set-timezone CET; 44 | ``` 45 | 46 | # Tools 47 | 48 | ```bash 49 | # curl, vim, tmux, git (Usually installed already) 50 | sudo apt install curl vim tmux git -y; 51 | ``` 52 | 53 | # Node.js 54 | 55 | **DO NOT install `nodejs` directly. Use `nvm`!** 56 | 57 | > **MUST RESTART TERMINAL AFTER INSTALL FOR `nvm` TO WORK!** 58 | 59 | ```bash 60 | # Download and install nvm 61 | curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash; 62 | # MUST RESTART TERMINAL AFTER INSTALL FOR nvm TO WORK!! 63 | 64 | # Install latest nodejs 65 | nvm install node; 66 | 67 | # Forward all the commands received as node to nodejs 68 | sudo ln -sf "$(which node)" /usr/bin/node; 69 | ``` 70 | 71 | # Daemons 72 | 73 | ```bash 74 | # Global nodemon 75 | npm i -g nodemon; 76 | 77 | # Global process manager 78 | npm i -g pm2; 79 | 80 | # Forward all the commands received as pm2 to whatever the fuck 81 | sudo ln -sf "$(which pm2)" /usr/bin/pm2; 82 | ``` 83 | 84 | # Web Server - nginx 85 | 86 | ```bash 87 | sudo apt install nginx -y; 88 | ``` 89 | 90 | # Database - MySQL 91 | 92 | ```bash 93 | sudo apt install mysql-server; 94 | 95 | sudo service mysql start 96 | # sudo /etc/init.d/mysql start; 97 | ``` 98 | 99 | Add a password to the `root` user. 100 | 101 | ```bash 102 | # Login 103 | sudo mysql; 104 | 105 | # Change root password 106 | ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password'; 107 | 108 | # Reload the privileges after password change. 109 | FLUSH PRIVILEGES; 110 | 111 | # Login with password 112 | sudo mysql -u root -p; 113 | ``` 114 | 115 | Change time zone. 116 | 117 | ``` 118 | sudo vim /etc/mysql/my.cnf 119 | ``` 120 | 121 | Add this: 122 | 123 | ``` 124 | [mysqld] 125 | default-time-zone = "+01:00" 126 | ``` 127 | 128 | Restart the MySQL server: 129 | 130 | ``` 131 | sudo systemctl restart mysql 132 | ``` 133 | --------------------------------------------------------------------------------