From 7c199adba9977cab16f6cd076316e6895af5365b Mon Sep 17 00:00:00 2001 From: thomasabishop Date: Sun, 29 Dec 2024 15:13:49 +0000 Subject: [PATCH] feat: add graph service --- db/eolas.db | Bin 1548288 -> 1560576 bytes out/eolas-graph.json | 7618 ++++++++++++++++++++++++++++ src/cli.py | 13 +- src/constants.py | 1 + src/controllers/controller.py | 20 +- src/models/entry.py | 2 +- src/models/graph_edge.py | 7 + src/models/graph_node.py | 7 + src/services/database_service.py | 4 +- src/services/graph_service.py | 49 + src/services/parse_file_service.py | 8 +- src/services/sqlite_service.py | 27 +- src/services/table_service.py | 36 +- 13 files changed, 7755 insertions(+), 37 deletions(-) create mode 100644 out/eolas-graph.json create mode 100644 src/models/graph_edge.py create mode 100644 src/models/graph_node.py create mode 100644 src/services/graph_service.py diff --git a/db/eolas.db b/db/eolas.db index afb6270818eafbf5e4c88628e2d5fe7dc8d40b5a..7d9c76ef53531972132ce38b7abbb082dcc31839 100644 GIT binary patch delta 40650 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 Dd`+n) delta 35403 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 diff --git a/out/eolas-graph.json b/out/eolas-graph.json new file mode 100644 index 0000000..47d2d82 --- /dev/null +++ b/out/eolas-graph.json @@ -0,0 +1,7618 @@ +{ + "nodes": [ + { + "id": "#nand-to-tetris", + "type": "tag" + }, + { + "id": "#question", + "type": "tag" + }, + { + "id": "#AWS", + "type": "tag" + }, + { + "id": "#graphql", + "type": "tag" + }, + { + "id": "#OOP", + "type": "tag" + }, + { + "id": "#design-patterns", + "type": "tag" + }, + { + "id": "#git", + "type": "tag" + }, + { + "id": "#python", + "type": "tag" + }, + { + "id": "#APIs", + "type": "tag" + }, + { + "id": "#ecopolsoc", + "type": "tag" + }, + { + "id": "#internet", + "type": "tag" + }, + { + "id": "#memory", + "type": "tag" + }, + { + "id": "#binary", + "type": "tag" + }, + { + "id": "#SNS", + "type": "tag" + }, + { + "id": "#SQS", + "type": "tag" + }, + { + "id": "#shell", + "type": "tag" + }, + { + "id": "#propositional-logic", + "type": "tag" + }, + { + "id": "#algebra", + "type": "tag" + }, + { + "id": "#logic", + "type": "tag" + }, + { + "id": "#node-js", + "type": "tag" + }, + { + "id": "#SQL", + "type": "tag" + }, + { + "id": "#databases", + "type": "tag" + }, + { + "id": "#data-types", + "type": "tag" + }, + { + "id": "#mongo-db", + "type": "tag" + }, + { + "id": "#physics", + "type": "tag" + }, + { + "id": "#electricity", + "type": "tag" + }, + { + "id": "#docker", + "type": "tag" + }, + { + "id": "#containerization", + "type": "tag" + }, + { + "id": "#Linux", + "type": "tag" + }, + { + "id": "#javascript", + "type": "tag" + }, + { + "id": "#ARPANET", + "type": "tag" + }, + { + "id": "#networks", + "type": "tag" + }, + { + "id": "#computer-history", + "type": "tag" + }, + { + "id": "#typescript", + "type": "tag" + }, + { + "id": "#disks", + "type": "tag" + }, + { + "id": "#procedural", + "type": "tag" + }, + { + "id": "#prealgebra", + "type": "tag" + }, + { + "id": "#fractions", + "type": "tag" + }, + { + "id": "#SQLite", + "type": "tag" + }, + { + "id": "#hardware", + "type": "tag" + }, + { + "id": "#set-theory", + "type": "tag" + }, + { + "id": "#awk", + "type": "tag" + }, + { + "id": "#data-structures", + "type": "tag" + }, + { + "id": "#systems-programming", + "type": "tag" + }, + { + "id": "#CPU", + "type": "tag" + }, + { + "id": "#computer-architecture", + "type": "tag" + }, + { + "id": "#electronics", + "type": "tag" + }, + { + "id": "#react", + "type": "tag" + }, + { + "id": "#ports", + "type": "tag" + }, + { + "id": "#theorems", + "type": "tag" + }, + { + "id": "#operating-systems", + "type": "tag" + }, + { + "id": "#algorithms", + "type": "tag" + }, + { + "id": "#C", + "type": "tag" + }, + { + "id": "#REST", + "type": "tag" + }, + { + "id": "#ARPA", + "type": "tag" + }, + { + "id": "#number-systems", + "type": "tag" + }, + { + "id": "#aws-lambda", + "type": "tag" + }, + { + "id": "#fleeting", + "type": "tag" + }, + { + "id": "#modems", + "type": "tag" + }, + { + "id": "#bulletin-boards", + "type": "tag" + }, + { + "id": "#packet-switching", + "type": "tag" + }, + { + "id": "#encryption", + "type": "tag" + }, + { + "id": "#privacy", + "type": "tag" + }, + { + "id": "#TOR", + "type": "tag" + }, + { + "id": "#logic-gates", + "type": "tag" + }, + { + "id": "#world-wide-web", + "type": "tag" + }, + { + "id": "#electromagnetism", + "type": "tag" + }, + { + "id": "#mongoose", + "type": "tag" + }, + { + "id": "#middleware", + "type": "tag" + }, + { + "id": "#network-protocols", + "type": "tag" + }, + { + "id": "#Microsoft", + "type": "tag" + }, + { + "id": "#literature", + "type": "tag" + }, + { + "id": "#ecosolpoc", + "type": "tag" + }, + { + "id": "#bus", + "type": "tag" + }, + { + "id": "#testing", + "type": "tag" + }, + { + "id": "#number-theory", + "type": "tag" + }, + { + "id": "#analogue", + "type": "tag" + }, + { + "id": "#file-system", + "type": "tag" + }, + { + "id": "#regex", + "type": "tag" + }, + { + "id": "#systemd", + "type": "tag" + }, + { + "id": "#surveillance-capitalism", + "type": "tag" + }, + { + "id": "#exponents", + "type": "tag" + }, + { + "id": "#dynamodb", + "type": "tag" + }, + { + "id": "#cryptography", + "type": "tag" + }, + { + "id": "#json", + "type": "tag" + }, + { + "id": "#kernel", + "type": "tag" + }, + { + "id": "#sound", + "type": "tag" + }, + { + "id": "#theory-of-computation", + "type": "tag" + }, + { + "id": "#Turing", + "type": "tag" + }, + { + "id": "#jest", + "type": "tag" + }, + { + "id": "#yaml", + "type": "tag" + }, + { + "id": "#storage", + "type": "tag" + }, + { + "id": "#unix", + "type": "tag" + }, + { + "id": "#time", + "type": "tag" + }, + { + "id": "#recursion", + "type": "tag" + }, + { + "id": "#arithmetic", + "type": "tag" + }, + { + "id": "#csv", + "type": "tag" + }, + { + "id": "#raspberry-pi", + "type": "tag" + }, + { + "id": "#S3", + "type": "tag" + }, + { + "id": "#IaC", + "type": "tag" + }, + { + "id": "#JSON", + "type": "tag" + }, + { + "id": "#arch-linux", + "type": "tag" + }, + { + "id": "0716531c_rewilding_the_internet", + "type": "entry" + }, + { + "id": "241fe1a3_the_Web_versus_modem_BBSs", + "type": "entry" + }, + { + "id": "385af4b4_Baran_distributed_networks", + "type": "entry" + }, + { + "id": "3f1b9fe5_motivation_Berners_Lee", + "type": "entry" + }, + { + "id": "4a3dc316_key_figures_ARPANET", + "type": "entry" + }, + { + "id": "4da22434_from_ARPANET_to_Internet", + "type": "entry" + }, + { + "id": "653c0b1d_host_protocols_of_ARPANET", + "type": "entry" + }, + { + "id": "82f9c228_dissolution_of_ARPANET", + "type": "entry" + }, + { + "id": "861cc26e_ARPA_origins", + "type": "entry" + }, + { + "id": "API_Gateway", + "type": "entry" + }, + { + "id": "AWS_CLI", + "type": "entry" + }, + { + "id": "AWS_CloudWatch", + "type": "entry" + }, + { + "id": "AWS_SAM_and_Docker", + "type": "entry" + }, + { + "id": "AWS_SNS", + "type": "entry" + }, + { + "id": "AWS_SQS", + "type": "entry" + }, + { + "id": "AWS_SQS_SDK", + "type": "entry" + }, + { + "id": "AWS_architecture_hierarchy", + "type": "entry" + }, + { + "id": "Accessing_metadata_about_SQL_database", + "type": "entry" + }, + { + "id": "Accessing_secrets_from_a_Lambda", + "type": "entry" + }, + { + "id": "Add_Subtract_Fractions", + "type": "entry" + }, + { + "id": "Adding_documents_to_a_Mongo_collection", + "type": "entry" + }, + { + "id": "Additive_identity", + "type": "entry" + }, + { + "id": "Additive_inverse_property", + "type": "entry" + }, + { + "id": "Aggregate_functions_in_SQL", + "type": "entry" + }, + { + "id": "Algebra_key_terms", + "type": "entry" + }, + { + "id": "Algorithmic_complexity", + "type": "entry" + }, + { + "id": "Analogue_and_digital", + "type": "entry" + }, + { + "id": "Any", + "type": "entry" + }, + { + "id": "Apollo_Client", + "type": "entry" + }, + { + "id": "Apollo_Server", + "type": "entry" + }, + { + "id": "Appending_to_files_in_Python", + "type": "entry" + }, + { + "id": "Application_Layer_of_Internet_Protocol", + "type": "entry" + }, + { + "id": "Application_state_management_with_React_hooks", + "type": "entry" + }, + { + "id": "Architecture_of_the_World_Wide_Web", + "type": "entry" + }, + { + "id": "Arithmetic_Logic_Unit", + "type": "entry" + }, + { + "id": "Arrays", + "type": "entry" + }, + { + "id": "Assembly", + "type": "entry" + }, + { + "id": "Associative_Property_of_Addition_and_Multiplication", + "type": "entry" + }, + { + "id": "Atomic_and_molecular_propositions", + "type": "entry" + }, + { + "id": "Audio_file_formats", + "type": "entry" + }, + { + "id": "Awk", + "type": "entry" + }, + { + "id": "Axioms_of_set_theory", + "type": "entry" + }, + { + "id": "Bash_colour_output", + "type": "entry" + }, + { + "id": "Bash_file_exists", + "type": "entry" + }, + { + "id": "Bash_store_status_of_command_execution", + "type": "entry" + }, + { + "id": "Basic_model_of_the_operating_system", + "type": "entry" + }, + { + "id": "Basic_properties_of_sets", + "type": "entry" + }, + { + "id": "Basics_of_web_components", + "type": "entry" + }, + { + "id": "Batch_processing", + "type": "entry" + }, + { + "id": "Bauman_quote", + "type": "entry" + }, + { + "id": "Bell_System", + "type": "entry" + }, + { + "id": "Biconditional_Elimination", + "type": "entry" + }, + { + "id": "Biconditional_Introduction", + "type": "entry" + }, + { + "id": "Binary_addition", + "type": "entry" + }, + { + "id": "Binary_arithmetic", + "type": "entry" + }, + { + "id": "Binary_colour_encoding", + "type": "entry" + }, + { + "id": "Binary_encoding", + "type": "entry" + }, + { + "id": "Binary_encoding_of_sound", + "type": "entry" + }, + { + "id": "Binary_encoding_of_text", + "type": "entry" + }, + { + "id": "Binary_number_system", + "type": "entry" + }, + { + "id": "Binary_units_of_measurement", + "type": "entry" + }, + { + "id": "Bitwise_operators", + "type": "entry" + }, + { + "id": "Bluetooth", + "type": "entry" + }, + { + "id": "Bolt_Beranek_and_Newman", + "type": "entry" + }, + { + "id": "Boolean_algebra", + "type": "entry" + }, + { + "id": "Boolean_function_synthesis", + "type": "entry" + }, + { + "id": "Boolean_functions", + "type": "entry" + }, + { + "id": "Boot_process", + "type": "entry" + }, + { + "id": "Breadboards", + "type": "entry" + }, + { + "id": "Bus", + "type": "entry" + }, + { + "id": "CPU_architecture", + "type": "entry" + }, + { + "id": "Call_stack", + "type": "entry" + }, + { + "id": "Capturing_user_input_in_Bash", + "type": "entry" + }, + { + "id": "Case_statements_in_Bash", + "type": "entry" + }, + { + "id": "Cells_and_batteries", + "type": "entry" + }, + { + "id": "Cherry_picking", + "type": "entry" + }, + { + "id": "Child_to_parent_data_flow_in_React", + "type": "entry" + }, + { + "id": "Chipset_and_controllers", + "type": "entry" + }, + { + "id": "Class_inheritance_in_Python", + "type": "entry" + }, + { + "id": "Classes", + "type": "entry" + }, + { + "id": "Classes_in_Python", + "type": "entry" + }, + { + "id": "Clock_signals", + "type": "entry" + }, + { + "id": "Command_pattern", + "type": "entry" + }, + { + "id": "Commutative_Property_of_Addition_and_Multiplication", + "type": "entry" + }, + { + "id": "Comparing_React_classes_to_hooks", + "type": "entry" + }, + { + "id": "Compile_Python_app_to_single_executable", + "type": "entry" + }, + { + "id": "Compile_from_source", + "type": "entry" + }, + { + "id": "Components_props_classes", + "type": "entry" + }, + { + "id": "Components_props_hooks_in_React", + "type": "entry" + }, + { + "id": "Concise_subfield_mapping_JS", + "type": "entry" + }, + { + "id": "Conditional_Elimination", + "type": "entry" + }, + { + "id": "Conditional_Introduction", + "type": "entry" + }, + { + "id": "Conditional_statements_in_Python", + "type": "entry" + }, + { + "id": "Conditionals_in_Bash", + "type": "entry" + }, + { + "id": "Conjunction_Elimination", + "type": "entry" + }, + { + "id": "Conjunction_Introduction", + "type": "entry" + }, + { + "id": "Connect_to_Mongo_database", + "type": "entry" + }, + { + "id": "Connecting_a_frontend_to_a_Docker_backend", + "type": "entry" + }, + { + "id": "Containerization", + "type": "entry" + }, + { + "id": "Controlled_components_in_React", + "type": "entry" + }, + { + "id": "Corresponding_material_and_biconditional", + "type": "entry" + }, + { + "id": "Coulombs_Laws", + "type": "entry" + }, + { + "id": "Create_Mongo_database", + "type": "entry" + }, + { + "id": "Create_an_SQL_table", + "type": "entry" + }, + { + "id": "Create_timed_systemd_job", + "type": "entry" + }, + { + "id": "Creating_a_Docker_image", + "type": "entry" + }, + { + "id": "Creating_a_Linux_partition_table", + "type": "entry" + }, + { + "id": "Creating_a_Mongo_schema_and_model", + "type": "entry" + }, + { + "id": "Creating_a_RESTful_API_GET", + "type": "entry" + }, + { + "id": "Creating_a_RESTful_API_Integrating_the_Database", + "type": "entry" + }, + { + "id": "Creating_a_RESTful_API_Introduction", + "type": "entry" + }, + { + "id": "Creating_a_RESTful_API_POST", + "type": "entry" + }, + { + "id": "Creating_a_RESTful_API_PUT", + "type": "entry" + }, + { + "id": "Creating_memory_with_NAND", + "type": "entry" + }, + { + "id": "Cron", + "type": "entry" + }, + { + "id": "Current", + "type": "entry" + }, + { + "id": "Custom_React_hook_examples", + "type": "entry" + }, + { + "id": "Custom_types_in_TypeScript", + "type": "entry" + }, + { + "id": "DRAM_and_SRAM_memory", + "type": "entry" + }, + { + "id": "Daemons", + "type": "entry" + }, + { + "id": "Data_types_in_Bash", + "type": "entry" + }, + { + "id": "Data_types_in_MySQL", + "type": "entry" + }, + { + "id": "Database_indices", + "type": "entry" + }, + { + "id": "Database_options_on_AWS", + "type": "entry" + }, + { + "id": "Dates_in_Python", + "type": "entry" + }, + { + "id": "DeMorgan's_Laws", + "type": "entry" + }, + { + "id": "Defining_a_computer", + "type": "entry" + }, + { + "id": "Delay_line_memory", + "type": "entry" + }, + { + "id": "Delete_a_branch", + "type": "entry" + }, + { + "id": "Delete_records_in_an_SQL_table", + "type": "entry" + }, + { + "id": "Deleting_Mongo_documents", + "type": "entry" + }, + { + "id": "Dependency_injection", + "type": "entry" + }, + { + "id": "Devices", + "type": "entry" + }, + { + "id": "Dictionaries_in_Python", + "type": "entry" + }, + { + "id": "Difference_between_remote_origin_and_head", + "type": "entry" + }, + { + "id": "Disjunction_Elimination", + "type": "entry" + }, + { + "id": "Disjunction_Introduction", + "type": "entry" + }, + { + "id": "Disk_info", + "type": "entry" + }, + { + "id": "Distributivity", + "type": "entry" + }, + { + "id": "Dividing_fractions", + "type": "entry" + }, + { + "id": "Docker_CLI", + "type": "entry" + }, + { + "id": "Docker_Compose", + "type": "entry" + }, + { + "id": "Docker_architecture", + "type": "entry" + }, + { + "id": "Docker_compose_and_Dockerfile_difference", + "type": "entry" + }, + { + "id": "Docker_containers", + "type": "entry" + }, + { + "id": "Docker_general_overview", + "type": "entry" + }, + { + "id": "Docker_images", + "type": "entry" + }, + { + "id": "Docker_storage", + "type": "entry" + }, + { + "id": "Dynamic_and_static_websites", + "type": "entry" + }, + { + "id": "DynamoDB_CLI_commands", + "type": "entry" + }, + { + "id": "DynamoDB_SDK_commands", + "type": "entry" + }, + { + "id": "DynamoDB_data_structure", + "type": "entry" + }, + { + "id": "Effective_logging_in_Git", + "type": "entry" + }, + { + "id": "Elastic_Compute_Cloud", + "type": "entry" + }, + { + "id": "Electromagnetism", + "type": "entry" + }, + { + "id": "Electrons", + "type": "entry" + }, + { + "id": "Enums", + "type": "entry" + }, + { + "id": "Environmental_and_shell_variables", + "type": "entry" + }, + { + "id": "Equivalent_equations", + "type": "entry" + }, + { + "id": "Equivalent_fractions", + "type": "entry" + }, + { + "id": "Error_handling_in_Python", + "type": "entry" + }, + { + "id": "Event_loop", + "type": "entry" + }, + { + "id": "Example_scenario_internet_data_transfer", + "type": "entry" + }, + { + "id": "Expansions_and_substitutions", + "type": "entry" + }, + { + "id": "Exponents", + "type": "entry" + }, + { + "id": "Expressing_whole_numbers_as_fractions", + "type": "entry" + }, + { + "id": "Factors_and_divisors", + "type": "entry" + }, + { + "id": "Factory_pattern", + "type": "entry" + }, + { + "id": "Fetch_decode_execute", + "type": "entry" + }, + { + "id": "Fetch_from_Secrets_Manager", + "type": "entry" + }, + { + "id": "File_descriptors", + "type": "entry" + }, + { + "id": "File_operations_in_Python", + "type": "entry" + }, + { + "id": "File_permissions_and_execution_in_Bash", + "type": "entry" + }, + { + "id": "File_system_error_handling_in_Python", + "type": "entry" + }, + { + "id": "Filesystems", + "type": "entry" + }, + { + "id": "Find_Bash_command", + "type": "entry" + }, + { + "id": "Flip_flops", + "type": "entry" + }, + { + "id": "Foreign_keys_in_SQL", + "type": "entry" + }, + { + "id": "Formal_conventions", + "type": "entry" + }, + { + "id": "Formal_proofs_in_propositional_logic", + "type": "entry" + }, + { + "id": "Format_specifiers_in_C", + "type": "entry" + }, + { + "id": "Formatting_output_text_in_Bash", + "type": "entry" + }, + { + "id": "Forms_in_React", + "type": "entry" + }, + { + "id": "Four_bit_adder", + "type": "entry" + }, + { + "id": "Frequency_counters", + "type": "entry" + }, + { + "id": "Full_Node_API_example", + "type": "entry" + }, + { + "id": "Function_overloads", + "type": "entry" + }, + { + "id": "Functions", + "type": "entry" + }, + { + "id": "Functions_in_Bash", + "type": "entry" + }, + { + "id": "Functions_in_Python", + "type": "entry" + }, + { + "id": "Fundamental_Theorem_of_Arithmetic", + "type": "entry" + }, + { + "id": "Further_examples_of_TS_generics", + "type": "entry" + }, + { + "id": "GPU_versus_CPU", + "type": "entry" + }, + { + "id": "Generics_in_TypeScript", + "type": "entry" + }, + { + "id": "Git_bisect", + "type": "entry" + }, + { + "id": "Git_rebasing", + "type": "entry" + }, + { + "id": "Global_object_in_NodeJS", + "type": "entry" + }, + { + "id": "Grep", + "type": "entry" + }, + { + "id": "Ground", + "type": "entry" + }, + { + "id": "Guide_to_YAML", + "type": "entry" + }, + { + "id": "HTTPS", + "type": "entry" + }, + { + "id": "HTTP_request_types", + "type": "entry" + }, + { + "id": "Half_adder_and_full_adder", + "type": "entry" + }, + { + "id": "Handle_multiple_endpoints_single_lambda", + "type": "entry" + }, + { + "id": "Handling_negative_fractions", + "type": "entry" + }, + { + "id": "Hardware_Description_Language", + "type": "entry" + }, + { + "id": "Hardware_abstraction_and_modularity", + "type": "entry" + }, + { + "id": "Hardware_simulation", + "type": "entry" + }, + { + "id": "Headless_Raspi_network_setup", + "type": "entry" + }, + { + "id": "Heap_memory", + "type": "entry" + }, + { + "id": "Hexadecimal_number_system", + "type": "entry" + }, + { + "id": "IP_addresses", + "type": "entry" + }, + { + "id": "Identify_merged_branches", + "type": "entry" + }, + { + "id": "Importing_MongoDB_data", + "type": "entry" + }, + { + "id": "Increasing_fractions_to_their_highest_terms", + "type": "entry" + }, + { + "id": "Insert_data_into_SQL_table", + "type": "entry" + }, + { + "id": "Instruction_set_architectures", + "type": "entry" + }, + { + "id": "Integers", + "type": "entry" + }, + { + "id": "Integrated_circuits", + "type": "entry" + }, + { + "id": "Interactive_staging", + "type": "entry" + }, + { + "id": "Internet_Layer_of_Internet_Protocol", + "type": "entry" + }, + { + "id": "Internet_fundamentals", + "type": "entry" + }, + { + "id": "Intersection_types_in_TypeScript", + "type": "entry" + }, + { + "id": "Intro_to_the_Unix_shell", + "type": "entry" + }, + { + "id": "Inversion_of_operators", + "type": "entry" + }, + { + "id": "Invoking_the_shell_in_Python", + "type": "entry" + }, + { + "id": "Iterating_in_React", + "type": "entry" + }, + { + "id": "Iterating_through_complex_data_structures_in_Python", + "type": "entry" + }, + { + "id": "JavaScript_module_types", + "type": "entry" + }, + { + "id": "Joins_in_SQL", + "type": "entry" + }, + { + "id": "Journey_of_GraphQL_query", + "type": "entry" + }, + { + "id": "Key_characteristics_of_GraphQL", + "type": "entry" + }, + { + "id": "Killing_processes", + "type": "entry" + }, + { + "id": "LEDs", + "type": "entry" + }, + { + "id": "Lambda_directory_structure", + "type": "entry" + }, + { + "id": "Lambda_handler_function", + "type": "entry" + }, + { + "id": "Lambda_programming_model", + "type": "entry" + }, + { + "id": "Lambda_triggers", + "type": "entry" + }, + { + "id": "Lambdas_in_Python", + "type": "entry" + }, + { + "id": "Latches", + "type": "entry" + }, + { + "id": "Law_of_Non_Contradiction", + "type": "entry" + }, + { + "id": "Law_of_the_Excluded_Middle", + "type": "entry" + }, + { + "id": "Lifecycle_methods", + "type": "entry" + }, + { + "id": "Link_Layer_of_Internet_Protocol", + "type": "entry" + }, + { + "id": "Linux_disk_partitions", + "type": "entry" + }, + { + "id": "List_comprehension_in_Python", + "type": "entry" + }, + { + "id": "Listing_and_navigating_directories_in_the_Shell", + "type": "entry" + }, + { + "id": "Lists_and_arrays_in_Bash", + "type": "entry" + }, + { + "id": "Lists_in_Python", + "type": "entry" + }, + { + "id": "Local_AWS_development_with_SAM", + "type": "entry" + }, + { + "id": "Logarithms", + "type": "entry" + }, + { + "id": "Logic_gates", + "type": "entry" + }, + { + "id": "Logical_consistency", + "type": "entry" + }, + { + "id": "Logical_equivalence", + "type": "entry" + }, + { + "id": "Logical_indeterminacy", + "type": "entry" + }, + { + "id": "Logical_possibility_and_necessity", + "type": "entry" + }, + { + "id": "Logical_truth_and_falsity", + "type": "entry" + }, + { + "id": "Loops_in_Python", + "type": "entry" + }, + { + "id": "Loops_in_bash", + "type": "entry" + }, + { + "id": "MAC_addresses", + "type": "entry" + }, + { + "id": "Machine_code", + "type": "entry" + }, + { + "id": "Magnetic_core_memory", + "type": "entry" + }, + { + "id": "Magnetic_drum_memory", + "type": "entry" + }, + { + "id": "Magnetic_tape", + "type": "entry" + }, + { + "id": "Mainframe_computers", + "type": "entry" + }, + { + "id": "Managing_environments_in_NodeJS", + "type": "entry" + }, + { + "id": "Map_and_filter_in_Python", + "type": "entry" + }, + { + "id": "Map_and_filter_to_reduce_in_JS", + "type": "entry" + }, + { + "id": "Mapped_types_in_TS", + "type": "entry" + }, + { + "id": "Maps_and_sets_in_JS", + "type": "entry" + }, + { + "id": "Match_statements_in_Python", + "type": "entry" + }, + { + "id": "Matter_and_atoms", + "type": "entry" + }, + { + "id": "Memoization_in_React", + "type": "entry" + }, + { + "id": "Memory_Management_Unit", + "type": "entry" + }, + { + "id": "Memory_addresses", + "type": "entry" + }, + { + "id": "Memory_leaks", + "type": "entry" + }, + { + "id": "Memory_versus_processor", + "type": "entry" + }, + { + "id": "Middleware_in_NodeJS", + "type": "entry" + }, + { + "id": "Mixed_and_improper_fractions", + "type": "entry" + }, + { + "id": "Modelling_relationships_in_MongoDB", + "type": "entry" + }, + { + "id": "Module_pattern", + "type": "entry" + }, + { + "id": "Module_wrapping_at_runtime", + "type": "entry" + }, + { + "id": "Modules_in_NodeJS", + "type": "entry" + }, + { + "id": "MongoDB_Introduction", + "type": "entry" + }, + { + "id": "MongoDB_connection", + "type": "entry" + }, + { + "id": "Monitoring_processes_and_resources", + "type": "entry" + }, + { + "id": "Morgan", + "type": "entry" + }, + { + "id": "Motherboard", + "type": "entry" + }, + { + "id": "Multiple_pointers", + "type": "entry" + }, + { + "id": "Multiplexers_and_demultiplexers", + "type": "entry" + }, + { + "id": "Multiplicative_identity", + "type": "entry" + }, + { + "id": "Multiplicative_property_of_negative_one", + "type": "entry" + }, + { + "id": "Multiplying_fractions", + "type": "entry" + }, + { + "id": "Mutations_with_Apollo_Client", + "type": "entry" + }, + { + "id": "Naming_conventions", + "type": "entry" + }, + { + "id": "Natural_numbers", + "type": "entry" + }, + { + "id": "Negation_Elimination", + "type": "entry" + }, + { + "id": "Negation_Introduction", + "type": "entry" + }, + { + "id": "Negative_exponents", + "type": "entry" + }, + { + "id": "Network_card", + "type": "entry" + }, + { + "id": "Network_debugging", + "type": "entry" + }, + { + "id": "Network_fundamentals", + "type": "entry" + }, + { + "id": "Network_hosts", + "type": "entry" + }, + { + "id": "Network_packet_analysis_tools", + "type": "entry" + }, + { + "id": "Network_protocols", + "type": "entry" + }, + { + "id": "Network_requests_in_Python", + "type": "entry" + }, + { + "id": "Network_scanning", + "type": "entry" + }, + { + "id": "NodeJS_scripts", + "type": "entry" + }, + { + "id": "Node_and_MySQL_db", + "type": "entry" + }, + { + "id": "Nodemon", + "type": "entry" + }, + { + "id": "Non_null_assertion_in_TypeScript", + "type": "entry" + }, + { + "id": "None_in_Python", + "type": "entry" + }, + { + "id": "Numbers_in_Python", + "type": "entry" + }, + { + "id": "Object_language_and_meta_language", + "type": "entry" + }, + { + "id": "Observer_pattern", + "type": "entry" + }, + { + "id": "Ohms_Law", + "type": "entry" + }, + { + "id": "OpenSearch", + "type": "entry" + }, + { + "id": "Operating_system_API", + "type": "entry" + }, + { + "id": "Order_of_operations", + "type": "entry" + }, + { + "id": "Package_management_in_NodeJS", + "type": "entry" + }, + { + "id": "Packet_switching_British_precursors", + "type": "entry" + }, + { + "id": "Pacman", + "type": "entry" + }, + { + "id": "Passing_arguments_and_options_to_Bash_scripts", + "type": "entry" + }, + { + "id": "Passing_arguments_to_Python_scripts", + "type": "entry" + }, + { + "id": "Peer_to_peer_network", + "type": "entry" + }, + { + "id": "Ports_in_NodeJS", + "type": "entry" + }, + { + "id": "Practical_walkthrough_Lambda_creation_within_AWS", + "type": "entry" + }, + { + "id": "Prefixes_for_units_of_electrical_measurement", + "type": "entry" + }, + { + "id": "Prime_factorization", + "type": "entry" + }, + { + "id": "Primes_and_composites", + "type": "entry" + }, + { + "id": "Primitive_types", + "type": "entry" + }, + { + "id": "Printing_values_in_C", + "type": "entry" + }, + { + "id": "Process_module_in_NodeJS", + "type": "entry" + }, + { + "id": "Processes", + "type": "entry" + }, + { + "id": "Prop_types_in_React", + "type": "entry" + }, + { + "id": "Proper_shebang_syntax", + "type": "entry" + }, + { + "id": "Props_in_React", + "type": "entry" + }, + { + "id": "Prototypical_inheritance", + "type": "entry" + }, + { + "id": "Push_buttons", + "type": "entry" + }, + { + "id": "Python_application_structure", + "type": "entry" + }, + { + "id": "Python_data_types", + "type": "entry" + }, + { + "id": "Python_execution", + "type": "entry" + }, + { + "id": "Python_interpreter", + "type": "entry" + }, + { + "id": "Python_modules_and_imports", + "type": "entry" + }, + { + "id": "Python_package_management", + "type": "entry" + }, + { + "id": "Querying_a_Mongo_collection", + "type": "entry" + }, + { + "id": "Queue", + "type": "entry" + }, + { + "id": "Quote_marks_in_Bash", + "type": "entry" + }, + { + "id": "RESTful_APIs", + "type": "entry" + }, + { + "id": "ROM_versus_disk_loading", + "type": "entry" + }, + { + "id": "React_Components", + "type": "entry" + }, + { + "id": "React_application_structure", + "type": "entry" + }, + { + "id": "React_errors", + "type": "entry" + }, + { + "id": "React_useContext", + "type": "entry" + }, + { + "id": "React_useEffect", + "type": "entry" + }, + { + "id": "React_useReducer", + "type": "entry" + }, + { + "id": "React_useState", + "type": "entry" + }, + { + "id": "Read_command__in_Bash", + "type": "entry" + }, + { + "id": "Reading_files_in_Python", + "type": "entry" + }, + { + "id": "Reciprocals", + "type": "entry" + }, + { + "id": "Recursion", + "type": "entry" + }, + { + "id": "Redirect_to_dev_null", + "type": "entry" + }, + { + "id": "Redirection_in_Bash", + "type": "entry" + }, + { + "id": "Reducing_fractions", + "type": "entry" + }, + { + "id": "Register_and_cache_memory", + "type": "entry" + }, + { + "id": "Regular_expressions_in_SQL", + "type": "entry" + }, + { + "id": "Reiteration", + "type": "entry" + }, + { + "id": "Relation_between_kernel_and_CPU", + "type": "entry" + }, + { + "id": "Relational_database_architecture", + "type": "entry" + }, + { + "id": "Relays", + "type": "entry" + }, + { + "id": "Remote_tracking_branches", + "type": "entry" + }, + { + "id": "Rename_a_branch", + "type": "entry" + }, + { + "id": "Reset_to_remote_version", + "type": "entry" + }, + { + "id": "Resistance", + "type": "entry" + }, + { + "id": "Restructure_URLs_lambda", + "type": "entry" + }, + { + "id": "Retrieve_data_from_SQL_table", + "type": "entry" + }, + { + "id": "Role_of_memory_in_computation", + "type": "entry" + }, + { + "id": "Role_of_unique_key_in_relational_databases", + "type": "entry" + }, + { + "id": "Routing_on_link_click_in_React", + "type": "entry" + }, + { + "id": "Rules_for_operations_on_like_and_unlike_terms", + "type": "entry" + }, + { + "id": "S3", + "type": "entry" + }, + { + "id": "SAM", + "type": "entry" + }, + { + "id": "SQLite", + "type": "entry" + }, + { + "id": "Save_readonly_Vim_file", + "type": "entry" + }, + { + "id": "Schema_Definition_Language_in_GraphQL", + "type": "entry" + }, + { + "id": "Secrets_or_env_vars_in_AWS", + "type": "entry" + }, + { + "id": "Semantic_versioning", + "type": "entry" + }, + { + "id": "Set_DNS_settings", + "type": "entry" + }, + { + "id": "Sets_in_Python", + "type": "entry" + }, + { + "id": "Setting_up_and_configuring_TypeScript", + "type": "entry" + }, + { + "id": "Shell_sessions", + "type": "entry" + }, + { + "id": "Signed_and_unsigned_numbers", + "type": "entry" + }, + { + "id": "Signed_magnitude_representation", + "type": "entry" + }, + { + "id": "Single_file_Python_scripts", + "type": "entry" + }, + { + "id": "Singleton_pattern", + "type": "entry" + }, + { + "id": "Sliding_window", + "type": "entry" + }, + { + "id": "Solving_equations", + "type": "entry" + }, + { + "id": "Sorting_lists_in_Python", + "type": "entry" + }, + { + "id": "Soundness", + "type": "entry" + }, + { + "id": "Split_into_array_in_Bash", + "type": "entry" + }, + { + "id": "Stack_memory", + "type": "entry" + }, + { + "id": "Stacks", + "type": "entry" + }, + { + "id": "Stale_branches_and_pruning", + "type": "entry" + }, + { + "id": "Step_functions_and_state_machines", + "type": "entry" + }, + { + "id": "Strategies_for_constructing_proofs", + "type": "entry" + }, + { + "id": "Streams_in_NodeJS", + "type": "entry" + }, + { + "id": "Strings_in_Bash", + "type": "entry" + }, + { + "id": "Strings_in_Python", + "type": "entry" + }, + { + "id": "Structuring_Express_applications", + "type": "entry" + }, + { + "id": "Substrings_in_Bash", + "type": "entry" + }, + { + "id": "Swap_space", + "type": "entry" + }, + { + "id": "Switch_between_Python_vers", + "type": "entry" + }, + { + "id": "Syllogism", + "type": "entry" + }, + { + "id": "Symlinks", + "type": "entry" + }, + { + "id": "Syntax_of_propositional_logic", + "type": "entry" + }, + { + "id": "Tags_in_Git", + "type": "entry" + }, + { + "id": "Terraform", + "type": "entry" + }, + { + "id": "Test_values_in_Bash", + "type": "entry" + }, + { + "id": "Testing_Python_code", + "type": "entry" + }, + { + "id": "Testing_basic_prop_passing_in_React", + "type": "entry" + }, + { + "id": "Testing_with_Jest", + "type": "entry" + }, + { + "id": "Text_manipulation_in_Bash", + "type": "entry" + }, + { + "id": "The_History_of_Computing_Swade", + "type": "entry" + }, + { + "id": "The_Little_Man_computer", + "type": "entry" + }, + { + "id": "The_PATH", + "type": "entry" + }, + { + "id": "The_Pragmatic_Programmer_1999", + "type": "entry" + }, + { + "id": "The_kernel", + "type": "entry" + }, + { + "id": "The_memory_hierarchy", + "type": "entry" + }, + { + "id": "Theorems_and_empty_sets", + "type": "entry" + }, + { + "id": "Threads", + "type": "entry" + }, + { + "id": "Three_bit_counter", + "type": "entry" + }, + { + "id": "Time_and_computers", + "type": "entry" + }, + { + "id": "Torrenting", + "type": "entry" + }, + { + "id": "Transistors", + "type": "entry" + }, + { + "id": "Transport_Layer_of_Internet_Protocol", + "type": "entry" + }, + { + "id": "Troubleshooting_MongoDB", + "type": "entry" + }, + { + "id": "Truth_functional_connectives", + "type": "entry" + }, + { + "id": "Truth_tables", + "type": "entry" + }, + { + "id": "Truth_trees", + "type": "entry" + }, + { + "id": "Tuples_in_Python", + "type": "entry" + }, + { + "id": "Turing_completeness", + "type": "entry" + }, + { + "id": "Turing_machines", + "type": "entry" + }, + { + "id": "Twos_complement", + "type": "entry" + }, + { + "id": "Type_guarding_and_narrowing_in_TS", + "type": "entry" + }, + { + "id": "Type_hinting", + "type": "entry" + }, + { + "id": "Typing_built_in_React_hooks", + "type": "entry" + }, + { + "id": "Union_types_in_TS", + "type": "entry" + }, + { + "id": "Unknown_type_in_TS", + "type": "entry" + }, + { + "id": "Update_a_Mongo_document", + "type": "entry" + }, + { + "id": "Update_an_SQL_table", + "type": "entry" + }, + { + "id": "Update_existing_data_in_SQL_table", + "type": "entry" + }, + { + "id": "Useful_operators_in_SQL", + "type": "entry" + }, + { + "id": "Usenet", + "type": "entry" + }, + { + "id": "User_Space", + "type": "entry" + }, + { + "id": "User_agent", + "type": "entry" + }, + { + "id": "User_management_in_Linux", + "type": "entry" + }, + { + "id": "User_management_on_AWS", + "type": "entry" + }, + { + "id": "Using_GraphQL_with_Node", + "type": "entry" + }, + { + "id": "Using_SQLite_with_Python", + "type": "entry" + }, + { + "id": "Using_arguments_with_Apollo_Client", + "type": "entry" + }, + { + "id": "Utilities_operators_flags", + "type": "entry" + }, + { + "id": "Validating_Mongoose_schemas", + "type": "entry" + }, + { + "id": "Validation_in_NodeJS", + "type": "entry" + }, + { + "id": "Validity_and_entailment", + "type": "entry" + }, + { + "id": "Variable_indirection_in_Bash", + "type": "entry" + }, + { + "id": "Variables_and_data_types_in_Bash", + "type": "entry" + }, + { + "id": "Variables_in_C", + "type": "entry" + }, + { + "id": "Viewing_remote_changes_without_merging", + "type": "entry" + }, + { + "id": "Views_in_relational_databases", + "type": "entry" + }, + { + "id": "VirtualMemory", + "type": "entry" + }, + { + "id": "Virtual_private_cloud", + "type": "entry" + }, + { + "id": "Voltage", + "type": "entry" + }, + { + "id": "Voltage_sources", + "type": "entry" + }, + { + "id": "Weaving_the_Web_Berners_Lee", + "type": "entry" + }, + { + "id": "What_are_disks", + "type": "entry" + }, + { + "id": "What_can_the_ISP_see", + "type": "entry" + }, + { + "id": "What_is_memory", + "type": "entry" + }, + { + "id": "Whole_numbers", + "type": "entry" + }, + { + "id": "Why_computers_use_binary", + "type": "entry" + }, + { + "id": "Wildcards_in_SQL", + "type": "entry" + }, + { + "id": "Williams_Tube_memory", + "type": "entry" + }, + { + "id": "With_open_in_Python", + "type": "entry" + }, + { + "id": "Working_with_CSVs_in_Python", + "type": "entry" + }, + { + "id": "Working_with_JSON_in_Python", + "type": "entry" + }, + { + "id": "Working_with_directories_in_Python", + "type": "entry" + }, + { + "id": "Working_with_numbers_in_Bash", + "type": "entry" + }, + { + "id": "Writing_to_files_in_Python", + "type": "entry" + }, + { + "id": "Zero_property_of_multiplication", + "type": "entry" + }, + { + "id": "Zip_function_in_Python", + "type": "entry" + }, + { + "id": "a247fa9b_surveillance_capitalism_not_necessary", + "type": "entry" + }, + { + "id": "a4601796_trapdoor_functions", + "type": "entry" + }, + { + "id": "a771a6d9_attributes_of_internet_enclosure", + "type": "entry" + }, + { + "id": "bbdcb54f_public_key_cryptography", + "type": "entry" + }, + { + "id": "c301a0b3-1d8_Mosaic_Netscape_and_Browser_Wars", + "type": "entry" + }, + { + "id": "c8173d17_TIMPs", + "type": "entry" + }, + { + "id": "cfbef1c4_web_precursors", + "type": "entry" + }, + { + "id": "e470bf3d_IMPs_in_the_ARPANET", + "type": "entry" + }, + { + "id": "ecec56e6_precursors_to_search_engines", + "type": "entry" + }, + { + "id": "f0f70a3c_ARPANET_motivations", + "type": "entry" + }, + { + "id": "f6564af9_AOL_and_early_internet_enclosure", + "type": "entry" + }, + { + "id": "fbbfbc32-political-accommodation-inveigelment-surveillance-capitalism", + "type": "entry" + }, + { + "id": "fs", + "type": "entry" + }, + { + "id": "http_in_Node", + "type": "entry" + }, + { + "id": "journald", + "type": "entry" + }, + { + "id": "jq", + "type": "entry" + }, + { + "id": "ps", + "type": "entry" + }, + { + "id": "python_advent_learnings", + "type": "entry" + }, + { + "id": "systemd", + "type": "entry" + }, + { + "id": "systemd_status", + "type": "entry" + }, + { + "id": "v8", + "type": "entry" + } + ], + "edges": [ + { + "source": "#nand-to-tetris", + "target": "Hardware_abstraction_and_modularity" + }, + { + "source": "#question", + "target": "Memory_versus_processor" + }, + { + "source": "#AWS", + "target": "Elastic_Compute_Cloud" + }, + { + "source": "#graphql", + "target": "Mutations_with_Apollo_Client" + }, + { + "source": "#OOP", + "target": "Observer_pattern" + }, + { + "source": "#design-patterns", + "target": "Observer_pattern" + }, + { + "source": "#git", + "target": "Tags_in_Git" + }, + { + "source": "#python", + "target": "Passing_arguments_to_Python_scripts" + }, + { + "source": "#graphql", + "target": "Key_characteristics_of_GraphQL" + }, + { + "source": "#APIs", + "target": "Key_characteristics_of_GraphQL" + }, + { + "source": "#ecopolsoc", + "target": "0716531c_rewilding_the_internet" + }, + { + "source": "#internet", + "target": "0716531c_rewilding_the_internet" + }, + { + "source": "#memory", + "target": "Memory_addresses" + }, + { + "source": "#binary", + "target": "Signed_magnitude_representation" + }, + { + "source": "#AWS", + "target": "AWS_SNS" + }, + { + "source": "#SNS", + "target": "AWS_SNS" + }, + { + "source": "#SQS", + "target": "AWS_SNS" + }, + { + "source": "#shell", + "target": "Proper_shebang_syntax" + }, + { + "source": "#propositional-logic", + "target": "Boolean_algebra" + }, + { + "source": "#algebra", + "target": "Boolean_algebra" + }, + { + "source": "#nand-to-tetris", + "target": "Boolean_algebra" + }, + { + "source": "#logic", + "target": "Boolean_algebra" + }, + { + "source": "#node-js", + "target": "Package_management_in_NodeJS" + }, + { + "source": "#SQL", + "target": "Data_types_in_MySQL" + }, + { + "source": "#databases", + "target": "Data_types_in_MySQL" + }, + { + "source": "#data-types", + "target": "Data_types_in_MySQL" + }, + { + "source": "#AWS", + "target": "OpenSearch" + }, + { + "source": "#mongo-db", + "target": "MongoDB_Introduction" + }, + { + "source": "#databases", + "target": "MongoDB_Introduction" + }, + { + "source": "#physics", + "target": "Electrons" + }, + { + "source": "#electricity", + "target": "Electrons" + }, + { + "source": "#propositional-logic", + "target": "Conditional_Elimination" + }, + { + "source": "#logic", + "target": "Conditional_Elimination" + }, + { + "source": "#docker", + "target": "Containerization" + }, + { + "source": "#containerization", + "target": "Containerization" + }, + { + "source": "#Linux", + "target": "Containerization" + }, + { + "source": "#memory", + "target": "Call_stack" + }, + { + "source": "#javascript", + "target": "Call_stack" + }, + { + "source": "#memory", + "target": "The_memory_hierarchy" + }, + { + "source": "#ARPANET", + "target": "c8173d17_TIMPs" + }, + { + "source": "#networks", + "target": "c8173d17_TIMPs" + }, + { + "source": "#computer-history", + "target": "c8173d17_TIMPs" + }, + { + "source": "#git", + "target": "Interactive_staging" + }, + { + "source": "#OOP", + "target": "Module_pattern" + }, + { + "source": "#design-patterns", + "target": "Module_pattern" + }, + { + "source": "#typescript", + "target": "Custom_types_in_TypeScript" + }, + { + "source": "#disks", + "target": "Linux_disk_partitions" + }, + { + "source": "#Linux", + "target": "Linux_disk_partitions" + }, + { + "source": "#procedural", + "target": "Linux_disk_partitions" + }, + { + "source": "#prealgebra", + "target": "Reducing_fractions" + }, + { + "source": "#fractions", + "target": "Reducing_fractions" + }, + { + "source": "#python", + "target": "Using_SQLite_with_Python" + }, + { + "source": "#databases", + "target": "Using_SQLite_with_Python" + }, + { + "source": "#SQL", + "target": "Using_SQLite_with_Python" + }, + { + "source": "#SQLite", + "target": "Using_SQLite_with_Python" + }, + { + "source": "#git", + "target": "Git_rebasing" + }, + { + "source": "#prealgebra", + "target": "Dividing_fractions" + }, + { + "source": "#fractions", + "target": "Dividing_fractions" + }, + { + "source": "#propositional-logic", + "target": "Conjunction_Elimination" + }, + { + "source": "#logic", + "target": "Conjunction_Elimination" + }, + { + "source": "#networks", + "target": "Network_card" + }, + { + "source": "#hardware", + "target": "Network_card" + }, + { + "source": "#set-theory", + "target": "Basic_properties_of_sets" + }, + { + "source": "#memory", + "target": "What_is_memory" + }, + { + "source": "#prealgebra", + "target": "Natural_numbers" + }, + { + "source": "#computer-history", + "target": "Bolt_Beranek_and_Newman" + }, + { + "source": "#ARPANET", + "target": "Bolt_Beranek_and_Newman" + }, + { + "source": "#propositional-logic", + "target": "Disjunction_Elimination" + }, + { + "source": "#logic", + "target": "Disjunction_Elimination" + }, + { + "source": "#shell", + "target": "Awk" + }, + { + "source": "#awk", + "target": "Awk" + }, + { + "source": "#data-structures", + "target": "Queue" + }, + { + "source": "#logic", + "target": "Truth_tables" + }, + { + "source": "#propositional-logic", + "target": "Truth_tables" + }, + { + "source": "#systems-programming", + "target": "Disk_info" + }, + { + "source": "#disks", + "target": "Disk_info" + }, + { + "source": "#procedural", + "target": "Disk_info" + }, + { + "source": "#Linux", + "target": "Disk_info" + }, + { + "source": "#CPU", + "target": "CPU_architecture" + }, + { + "source": "#computer-architecture", + "target": "CPU_architecture" + }, + { + "source": "#python", + "target": "Python_package_management" + }, + { + "source": "#data-types", + "target": "Python_package_management" + }, + { + "source": "#AWS", + "target": "Local_AWS_development_with_SAM" + }, + { + "source": "#docker", + "target": "Local_AWS_development_with_SAM" + }, + { + "source": "#propositional-logic", + "target": "Truth_functional_connectives" + }, + { + "source": "#logic", + "target": "Truth_functional_connectives" + }, + { + "source": "#python", + "target": "Lists_in_Python" + }, + { + "source": "#data-structures", + "target": "Lists_in_Python" + }, + { + "source": "#algebra", + "target": "Algebra_key_terms" + }, + { + "source": "#networks", + "target": "IP_addresses" + }, + { + "source": "#internet", + "target": "IP_addresses" + }, + { + "source": "#shell", + "target": "Substrings_in_Bash" + }, + { + "source": "#node-js", + "target": "http_in_Node" + }, + { + "source": "#propositional-logic", + "target": "Disjunction_Introduction" + }, + { + "source": "#logic", + "target": "Disjunction_Introduction" + }, + { + "source": "#python", + "target": "Classes_in_Python" + }, + { + "source": "#OOP", + "target": "Classes_in_Python" + }, + { + "source": "#electronics", + "target": "Breadboards" + }, + { + "source": "#typescript", + "target": "Union_types_in_TS" + }, + { + "source": "#nand-to-tetris", + "target": "Hardware_Description_Language" + }, + { + "source": "#javascript", + "target": "React_useReducer" + }, + { + "source": "#react", + "target": "React_useReducer" + }, + { + "source": "#typescript", + "target": "Function_overloads" + }, + { + "source": "#python", + "target": "Network_requests_in_Python" + }, + { + "source": "#APIs", + "target": "Network_requests_in_Python" + }, + { + "source": "#networks", + "target": "Network_requests_in_Python" + }, + { + "source": "#internet", + "target": "Transport_Layer_of_Internet_Protocol" + }, + { + "source": "#networks", + "target": "Transport_Layer_of_Internet_Protocol" + }, + { + "source": "#ports", + "target": "Transport_Layer_of_Internet_Protocol" + }, + { + "source": "#set-theory", + "target": "Axioms_of_set_theory" + }, + { + "source": "#theorems", + "target": "Axioms_of_set_theory" + }, + { + "source": "#propositional-logic", + "target": "Conjunction_Introduction" + }, + { + "source": "#logic", + "target": "Conjunction_Introduction" + }, + { + "source": "#javascript", + "target": "React_useState" + }, + { + "source": "#react", + "target": "React_useState" + }, + { + "source": "#systems-programming", + "target": "The_kernel" + }, + { + "source": "#memory", + "target": "The_kernel" + }, + { + "source": "#operating-systems", + "target": "The_kernel" + }, + { + "source": "#computer-architecture", + "target": "The_kernel" + }, + { + "source": "#python", + "target": "Zip_function_in_Python" + }, + { + "source": "#data-structures", + "target": "Zip_function_in_Python" + }, + { + "source": "#node-js", + "target": "Event_loop" + }, + { + "source": "#data-structures", + "target": "Frequency_counters" + }, + { + "source": "#python", + "target": "Class_inheritance_in_Python" + }, + { + "source": "#OOP", + "target": "Class_inheritance_in_Python" + }, + { + "source": "#algorithms", + "target": "Algorithmic_complexity" + }, + { + "source": "#C", + "target": "Format_specifiers_in_C" + }, + { + "source": "#typescript", + "target": "Enums" + }, + { + "source": "#CPU", + "target": "The_Little_Man_computer" + }, + { + "source": "#python", + "target": "Python_modules_and_imports" + }, + { + "source": "#OOP", + "target": "Python_modules_and_imports" + }, + { + "source": "#node-js", + "target": "Process_module_in_NodeJS" + }, + { + "source": "#AWS", + "target": "Fetch_from_Secrets_Manager" + }, + { + "source": "#node-js", + "target": "Creating_a_RESTful_API_Introduction" + }, + { + "source": "#REST", + "target": "Creating_a_RESTful_API_Introduction" + }, + { + "source": "#APIs", + "target": "Creating_a_RESTful_API_Introduction" + }, + { + "source": "#python", + "target": "Loops_in_Python" + }, + { + "source": "#prealgebra", + "target": "Zero_property_of_multiplication" + }, + { + "source": "#theorems", + "target": "Zero_property_of_multiplication" + }, + { + "source": "#binary", + "target": "Twos_complement" + }, + { + "source": "#internet", + "target": "4a3dc316_key_figures_ARPANET" + }, + { + "source": "#ARPANET", + "target": "4a3dc316_key_figures_ARPANET" + }, + { + "source": "#ARPA", + "target": "4a3dc316_key_figures_ARPANET" + }, + { + "source": "#shell", + "target": "Find_Bash_command" + }, + { + "source": "#ecopolsoc", + "target": "a771a6d9_attributes_of_internet_enclosure" + }, + { + "source": "#internet", + "target": "a771a6d9_attributes_of_internet_enclosure" + }, + { + "source": "#graphql", + "target": "Schema_Definition_Language_in_GraphQL" + }, + { + "source": "#typescript", + "target": "Any" + }, + { + "source": "#git", + "target": "Viewing_remote_changes_without_merging" + }, + { + "source": "#APIs", + "target": "RESTful_APIs" + }, + { + "source": "#REST", + "target": "RESTful_APIs" + }, + { + "source": "#typescript", + "target": "Generics_in_TypeScript" + }, + { + "source": "#databases", + "target": "Relational_database_architecture" + }, + { + "source": "#binary", + "target": "Binary_number_system" + }, + { + "source": "#number-systems", + "target": "Binary_number_system" + }, + { + "source": "#question", + "target": "Torrenting" + }, + { + "source": "#networks", + "target": "Torrenting" + }, + { + "source": "#REST", + "target": "HTTP_request_types" + }, + { + "source": "#mongo-db", + "target": "Importing_MongoDB_data" + }, + { + "source": "#node-js", + "target": "Importing_MongoDB_data" + }, + { + "source": "#databases", + "target": "Importing_MongoDB_data" + }, + { + "source": "#javascript", + "target": "Application_state_management_with_React_hooks" + }, + { + "source": "#react", + "target": "Application_state_management_with_React_hooks" + }, + { + "source": "#docker", + "target": "Docker_compose_and_Dockerfile_difference" + }, + { + "source": "#shell", + "target": "Cron" + }, + { + "source": "#Linux", + "target": "Cron" + }, + { + "source": "#procedural", + "target": "Cron" + }, + { + "source": "#networks", + "target": "Network_packet_analysis_tools" + }, + { + "source": "#procedural", + "target": "Network_packet_analysis_tools" + }, + { + "source": "#javascript", + "target": "Map_and_filter_to_reduce_in_JS" + }, + { + "source": "#AWS", + "target": "Accessing_secrets_from_a_Lambda" + }, + { + "source": "#aws-lambda", + "target": "Accessing_secrets_from_a_Lambda" + }, + { + "source": "#OOP", + "target": "Singleton_pattern" + }, + { + "source": "#design-patterns", + "target": "Singleton_pattern" + }, + { + "source": "#fleeting", + "target": "cfbef1c4_web_precursors" + }, + { + "source": "#modems", + "target": "cfbef1c4_web_precursors" + }, + { + "source": "#computer-history", + "target": "cfbef1c4_web_precursors" + }, + { + "source": "#internet", + "target": "cfbef1c4_web_precursors" + }, + { + "source": "#bulletin-boards", + "target": "cfbef1c4_web_precursors" + }, + { + "source": "#fleeting", + "target": "385af4b4_Baran_distributed_networks" + }, + { + "source": "#networks", + "target": "385af4b4_Baran_distributed_networks" + }, + { + "source": "#ARPANET", + "target": "385af4b4_Baran_distributed_networks" + }, + { + "source": "#packet-switching", + "target": "385af4b4_Baran_distributed_networks" + }, + { + "source": "#shell", + "target": "File_permissions_and_execution_in_Bash" + }, + { + "source": "#prealgebra", + "target": "Inversion_of_operators" + }, + { + "source": "#networks", + "target": "Internet_fundamentals" + }, + { + "source": "#internet", + "target": "What_can_the_ISP_see" + }, + { + "source": "#encryption", + "target": "What_can_the_ISP_see" + }, + { + "source": "#privacy", + "target": "What_can_the_ISP_see" + }, + { + "source": "#TOR", + "target": "What_can_the_ISP_see" + }, + { + "source": "#AWS", + "target": "Step_functions_and_state_machines" + }, + { + "source": "#python", + "target": "Python_interpreter" + }, + { + "source": "#logic-gates", + "target": "Latches" + }, + { + "source": "#binary", + "target": "Latches" + }, + { + "source": "#memory", + "target": "Latches" + }, + { + "source": "#git", + "target": "Stale_branches_and_pruning" + }, + { + "source": "#data-structures", + "target": "Stacks" + }, + { + "source": "#networks", + "target": "Network_scanning" + }, + { + "source": "#procedural", + "target": "Network_scanning" + }, + { + "source": "#Linux", + "target": "Network_scanning" + }, + { + "source": "#world-wide-web", + "target": "3f1b9fe5_motivation_Berners_Lee" + }, + { + "source": "#internet", + "target": "3f1b9fe5_motivation_Berners_Lee" + }, + { + "source": "#binary", + "target": "Clock_signals" + }, + { + "source": "#memory", + "target": "Clock_signals" + }, + { + "source": "#electromagnetism", + "target": "Clock_signals" + }, + { + "source": "#hardware", + "target": "Clock_signals" + }, + { + "source": "#databases", + "target": "Database_indices" + }, + { + "source": "#python", + "target": "Type_hinting" + }, + { + "source": "#data-types", + "target": "Type_hinting" + }, + { + "source": "#operating-systems", + "target": "User_Space" + }, + { + "source": "#shell", + "target": "Shell_sessions" + }, + { + "source": "#electronics", + "target": "Push_buttons" + }, + { + "source": "#SQL", + "target": "Wildcards_in_SQL" + }, + { + "source": "#databases", + "target": "Wildcards_in_SQL" + }, + { + "source": "#javascript", + "target": "Memoization_in_React" + }, + { + "source": "#react", + "target": "Memoization_in_React" + }, + { + "source": "#AWS", + "target": "API_Gateway" + }, + { + "source": "#APIs", + "target": "API_Gateway" + }, + { + "source": "#computer-history", + "target": "Bell_System" + }, + { + "source": "#disks", + "target": "Filesystems" + }, + { + "source": "#computer-architecture", + "target": "Filesystems" + }, + { + "source": "#operating-systems", + "target": "Filesystems" + }, + { + "source": "#binary", + "target": "Binary_arithmetic" + }, + { + "source": "#typescript", + "target": "Classes" + }, + { + "source": "#OOP", + "target": "Classes" + }, + { + "source": "#docker", + "target": "Connecting_a_frontend_to_a_Docker_backend" + }, + { + "source": "#node-js", + "target": "Connecting_a_frontend_to_a_Docker_backend" + }, + { + "source": "#logic", + "target": "Biconditional_Elimination" + }, + { + "source": "#physics", + "target": "Cells_and_batteries" + }, + { + "source": "#electricity", + "target": "Cells_and_batteries" + }, + { + "source": "#docker", + "target": "Docker_storage" + }, + { + "source": "#propositional-logic", + "target": "Logical_equivalence" + }, + { + "source": "#logic", + "target": "Logical_equivalence" + }, + { + "source": "#docker", + "target": "Docker_images" + }, + { + "source": "#mongo-db", + "target": "Validating_Mongoose_schemas" + }, + { + "source": "#mongoose", + "target": "Validating_Mongoose_schemas" + }, + { + "source": "#node-js", + "target": "Validating_Mongoose_schemas" + }, + { + "source": "#databases", + "target": "Validating_Mongoose_schemas" + }, + { + "source": "#node-js", + "target": "Middleware_in_NodeJS" + }, + { + "source": "#middleware", + "target": "Middleware_in_NodeJS" + }, + { + "source": "#javascript", + "target": "React_application_structure" + }, + { + "source": "#react", + "target": "React_application_structure" + }, + { + "source": "#propositional-logic", + "target": "Logical_consistency" + }, + { + "source": "#logic", + "target": "Logical_consistency" + }, + { + "source": "#python", + "target": "Sorting_lists_in_Python" + }, + { + "source": "#internet", + "target": "4da22434_from_ARPANET_to_Internet" + }, + { + "source": "#ARPANET", + "target": "4da22434_from_ARPANET_to_Internet" + }, + { + "source": "#graphql", + "target": "Using_arguments_with_Apollo_Client" + }, + { + "source": "#shell", + "target": "Symlinks" + }, + { + "source": "#Linux", + "target": "Symlinks" + }, + { + "source": "#procedural", + "target": "Symlinks" + }, + { + "source": "#networks", + "target": "Network_fundamentals" + }, + { + "source": "#network-protocols", + "target": "Network_fundamentals" + }, + { + "source": "#networks", + "target": "Peer_to_peer_network" + }, + { + "source": "#logic-gates", + "target": "Multiplexers_and_demultiplexers" + }, + { + "source": "#binary", + "target": "Multiplexers_and_demultiplexers" + }, + { + "source": "#nand-to-tetris", + "target": "Multiplexers_and_demultiplexers" + }, + { + "source": "#logic", + "target": "Negation_Elimination" + }, + { + "source": "#propositional-logic", + "target": "Negation_Elimination" + }, + { + "source": "#binary", + "target": "Machine_code" + }, + { + "source": "#CPU", + "target": "Machine_code" + }, + { + "source": "#hardware", + "target": "Machine_code" + }, + { + "source": "#computer-architecture", + "target": "Machine_code" + }, + { + "source": "#mongo-db", + "target": "Troubleshooting_MongoDB" + }, + { + "source": "#world-wide-web", + "target": "c301a0b3-1d8_Mosaic_Netscape_and_Browser_Wars" + }, + { + "source": "#computer-history", + "target": "c301a0b3-1d8_Mosaic_Netscape_and_Browser_Wars" + }, + { + "source": "#Microsoft", + "target": "c301a0b3-1d8_Mosaic_Netscape_and_Browser_Wars" + }, + { + "source": "#literature", + "target": "Weaving_the_Web_Berners_Lee" + }, + { + "source": "#ecosolpoc", + "target": "Weaving_the_Web_Berners_Lee" + }, + { + "source": "#world-wide-web", + "target": "Weaving_the_Web_Berners_Lee" + }, + { + "source": "#git", + "target": "Git_bisect" + }, + { + "source": "#world-wide-web", + "target": "Architecture_of_the_World_Wide_Web" + }, + { + "source": "#internet", + "target": "Architecture_of_the_World_Wide_Web" + }, + { + "source": "#mongo-db", + "target": "Modelling_relationships_in_MongoDB" + }, + { + "source": "#node-js", + "target": "Modelling_relationships_in_MongoDB" + }, + { + "source": "#mongoose", + "target": "Modelling_relationships_in_MongoDB" + }, + { + "source": "#databases", + "target": "Modelling_relationships_in_MongoDB" + }, + { + "source": "#fleeting", + "target": "861cc26e_ARPA_origins" + }, + { + "source": "#computer-history", + "target": "861cc26e_ARPA_origins" + }, + { + "source": "#ARPA", + "target": "861cc26e_ARPA_origins" + }, + { + "source": "#AWS", + "target": "Practical_walkthrough_Lambda_creation_within_AWS" + }, + { + "source": "#aws-lambda", + "target": "Practical_walkthrough_Lambda_creation_within_AWS" + }, + { + "source": "#node-js", + "target": "Practical_walkthrough_Lambda_creation_within_AWS" + }, + { + "source": "#prealgebra", + "target": "Formal_conventions" + }, + { + "source": "#prealgebra", + "target": "Equivalent_fractions" + }, + { + "source": "#fractions", + "target": "Equivalent_fractions" + }, + { + "source": "#bus", + "target": "Bus" + }, + { + "source": "#computer-architecture", + "target": "Bus" + }, + { + "source": "#shell", + "target": "Killing_processes" + }, + { + "source": "#procedural", + "target": "Killing_processes" + }, + { + "source": "#logic-gates", + "target": "Creating_memory_with_NAND" + }, + { + "source": "#binary", + "target": "Creating_memory_with_NAND" + }, + { + "source": "#memory", + "target": "Creating_memory_with_NAND" + }, + { + "source": "#shell", + "target": "Loops_in_bash" + }, + { + "source": "#python", + "target": "Testing_Python_code" + }, + { + "source": "#testing", + "target": "Testing_Python_code" + }, + { + "source": "#computer-architecture", + "target": "GPU_versus_CPU" + }, + { + "source": "#prealgebra", + "target": "Increasing_fractions_to_their_highest_terms" + }, + { + "source": "#fractions", + "target": "Increasing_fractions_to_their_highest_terms" + }, + { + "source": "#python", + "target": "Python_application_structure" + }, + { + "source": "#operating-systems", + "target": "Daemons" + }, + { + "source": "#prealgebra", + "target": "Multiplicative_identity" + }, + { + "source": "#theorems", + "target": "Multiplicative_identity" + }, + { + "source": "#theorems", + "target": "Commutative_Property_of_Addition_and_Multiplication" + }, + { + "source": "#algebra", + "target": "Commutative_Property_of_Addition_and_Multiplication" + }, + { + "source": "#number-theory", + "target": "Commutative_Property_of_Addition_and_Multiplication" + }, + { + "source": "#git", + "target": "Difference_between_remote_origin_and_head" + }, + { + "source": "#shell", + "target": "Quote_marks_in_Bash" + }, + { + "source": "#memory", + "target": "Register_and_cache_memory" + }, + { + "source": "#CPU", + "target": "Register_and_cache_memory" + }, + { + "source": "#analogue", + "target": "Analogue_and_digital" + }, + { + "source": "#SQL", + "target": "Update_an_SQL_table" + }, + { + "source": "#databases", + "target": "Update_an_SQL_table" + }, + { + "source": "#prealgebra", + "target": "Factors_and_divisors" + }, + { + "source": "#databases", + "target": "SQLite" + }, + { + "source": "#SQL", + "target": "SQLite" + }, + { + "source": "#SQLite", + "target": "SQLite" + }, + { + "source": "#node-js", + "target": "Morgan" + }, + { + "source": "#middleware", + "target": "Morgan" + }, + { + "source": "#logic", + "target": "Negation_Introduction" + }, + { + "source": "#propositional-logic", + "target": "Negation_Introduction" + }, + { + "source": "#python", + "target": "Iterating_through_complex_data_structures_in_Python" + }, + { + "source": "#python", + "target": "Lambdas_in_Python" + }, + { + "source": "#aws-lambda", + "target": "Lambdas_in_Python" + }, + { + "source": "#AWS", + "target": "Lambdas_in_Python" + }, + { + "source": "#mongo-db", + "target": "Create_Mongo_database" + }, + { + "source": "#node-js", + "target": "Create_Mongo_database" + }, + { + "source": "#mongoose", + "target": "Create_Mongo_database" + }, + { + "source": "#databases", + "target": "Create_Mongo_database" + }, + { + "source": "#javascript", + "target": "Prop_types_in_React" + }, + { + "source": "#react", + "target": "Prop_types_in_React" + }, + { + "source": "#data-types", + "target": "Prop_types_in_React" + }, + { + "source": "#Linux", + "target": "User_management_in_Linux" + }, + { + "source": "#procedural", + "target": "User_management_in_Linux" + }, + { + "source": "#shell", + "target": "Redirect_to_dev_null" + }, + { + "source": "#physics", + "target": "Matter_and_atoms" + }, + { + "source": "#python", + "target": "Working_with_directories_in_Python" + }, + { + "source": "#file-system", + "target": "Working_with_directories_in_Python" + }, + { + "source": "#procedural", + "target": "Working_with_directories_in_Python" + }, + { + "source": "#docker", + "target": "Docker_general_overview" + }, + { + "source": "#containerization", + "target": "Docker_general_overview" + }, + { + "source": "#algebra", + "target": "Equivalent_equations" + }, + { + "source": "#propositional-logic", + "target": "Object_language_and_meta_language" + }, + { + "source": "#logic", + "target": "Object_language_and_meta_language" + }, + { + "source": "#SQL", + "target": "Regular_expressions_in_SQL" + }, + { + "source": "#regex", + "target": "Regular_expressions_in_SQL" + }, + { + "source": "#databases", + "target": "Regular_expressions_in_SQL" + }, + { + "source": "#algebra", + "target": "Logarithms" + }, + { + "source": "#typescript", + "target": "Unknown_type_in_TS" + }, + { + "source": "#propositional-logic", + "target": "Logical_truth_and_falsity" + }, + { + "source": "#logic", + "target": "Logical_truth_and_falsity" + }, + { + "source": "#git", + "target": "Remote_tracking_branches" + }, + { + "source": "#typescript", + "target": "Typing_built_in_React_hooks" + }, + { + "source": "#react", + "target": "Typing_built_in_React_hooks" + }, + { + "source": "#physics", + "target": "Coulombs_Laws" + }, + { + "source": "#electricity", + "target": "Coulombs_Laws" + }, + { + "source": "#node-js", + "target": "Modules_in_NodeJS" + }, + { + "source": "#python", + "target": "Writing_to_files_in_Python" + }, + { + "source": "#file-system", + "target": "Writing_to_files_in_Python" + }, + { + "source": "#procedural", + "target": "Writing_to_files_in_Python" + }, + { + "source": "#node-js", + "target": "Streams_in_NodeJS" + }, + { + "source": "#python", + "target": "Numbers_in_Python" + }, + { + "source": "#data-types", + "target": "Numbers_in_Python" + }, + { + "source": "#node-js", + "target": "Creating_a_RESTful_API_PUT" + }, + { + "source": "#REST", + "target": "Creating_a_RESTful_API_PUT" + }, + { + "source": "#APIs", + "target": "Creating_a_RESTful_API_PUT" + }, + { + "source": "#design-patterns", + "target": "Command_pattern" + }, + { + "source": "#javascript", + "target": "Components_props_classes" + }, + { + "source": "#react", + "target": "Components_props_classes" + }, + { + "source": "#git", + "target": "Cherry_picking" + }, + { + "source": "#javascript", + "target": "React_useContext" + }, + { + "source": "#react", + "target": "React_useContext" + }, + { + "source": "#physics", + "target": "Voltage_sources" + }, + { + "source": "#electricity", + "target": "Voltage_sources" + }, + { + "source": "#theorems", + "target": "Additive_inverse_property" + }, + { + "source": "#world-wide-web", + "target": "User_agent" + }, + { + "source": "#Linux", + "target": "Save_readonly_Vim_file" + }, + { + "source": "#procedural", + "target": "Save_readonly_Vim_file" + }, + { + "source": "#computer-history", + "target": "Batch_processing" + }, + { + "source": "#CPU", + "target": "Relation_between_kernel_and_CPU" + }, + { + "source": "#computer-architecture", + "target": "Relation_between_kernel_and_CPU" + }, + { + "source": "#operating-systems", + "target": "Relation_between_kernel_and_CPU" + }, + { + "source": "#hardware", + "target": "Motherboard" + }, + { + "source": "#computer-architecture", + "target": "Motherboard" + }, + { + "source": "#data-structures", + "target": "Arrays" + }, + { + "source": "#computer-history", + "target": "Williams_Tube_memory" + }, + { + "source": "#memory", + "target": "Williams_Tube_memory" + }, + { + "source": "#node-js", + "target": "Managing_environments_in_NodeJS" + }, + { + "source": "#OOP", + "target": "Dependency_injection" + }, + { + "source": "#number-systems", + "target": "Hexadecimal_number_system" + }, + { + "source": "#computer-architecture", + "target": "Hexadecimal_number_system" + }, + { + "source": "#mongo-db", + "target": "MongoDB_connection" + }, + { + "source": "#node-js", + "target": "MongoDB_connection" + }, + { + "source": "#mongoose", + "target": "MongoDB_connection" + }, + { + "source": "#databases", + "target": "MongoDB_connection" + }, + { + "source": "#internet", + "target": "Application_Layer_of_Internet_Protocol" + }, + { + "source": "#networks", + "target": "Application_Layer_of_Internet_Protocol" + }, + { + "source": "#node-js", + "target": "Structuring_Express_applications" + }, + { + "source": "#REST", + "target": "Structuring_Express_applications" + }, + { + "source": "#APIs", + "target": "Structuring_Express_applications" + }, + { + "source": "#networks", + "target": "Network_protocols" + }, + { + "source": "#node-js", + "target": "v8" + }, + { + "source": "#Linux", + "target": "Compile_from_source" + }, + { + "source": "#procedural", + "target": "Compile_from_source" + }, + { + "source": "#typescript", + "target": "Intersection_types_in_TypeScript" + }, + { + "source": "#mongo-db", + "target": "Adding_documents_to_a_Mongo_collection" + }, + { + "source": "#node-js", + "target": "Adding_documents_to_a_Mongo_collection" + }, + { + "source": "#mongoose", + "target": "Adding_documents_to_a_Mongo_collection" + }, + { + "source": "#databases", + "target": "Adding_documents_to_a_Mongo_collection" + }, + { + "source": "#shell", + "target": "Test_values_in_Bash" + }, + { + "source": "#regex", + "target": "Test_values_in_Bash" + }, + { + "source": "#systems-programming", + "target": "Create_timed_systemd_job" + }, + { + "source": "#systemd", + "target": "Create_timed_systemd_job" + }, + { + "source": "#Linux", + "target": "Create_timed_systemd_job" + }, + { + "source": "#procedural", + "target": "Create_timed_systemd_job" + }, + { + "source": "#shell", + "target": "Environmental_and_shell_variables" + }, + { + "source": "#docker", + "target": "Creating_a_Docker_image" + }, + { + "source": "#prealgebra", + "target": "Integers" + }, + { + "source": "#ARPANET", + "target": "653c0b1d_host_protocols_of_ARPANET" + }, + { + "source": "#computer-history", + "target": "653c0b1d_host_protocols_of_ARPANET" + }, + { + "source": "#networks", + "target": "653c0b1d_host_protocols_of_ARPANET" + }, + { + "source": "#javascript", + "target": "Components_props_hooks_in_React" + }, + { + "source": "#react", + "target": "Components_props_hooks_in_React" + }, + { + "source": "#prealgebra", + "target": "Rules_for_operations_on_like_and_unlike_terms" + }, + { + "source": "#shell", + "target": "Text_manipulation_in_Bash" + }, + { + "source": "#ecopolsoc", + "target": "a247fa9b_surveillance_capitalism_not_necessary" + }, + { + "source": "#internet", + "target": "a247fa9b_surveillance_capitalism_not_necessary" + }, + { + "source": "#surveillance-capitalism", + "target": "a247fa9b_surveillance_capitalism_not_necessary" + }, + { + "source": "#operating-systems", + "target": "Basic_model_of_the_operating_system" + }, + { + "source": "#Linux", + "target": "Basic_model_of_the_operating_system" + }, + { + "source": "#shell", + "target": "Bash_file_exists" + }, + { + "source": "#databases", + "target": "Role_of_unique_key_in_relational_databases" + }, + { + "source": "#javascript", + "target": "Custom_React_hook_examples" + }, + { + "source": "#react", + "target": "Custom_React_hook_examples" + }, + { + "source": "#networks", + "target": "Bluetooth" + }, + { + "source": "#procedural", + "target": "Bluetooth" + }, + { + "source": "#Linux", + "target": "Bluetooth" + }, + { + "source": "#python", + "target": "Dictionaries_in_Python" + }, + { + "source": "#data-structures", + "target": "Dictionaries_in_Python" + }, + { + "source": "#algebra", + "target": "Negative_exponents" + }, + { + "source": "#exponents", + "target": "Negative_exponents" + }, + { + "source": "#memory", + "target": "DRAM_and_SRAM_memory" + }, + { + "source": "#hardware", + "target": "DRAM_and_SRAM_memory" + }, + { + "source": "#python", + "target": "Appending_to_files_in_Python" + }, + { + "source": "#file-system", + "target": "Appending_to_files_in_Python" + }, + { + "source": "#procedural", + "target": "Appending_to_files_in_Python" + }, + { + "source": "#prealgebra", + "target": "Prime_factorization" + }, + { + "source": "#number-theory", + "target": "Prime_factorization" + }, + { + "source": "#algebra", + "target": "Exponents" + }, + { + "source": "#exponents", + "target": "Exponents" + }, + { + "source": "#binary", + "target": "Binary_encoding" + }, + { + "source": "#SQL", + "target": "Retrieve_data_from_SQL_table" + }, + { + "source": "#databases", + "target": "Retrieve_data_from_SQL_table" + }, + { + "source": "#SQL", + "target": "Aggregate_functions_in_SQL" + }, + { + "source": "#databases", + "target": "Aggregate_functions_in_SQL" + }, + { + "source": "#prealgebra", + "target": "Fundamental_Theorem_of_Arithmetic" + }, + { + "source": "#theorems", + "target": "Fundamental_Theorem_of_Arithmetic" + }, + { + "source": "#git", + "target": "Effective_logging_in_Git" + }, + { + "source": "#procedural", + "target": "Effective_logging_in_Git" + }, + { + "source": "#typescript", + "target": "Functions" + }, + { + "source": "#react", + "target": "Functions" + }, + { + "source": "#python", + "target": "Sets_in_Python" + }, + { + "source": "#data-structures", + "target": "Sets_in_Python" + }, + { + "source": "#shell", + "target": "File_descriptors" + }, + { + "source": "#networks", + "target": "Network_hosts" + }, + { + "source": "#logic-gates", + "target": "Half_adder_and_full_adder" + }, + { + "source": "#binary", + "target": "Half_adder_and_full_adder" + }, + { + "source": "#binary", + "target": "Binary_units_of_measurement" + }, + { + "source": "#javascript", + "target": "React_useEffect" + }, + { + "source": "#react", + "target": "React_useEffect" + }, + { + "source": "#python", + "target": "With_open_in_Python" + }, + { + "source": "#propositional-logic", + "target": "Corresponding_material_and_biconditional" + }, + { + "source": "#logic", + "target": "Corresponding_material_and_biconditional" + }, + { + "source": "#theorems", + "target": "DeMorgan's_Laws" + }, + { + "source": "#logic", + "target": "DeMorgan's_Laws" + }, + { + "source": "#propositional-logic", + "target": "DeMorgan's_Laws" + }, + { + "source": "#python", + "target": "Tuples_in_Python" + }, + { + "source": "#data-structures", + "target": "Tuples_in_Python" + }, + { + "source": "#propositional-logic", + "target": "Strategies_for_constructing_proofs" + }, + { + "source": "#logic", + "target": "Strategies_for_constructing_proofs" + }, + { + "source": "#typescript", + "target": "Type_guarding_and_narrowing_in_TS" + }, + { + "source": "#operating-systems", + "target": "Processes" + }, + { + "source": "#memory", + "target": "Memory_leaks" + }, + { + "source": "#git", + "target": "Delete_a_branch" + }, + { + "source": "#databases", + "target": "Views_in_relational_databases" + }, + { + "source": "#AWS", + "target": "AWS_SQS_SDK" + }, + { + "source": "#SQS", + "target": "AWS_SQS_SDK" + }, + { + "source": "#docker", + "target": "Docker_containers" + }, + { + "source": "#containerization", + "target": "Docker_containers" + }, + { + "source": "#shell", + "target": "Data_types_in_Bash" + }, + { + "source": "#data-types", + "target": "Data_types_in_Bash" + }, + { + "source": "#shell", + "target": "Functions_in_Bash" + }, + { + "source": "#memory", + "target": "Memory_Management_Unit" + }, + { + "source": "#Linux", + "target": "Memory_Management_Unit" + }, + { + "source": "#AWS", + "target": "Database_options_on_AWS" + }, + { + "source": "#databases", + "target": "Database_options_on_AWS" + }, + { + "source": "#dynamodb", + "target": "Database_options_on_AWS" + }, + { + "source": "#propositional-logic", + "target": "Formal_proofs_in_propositional_logic" + }, + { + "source": "#logic", + "target": "Formal_proofs_in_propositional_logic" + }, + { + "source": "#propositional-logic", + "target": "Law_of_Non_Contradiction" + }, + { + "source": "#logic", + "target": "Law_of_Non_Contradiction" + }, + { + "source": "#javascript", + "target": "Lifecycle_methods" + }, + { + "source": "#react", + "target": "Lifecycle_methods" + }, + { + "source": "#encryption", + "target": "bbdcb54f_public_key_cryptography" + }, + { + "source": "#cryptography", + "target": "bbdcb54f_public_key_cryptography" + }, + { + "source": "#systems-programming", + "target": "systemd" + }, + { + "source": "#Linux", + "target": "systemd" + }, + { + "source": "#procedural", + "target": "systemd" + }, + { + "source": "#systemd", + "target": "systemd" + }, + { + "source": "#operating-systems", + "target": "systemd" + }, + { + "source": "#algebra", + "target": "Solving_equations" + }, + { + "source": "#javascript", + "target": "Iterating_in_React" + }, + { + "source": "#react", + "target": "Iterating_in_React" + }, + { + "source": "#AWS", + "target": "SAM" + }, + { + "source": "#python", + "target": "Compile_Python_app_to_single_executable" + }, + { + "source": "#procedural", + "target": "Compile_Python_app_to_single_executable" + }, + { + "source": "#shell", + "target": "Working_with_numbers_in_Bash" + }, + { + "source": "#json", + "target": "jq" + }, + { + "source": "#shell", + "target": "jq" + }, + { + "source": "#javascript", + "target": "Testing_basic_prop_passing_in_React" + }, + { + "source": "#react", + "target": "Testing_basic_prop_passing_in_React" + }, + { + "source": "#testing", + "target": "Testing_basic_prop_passing_in_React" + }, + { + "source": "#python", + "target": "Error_handling_in_Python" + }, + { + "source": "#propositional-logic", + "target": "Syntax_of_propositional_logic" + }, + { + "source": "#logic", + "target": "Syntax_of_propositional_logic" + }, + { + "source": "#electronics", + "target": "LEDs" + }, + { + "source": "#logic-gates", + "target": "Transistors" + }, + { + "source": "#binary", + "target": "Transistors" + }, + { + "source": "#electronics", + "target": "Transistors" + }, + { + "source": "#typescript", + "target": "React_Components" + }, + { + "source": "#react", + "target": "React_Components" + }, + { + "source": "#shell", + "target": "Read_command__in_Bash" + }, + { + "source": "#memory", + "target": "VirtualMemory" + }, + { + "source": "#Linux", + "target": "VirtualMemory" + }, + { + "source": "#kernel", + "target": "VirtualMemory" + }, + { + "source": "#AWS", + "target": "Virtual_private_cloud" + }, + { + "source": "#networks", + "target": "Virtual_private_cloud" + }, + { + "source": "#node-js", + "target": "Creating_a_RESTful_API_GET" + }, + { + "source": "#REST", + "target": "Creating_a_RESTful_API_GET" + }, + { + "source": "#APIs", + "target": "Creating_a_RESTful_API_GET" + }, + { + "source": "#propositional-logic", + "target": "Atomic_and_molecular_propositions" + }, + { + "source": "#logic", + "target": "Atomic_and_molecular_propositions" + }, + { + "source": "#physics", + "target": "Ohms_Law" + }, + { + "source": "#electricity", + "target": "Ohms_Law" + }, + { + "source": "#logic", + "target": "Biconditional_Introduction" + }, + { + "source": "#python", + "target": "Invoking_the_shell_in_Python" + }, + { + "source": "#shell", + "target": "Invoking_the_shell_in_Python" + }, + { + "source": "#shell", + "target": "Listing_and_navigating_directories_in_the_Shell" + }, + { + "source": "#physics", + "target": "Current" + }, + { + "source": "#electricity", + "target": "Current" + }, + { + "source": "#node-js", + "target": "Global_object_in_NodeJS" + }, + { + "source": "#AWS", + "target": "Lambda_programming_model" + }, + { + "source": "#aws-lambda", + "target": "Lambda_programming_model" + }, + { + "source": "#mongo-db", + "target": "Querying_a_Mongo_collection" + }, + { + "source": "#node-js", + "target": "Querying_a_Mongo_collection" + }, + { + "source": "#mongoose", + "target": "Querying_a_Mongo_collection" + }, + { + "source": "#databases", + "target": "Querying_a_Mongo_collection" + }, + { + "source": "#shell", + "target": "ps" + }, + { + "source": "#Linux", + "target": "ps" + }, + { + "source": "#operating-systems", + "target": "Operating_system_API" + }, + { + "source": "#shell", + "target": "Intro_to_the_Unix_shell" + }, + { + "source": "#memory", + "target": "Swap_space" + }, + { + "source": "#disks", + "target": "Swap_space" + }, + { + "source": "#Linux", + "target": "Swap_space" + }, + { + "source": "#operating-systems", + "target": "Swap_space" + }, + { + "source": "#shell", + "target": "Expansions_and_substitutions" + }, + { + "source": "#propositional-logic", + "target": "Boolean_functions" + }, + { + "source": "#nand-to-tetris", + "target": "Boolean_functions" + }, + { + "source": "#logic", + "target": "Boolean_functions" + }, + { + "source": "#computer-history", + "target": "Mainframe_computers" + }, + { + "source": "#typescript", + "target": "Mapped_types_in_TS" + }, + { + "source": "#shell", + "target": "Case_statements_in_Bash" + }, + { + "source": "#sound", + "target": "Audio_file_formats" + }, + { + "source": "#binary", + "target": "Audio_file_formats" + }, + { + "source": "#javascript", + "target": "Child_to_parent_data_flow_in_React" + }, + { + "source": "#react", + "target": "Child_to_parent_data_flow_in_React" + }, + { + "source": "#python", + "target": "File_operations_in_Python" + }, + { + "source": "#file-system", + "target": "File_operations_in_Python" + }, + { + "source": "#procedural", + "target": "File_operations_in_Python" + }, + { + "source": "#logic-gates", + "target": "Four_bit_adder" + }, + { + "source": "#binary", + "target": "Four_bit_adder" + }, + { + "source": "#prealgebra", + "target": "Mixed_and_improper_fractions" + }, + { + "source": "#fractions", + "target": "Mixed_and_improper_fractions" + }, + { + "source": "#binary", + "target": "Signed_and_unsigned_numbers" + }, + { + "source": "#theorems", + "target": "Additive_identity" + }, + { + "source": "#graphql", + "target": "Using_GraphQL_with_Node" + }, + { + "source": "#node-js", + "target": "Using_GraphQL_with_Node" + }, + { + "source": "#theory-of-computation", + "target": "Turing_machines" + }, + { + "source": "#Turing", + "target": "Turing_machines" + }, + { + "source": "#procedural", + "target": "Network_debugging" + }, + { + "source": "#Linux", + "target": "Network_debugging" + }, + { + "source": "#networks", + "target": "Network_debugging" + }, + { + "source": "#systems-programming", + "target": "journald" + }, + { + "source": "#Linux", + "target": "journald" + }, + { + "source": "#procedural", + "target": "journald" + }, + { + "source": "#SQL", + "target": "Create_an_SQL_table" + }, + { + "source": "#databases", + "target": "Create_an_SQL_table" + }, + { + "source": "#python", + "target": "Strings_in_Python" + }, + { + "source": "#data-types", + "target": "Strings_in_Python" + }, + { + "source": "#AWS", + "target": "AWS_architecture_hierarchy" + }, + { + "source": "#AWS", + "target": "Lambda_handler_function" + }, + { + "source": "#aws-lambda", + "target": "Lambda_handler_function" + }, + { + "source": "#shell", + "target": "Utilities_operators_flags" + }, + { + "source": "#networks", + "target": "Example_scenario_internet_data_transfer" + }, + { + "source": "#internet", + "target": "Example_scenario_internet_data_transfer" + }, + { + "source": "#SQL", + "target": "Insert_data_into_SQL_table" + }, + { + "source": "#databases", + "target": "Insert_data_into_SQL_table" + }, + { + "source": "#prealgebra", + "target": "Add_Subtract_Fractions" + }, + { + "source": "#fractions", + "target": "Add_Subtract_Fractions" + }, + { + "source": "#javascript", + "target": "Forms_in_React" + }, + { + "source": "#react", + "target": "Forms_in_React" + }, + { + "source": "#design-patterns", + "target": "Multiple_pointers" + }, + { + "source": "#mongo-db", + "target": "Deleting_Mongo_documents" + }, + { + "source": "#node-js", + "target": "Deleting_Mongo_documents" + }, + { + "source": "#mongoose", + "target": "Deleting_Mongo_documents" + }, + { + "source": "#databases", + "target": "Deleting_Mongo_documents" + }, + { + "source": "#javascript", + "target": "Testing_with_Jest" + }, + { + "source": "#testing", + "target": "Testing_with_Jest" + }, + { + "source": "#jest", + "target": "Testing_with_Jest" + }, + { + "source": "#python", + "target": "Map_and_filter_in_Python" + }, + { + "source": "#python", + "target": "List_comprehension_in_Python" + }, + { + "source": "#physics", + "target": "Ground" + }, + { + "source": "#electricity", + "target": "Ground" + }, + { + "source": "#typescript", + "target": "Further_examples_of_TS_generics" + }, + { + "source": "#AWS", + "target": "Lambda_triggers" + }, + { + "source": "#aws-lambda", + "target": "Lambda_triggers" + }, + { + "source": "#world-wide-web", + "target": "ecec56e6_precursors_to_search_engines" + }, + { + "source": "#computer-history", + "target": "ecec56e6_precursors_to_search_engines" + }, + { + "source": "#yaml", + "target": "Guide_to_YAML" + }, + { + "source": "#node-js", + "target": "Ports_in_NodeJS" + }, + { + "source": "#python", + "target": "Python_data_types" + }, + { + "source": "#data-types", + "target": "Python_data_types" + }, + { + "source": "#binary", + "target": "Bitwise_operators" + }, + { + "source": "#propositional-logic", + "target": "Logical_indeterminacy" + }, + { + "source": "#logic", + "target": "Logical_indeterminacy" + }, + { + "source": "#computer-history", + "target": "Magnetic_tape" + }, + { + "source": "#storage", + "target": "Magnetic_tape" + }, + { + "source": "#typescript", + "target": "Props_in_React" + }, + { + "source": "#react", + "target": "Props_in_React" + }, + { + "source": "#CPU", + "target": "Instruction_set_architectures" + }, + { + "source": "#python", + "target": "Switch_between_Python_vers" + }, + { + "source": "#shell", + "target": "Variable_indirection_in_Bash" + }, + { + "source": "#systemd", + "target": "systemd_status" + }, + { + "source": "#systems-programming", + "target": "systemd_status" + }, + { + "source": "#Linux", + "target": "systemd_status" + }, + { + "source": "#procedural", + "target": "systemd_status" + }, + { + "source": "#typescript", + "target": "Non_null_assertion_in_TypeScript" + }, + { + "source": "#ecopolsoc", + "target": "Bauman_quote" + }, + { + "source": "#surveillance-capitalism", + "target": "Bauman_quote" + }, + { + "source": "#unix", + "target": "Time_and_computers" + }, + { + "source": "#time", + "target": "Time_and_computers" + }, + { + "source": "#node-js", + "target": "Creating_a_RESTful_API_POST" + }, + { + "source": "#REST", + "target": "Creating_a_RESTful_API_POST" + }, + { + "source": "#APIs", + "target": "Creating_a_RESTful_API_POST" + }, + { + "source": "#AWS", + "target": "Handle_multiple_endpoints_single_lambda" + }, + { + "source": "#aws-lambda", + "target": "Handle_multiple_endpoints_single_lambda" + }, + { + "source": "#shell", + "target": "Lists_and_arrays_in_Bash" + }, + { + "source": "#data-structures", + "target": "Lists_and_arrays_in_Bash" + }, + { + "source": "#binary", + "target": "Binary_addition" + }, + { + "source": "#shell", + "target": "Redirection_in_Bash" + }, + { + "source": "#prealgebra", + "target": "Multiplicative_property_of_negative_one" + }, + { + "source": "#theorems", + "target": "Multiplicative_property_of_negative_one" + }, + { + "source": "#binary", + "target": "Binary_encoding_of_text" + }, + { + "source": "#CPU", + "target": "Arithmetic_Logic_Unit" + }, + { + "source": "#algorithms", + "target": "Recursion" + }, + { + "source": "#data-structures", + "target": "Recursion" + }, + { + "source": "#recursion", + "target": "Recursion" + }, + { + "source": "#SQL", + "target": "Joins_in_SQL" + }, + { + "source": "#databases", + "target": "Joins_in_SQL" + }, + { + "source": "#propositional-logic", + "target": "Law_of_the_Excluded_Middle" + }, + { + "source": "#logic", + "target": "Law_of_the_Excluded_Middle" + }, + { + "source": "#prealgebra", + "target": "Order_of_operations" + }, + { + "source": "#python", + "target": "File_system_error_handling_in_Python" + }, + { + "source": "#file-system", + "target": "File_system_error_handling_in_Python" + }, + { + "source": "#procedural", + "target": "File_system_error_handling_in_Python" + }, + { + "source": "#javascript", + "target": "React_errors" + }, + { + "source": "#react", + "target": "React_errors" + }, + { + "source": "#theory-of-computation", + "target": "Turing_completeness" + }, + { + "source": "#Turing", + "target": "Turing_completeness" + }, + { + "source": "#prealgebra", + "target": "Multiplying_fractions" + }, + { + "source": "#fractions", + "target": "Multiplying_fractions" + }, + { + "source": "#arithmetic", + "target": "Multiplying_fractions" + }, + { + "source": "#literature", + "target": "The_History_of_Computing_Swade" + }, + { + "source": "#computer-history", + "target": "The_History_of_Computing_Swade" + }, + { + "source": "#Linux", + "target": "Set_DNS_settings" + }, + { + "source": "#networks", + "target": "Set_DNS_settings" + }, + { + "source": "#python", + "target": "Reading_files_in_Python" + }, + { + "source": "#file-system", + "target": "Reading_files_in_Python" + }, + { + "source": "#procedural", + "target": "Reading_files_in_Python" + }, + { + "source": "#python", + "target": "Functions_in_Python" + }, + { + "source": "#typescript", + "target": "Setting_up_and_configuring_TypeScript" + }, + { + "source": "#propositional-logic", + "target": "Conditional_Introduction" + }, + { + "source": "#logic", + "target": "Conditional_Introduction" + }, + { + "source": "#docker", + "target": "Docker_Compose" + }, + { + "source": "#python", + "target": "Dates_in_Python" + }, + { + "source": "#time", + "target": "Dates_in_Python" + }, + { + "source": "#systems-programming", + "target": "Monitoring_processes_and_resources" + }, + { + "source": "#Linux", + "target": "Monitoring_processes_and_resources" + }, + { + "source": "#procedural", + "target": "Monitoring_processes_and_resources" + }, + { + "source": "#python", + "target": "Conditional_statements_in_Python" + }, + { + "source": "#graphql", + "target": "Apollo_Server" + }, + { + "source": "#REST", + "target": "Apollo_Server" + }, + { + "source": "#APIs", + "target": "Apollo_Server" + }, + { + "source": "#ARPANET", + "target": "e470bf3d_IMPs_in_the_ARPANET" + }, + { + "source": "#networks", + "target": "e470bf3d_IMPs_in_the_ARPANET" + }, + { + "source": "#computer-history", + "target": "e470bf3d_IMPs_in_the_ARPANET" + }, + { + "source": "#prealgebra", + "target": "Reciprocals" + }, + { + "source": "#fractions", + "target": "Reciprocals" + }, + { + "source": "#theorems", + "target": "Reciprocals" + }, + { + "source": "#binary", + "target": "Why_computers_use_binary" + }, + { + "source": "#computer-architecture", + "target": "Why_computers_use_binary" + }, + { + "source": "#docker", + "target": "AWS_SAM_and_Docker" + }, + { + "source": "#AWS", + "target": "AWS_SAM_and_Docker" + }, + { + "source": "#computer-history", + "target": "Magnetic_drum_memory" + }, + { + "source": "#memory", + "target": "Magnetic_drum_memory" + }, + { + "source": "#node-js", + "target": "fs" + }, + { + "source": "#AWS", + "target": "AWS_SQS" + }, + { + "source": "#SQS", + "target": "AWS_SQS" + }, + { + "source": "#ecopolsoc", + "target": "fbbfbc32-political-accommodation-inveigelment-surveillance-capitalism" + }, + { + "source": "#internet", + "target": "fbbfbc32-political-accommodation-inveigelment-surveillance-capitalism" + }, + { + "source": "#surveillance-capitalism", + "target": "fbbfbc32-political-accommodation-inveigelment-surveillance-capitalism" + }, + { + "source": "#prealgebra", + "target": "Handling_negative_fractions" + }, + { + "source": "#fractions", + "target": "Handling_negative_fractions" + }, + { + "source": "#logic", + "target": "Truth_trees" + }, + { + "source": "#propositional-logic", + "target": "Truth_trees" + }, + { + "source": "#prealgebra", + "target": "Expressing_whole_numbers_as_fractions" + }, + { + "source": "#fractions", + "target": "Expressing_whole_numbers_as_fractions" + }, + { + "source": "#shell", + "target": "Passing_arguments_and_options_to_Bash_scripts" + }, + { + "source": "#shell", + "target": "Bash_colour_output" + }, + { + "source": "#propositional-logic", + "target": "Soundness" + }, + { + "source": "#logic", + "target": "Soundness" + }, + { + "source": "#electronics", + "target": "Relays" + }, + { + "source": "#AWS", + "target": "DynamoDB_SDK_commands" + }, + { + "source": "#databases", + "target": "DynamoDB_SDK_commands" + }, + { + "source": "#dynamodb", + "target": "DynamoDB_SDK_commands" + }, + { + "source": "#physics", + "target": "Electromagnetism" + }, + { + "source": "#electricity", + "target": "Electromagnetism" + }, + { + "source": "#electromagnetism", + "target": "Electromagnetism" + }, + { + "source": "#python", + "target": "Working_with_CSVs_in_Python" + }, + { + "source": "#csv", + "target": "Working_with_CSVs_in_Python" + }, + { + "source": "#design-patterns", + "target": "Sliding_window" + }, + { + "source": "#node-js", + "target": "Nodemon" + }, + { + "source": "#logic-gates", + "target": "Flip_flops" + }, + { + "source": "#binary", + "target": "Flip_flops" + }, + { + "source": "#memory", + "target": "Flip_flops" + }, + { + "source": "#git", + "target": "Reset_to_remote_version" + }, + { + "source": "#procedural", + "target": "Reset_to_remote_version" + }, + { + "source": "#memory", + "target": "Stack_memory" + }, + { + "source": "#SQL", + "target": "Useful_operators_in_SQL" + }, + { + "source": "#databases", + "target": "Useful_operators_in_SQL" + }, + { + "source": "#prealgebra", + "target": "Whole_numbers" + }, + { + "source": "#node-js", + "target": "Module_wrapping_at_runtime" + }, + { + "source": "#node-js", + "target": "Full_Node_API_example" + }, + { + "source": "#REST", + "target": "Full_Node_API_example" + }, + { + "source": "#APIs", + "target": "Full_Node_API_example" + }, + { + "source": "#physics", + "target": "Resistance" + }, + { + "source": "#electricity", + "target": "Resistance" + }, + { + "source": "#SQL", + "target": "Delete_records_in_an_SQL_table" + }, + { + "source": "#databases", + "target": "Delete_records_in_an_SQL_table" + }, + { + "source": "#shell", + "target": "Variables_and_data_types_in_Bash" + }, + { + "source": "#memory", + "target": "Role_of_memory_in_computation" + }, + { + "source": "#mongo-db", + "target": "Creating_a_Mongo_schema_and_model" + }, + { + "source": "#node-js", + "target": "Creating_a_Mongo_schema_and_model" + }, + { + "source": "#mongoose", + "target": "Creating_a_Mongo_schema_and_model" + }, + { + "source": "#databases", + "target": "Creating_a_Mongo_schema_and_model" + }, + { + "source": "#computer-architecture", + "target": "ROM_versus_disk_loading" + }, + { + "source": "#memory", + "target": "ROM_versus_disk_loading" + }, + { + "source": "#networks", + "target": "Headless_Raspi_network_setup" + }, + { + "source": "#Linux", + "target": "Headless_Raspi_network_setup" + }, + { + "source": "#raspberry-pi", + "target": "Headless_Raspi_network_setup" + }, + { + "source": "#procedural", + "target": "Headless_Raspi_network_setup" + }, + { + "source": "#node-js", + "target": "NodeJS_scripts" + }, + { + "source": "#networks", + "target": "Usenet" + }, + { + "source": "#internet", + "target": "Usenet" + }, + { + "source": "#shell", + "target": "Formatting_output_text_in_Bash" + }, + { + "source": "#internet", + "target": "82f9c228_dissolution_of_ARPANET" + }, + { + "source": "#ARPANET", + "target": "82f9c228_dissolution_of_ARPANET" + }, + { + "source": "#cryptography", + "target": "a4601796_trapdoor_functions" + }, + { + "source": "#encryption", + "target": "a4601796_trapdoor_functions" + }, + { + "source": "#computer-architecture", + "target": "Devices" + }, + { + "source": "#Linux", + "target": "Devices" + }, + { + "source": "#javascript", + "target": "Prototypical_inheritance" + }, + { + "source": "#OOP", + "target": "Prototypical_inheritance" + }, + { + "source": "#node-js", + "target": "Validation_in_NodeJS" + }, + { + "source": "#REST", + "target": "Validation_in_NodeJS" + }, + { + "source": "#APIs", + "target": "Validation_in_NodeJS" + }, + { + "source": "#docker", + "target": "Node_and_MySQL_db" + }, + { + "source": "#SQL", + "target": "Node_and_MySQL_db" + }, + { + "source": "#node-js", + "target": "Node_and_MySQL_db" + }, + { + "source": "#databases", + "target": "Node_and_MySQL_db" + }, + { + "source": "#AWS", + "target": "Secrets_or_env_vars_in_AWS" + }, + { + "source": "#aws-lambda", + "target": "Secrets_or_env_vars_in_AWS" + }, + { + "source": "#C", + "target": "Variables_in_C" + }, + { + "source": "#world-wide-web", + "target": "HTTPS" + }, + { + "source": "#internet", + "target": "HTTPS" + }, + { + "source": "#encryption", + "target": "HTTPS" + }, + { + "source": "#nand-to-tetris", + "target": "Hardware_simulation" + }, + { + "source": "#internet", + "target": "Internet_Layer_of_Internet_Protocol" + }, + { + "source": "#networks", + "target": "Internet_Layer_of_Internet_Protocol" + }, + { + "source": "#AWS", + "target": "Restructure_URLs_lambda" + }, + { + "source": "#aws-lambda", + "target": "Restructure_URLs_lambda" + }, + { + "source": "#AWS", + "target": "AWS_CLI" + }, + { + "source": "#procedural", + "target": "AWS_CLI" + }, + { + "source": "#world-wide-web", + "target": "241fe1a3_the_Web_versus_modem_BBSs" + }, + { + "source": "#computer-history", + "target": "241fe1a3_the_Web_versus_modem_BBSs" + }, + { + "source": "#internet", + "target": "241fe1a3_the_Web_versus_modem_BBSs" + }, + { + "source": "#bulletin-boards", + "target": "241fe1a3_the_Web_versus_modem_BBSs" + }, + { + "source": "#networks", + "target": "Link_Layer_of_Internet_Protocol" + }, + { + "source": "#internet", + "target": "Link_Layer_of_Internet_Protocol" + }, + { + "source": "#graphql", + "target": "Journey_of_GraphQL_query" + }, + { + "source": "#shell", + "target": "Bash_store_status_of_command_execution" + }, + { + "source": "#AWS", + "target": "Bash_store_status_of_command_execution" + }, + { + "source": "#S3", + "target": "Bash_store_status_of_command_execution" + }, + { + "source": "#AWS", + "target": "DynamoDB_data_structure" + }, + { + "source": "#databases", + "target": "DynamoDB_data_structure" + }, + { + "source": "#dynamodb", + "target": "DynamoDB_data_structure" + }, + { + "source": "#AWS", + "target": "Terraform" + }, + { + "source": "#IaC", + "target": "Terraform" + }, + { + "source": "#physics", + "target": "Voltage" + }, + { + "source": "#electricity", + "target": "Voltage" + }, + { + "source": "#OOP", + "target": "Factory_pattern" + }, + { + "source": "#design-patterns", + "target": "Factory_pattern" + }, + { + "source": "#shell", + "target": "Split_into_array_in_Bash" + }, + { + "source": "#javascript", + "target": "Maps_and_sets_in_JS" + }, + { + "source": "#CPU", + "target": "Fetch_decode_execute" + }, + { + "source": "#logic", + "target": "Reiteration" + }, + { + "source": "#propositional-logic", + "target": "Reiteration" + }, + { + "source": "#networks", + "target": "MAC_addresses" + }, + { + "source": "#mongo-db", + "target": "Update_a_Mongo_document" + }, + { + "source": "#node-js", + "target": "Update_a_Mongo_document" + }, + { + "source": "#mongoose", + "target": "Update_a_Mongo_document" + }, + { + "source": "#databases", + "target": "Update_a_Mongo_document" + }, + { + "source": "#javascript", + "target": "Controlled_components_in_React" + }, + { + "source": "#react", + "target": "Controlled_components_in_React" + }, + { + "source": "#javascript", + "target": "Routing_on_link_click_in_React" + }, + { + "source": "#react", + "target": "Routing_on_link_click_in_React" + }, + { + "source": "#testing", + "target": "Routing_on_link_click_in_React" + }, + { + "source": "#propositional-logic", + "target": "Validity_and_entailment" + }, + { + "source": "#logic", + "target": "Validity_and_entailment" + }, + { + "source": "#AWS", + "target": "Lambda_directory_structure" + }, + { + "source": "#aws-lambda", + "target": "Lambda_directory_structure" + }, + { + "source": "#mongo-db", + "target": "Connect_to_Mongo_database" + }, + { + "source": "#node-js", + "target": "Connect_to_Mongo_database" + }, + { + "source": "#mongoose", + "target": "Connect_to_Mongo_database" + }, + { + "source": "#databases", + "target": "Connect_to_Mongo_database" + }, + { + "source": "#CPU", + "target": "Assembly" + }, + { + "source": "#logic-gates", + "target": "Logic_gates" + }, + { + "source": "#binary", + "target": "Logic_gates" + }, + { + "source": "#disks", + "target": "What_are_disks" + }, + { + "source": "#computer-architecture", + "target": "What_are_disks" + }, + { + "source": "#javascript", + "target": "Comparing_React_classes_to_hooks" + }, + { + "source": "#react", + "target": "Comparing_React_classes_to_hooks" + }, + { + "source": "#SQL", + "target": "Update_existing_data_in_SQL_table" + }, + { + "source": "#databases", + "target": "Update_existing_data_in_SQL_table" + }, + { + "source": "#disks", + "target": "Creating_a_Linux_partition_table" + }, + { + "source": "#Linux", + "target": "Creating_a_Linux_partition_table" + }, + { + "source": "#theorems", + "target": "Associative_Property_of_Addition_and_Multiplication" + }, + { + "source": "#prealgebra", + "target": "Associative_Property_of_Addition_and_Multiplication" + }, + { + "source": "#AWS", + "target": "User_management_on_AWS" + }, + { + "source": "#typescript", + "target": "Primitive_types" + }, + { + "source": "#data-types", + "target": "Primitive_types" + }, + { + "source": "#python", + "target": "Python_execution" + }, + { + "source": "#data-types", + "target": "Python_execution" + }, + { + "source": "#AWS", + "target": "S3" + }, + { + "source": "#AWS", + "target": "AWS_CloudWatch" + }, + { + "source": "#binary", + "target": "Binary_colour_encoding" + }, + { + "source": "#git", + "target": "Rename_a_branch" + }, + { + "source": "#procedural", + "target": "Rename_a_branch" + }, + { + "source": "#SQL", + "target": "Accessing_metadata_about_SQL_database" + }, + { + "source": "#databases", + "target": "Accessing_metadata_about_SQL_database" + }, + { + "source": "#propositional-logic", + "target": "Theorems_and_empty_sets" + }, + { + "source": "#logic", + "target": "Theorems_and_empty_sets" + }, + { + "source": "#node-js", + "target": "Creating_a_RESTful_API_Integrating_the_Database" + }, + { + "source": "#REST", + "target": "Creating_a_RESTful_API_Integrating_the_Database" + }, + { + "source": "#APIs", + "target": "Creating_a_RESTful_API_Integrating_the_Database" + }, + { + "source": "#mongo-db", + "target": "Creating_a_RESTful_API_Integrating_the_Database" + }, + { + "source": "#databases", + "target": "Creating_a_RESTful_API_Integrating_the_Database" + }, + { + "source": "#physics", + "target": "Prefixes_for_units_of_electrical_measurement" + }, + { + "source": "#electricity", + "target": "Prefixes_for_units_of_electrical_measurement" + }, + { + "source": "#exponents", + "target": "Prefixes_for_units_of_electrical_measurement" + }, + { + "source": "#python", + "target": "Naming_conventions" + }, + { + "source": "#ARPA", + "target": "f0f70a3c_ARPANET_motivations" + }, + { + "source": "#ARPANET", + "target": "f0f70a3c_ARPANET_motivations" + }, + { + "source": "#networks", + "target": "f0f70a3c_ARPANET_motivations" + }, + { + "source": "#computer-history", + "target": "f0f70a3c_ARPANET_motivations" + }, + { + "source": "#world-wide-web", + "target": "Dynamic_and_static_websites" + }, + { + "source": "#logic-gates", + "target": "Integrated_circuits" + }, + { + "source": "#electronics", + "target": "Integrated_circuits" + }, + { + "source": "#theorems", + "target": "Distributivity" + }, + { + "source": "#prealgebra", + "target": "Distributivity" + }, + { + "source": "#git", + "target": "Identify_merged_branches" + }, + { + "source": "#python", + "target": "Working_with_JSON_in_Python" + }, + { + "source": "#JSON", + "target": "Working_with_JSON_in_Python" + }, + { + "source": "#disks", + "target": "Boot_process" + }, + { + "source": "#operating-systems", + "target": "Boot_process" + }, + { + "source": "#docker", + "target": "Docker_architecture" + }, + { + "source": "#containerization", + "target": "Docker_architecture" + }, + { + "source": "#logic-gates", + "target": "Three_bit_counter" + }, + { + "source": "#binary", + "target": "Three_bit_counter" + }, + { + "source": "#memory", + "target": "Three_bit_counter" + }, + { + "source": "#SQL", + "target": "Foreign_keys_in_SQL" + }, + { + "source": "#databases", + "target": "Foreign_keys_in_SQL" + }, + { + "source": "#C", + "target": "Printing_values_in_C" + }, + { + "source": "#prealgebra", + "target": "Primes_and_composites" + }, + { + "source": "#number-theory", + "target": "Primes_and_composites" + }, + { + "source": "#theory-of-computation", + "target": "Defining_a_computer" + }, + { + "source": "#python", + "target": "Match_statements_in_Python" + }, + { + "source": "#shell", + "target": "The_PATH" + }, + { + "source": "#javascript", + "target": "JavaScript_module_types" + }, + { + "source": "#graphql", + "target": "Apollo_Client" + }, + { + "source": "#operating-systems", + "target": "Threads" + }, + { + "source": "#shell", + "target": "Capturing_user_input_in_Bash" + }, + { + "source": "#docker", + "target": "Docker_CLI" + }, + { + "source": "#shell", + "target": "Docker_CLI" + }, + { + "source": "#AWS", + "target": "DynamoDB_CLI_commands" + }, + { + "source": "#databases", + "target": "DynamoDB_CLI_commands" + }, + { + "source": "#dynamodb", + "target": "DynamoDB_CLI_commands" + }, + { + "source": "#python", + "target": "None_in_Python" + }, + { + "source": "#data-types", + "target": "None_in_Python" + }, + { + "source": "#Linux", + "target": "Pacman" + }, + { + "source": "#procedural", + "target": "Pacman" + }, + { + "source": "#arch-linux", + "target": "Pacman" + }, + { + "source": "#memory", + "target": "Heap_memory" + }, + { + "source": "#C", + "target": "Heap_memory" + }, + { + "source": "#world-wide-web", + "target": "f6564af9_AOL_and_early_internet_enclosure" + }, + { + "source": "#computer-history", + "target": "f6564af9_AOL_and_early_internet_enclosure" + }, + { + "source": "#internet", + "target": "f6564af9_AOL_and_early_internet_enclosure" + }, + { + "source": "#ecosolpoc", + "target": "f6564af9_AOL_and_early_internet_enclosure" + }, + { + "source": "#bulletin-boards", + "target": "f6564af9_AOL_and_early_internet_enclosure" + }, + { + "source": "#shell", + "target": "Strings_in_Bash" + }, + { + "source": "#data-types", + "target": "Strings_in_Bash" + }, + { + "source": "#shell", + "target": "Conditionals_in_Bash" + }, + { + "source": "#computer-history", + "target": "Delay_line_memory" + }, + { + "source": "#memory", + "target": "Delay_line_memory" + }, + { + "source": "#propositional-logic", + "target": "Syllogism" + }, + { + "source": "#logic", + "target": "Syllogism" + }, + { + "source": "#hardware", + "target": "Chipset_and_controllers" + }, + { + "source": "#computer-architecture", + "target": "Chipset_and_controllers" + }, + { + "source": "#shell", + "target": "Grep" + }, + { + "source": "#propositional-logic", + "target": "Boolean_function_synthesis" + }, + { + "source": "#nand-to-tetris", + "target": "Boolean_function_synthesis" + }, + { + "source": "#logic", + "target": "Boolean_function_synthesis" + }, + { + "source": "#propositional-logic", + "target": "Logical_possibility_and_necessity" + }, + { + "source": "#logic", + "target": "Logical_possibility_and_necessity" + }, + { + "source": "#computer-history", + "target": "Magnetic_core_memory" + }, + { + "source": "#memory", + "target": "Magnetic_core_memory" + }, + { + "source": "Memory_addresses", + "target": "Logarithms" + }, + { + "source": "Memory_addresses", + "target": "Hexadecimal_number_system" + }, + { + "source": "Memory_addresses", + "target": "Binary_encoding" + }, + { + "source": "AWS_SNS", + "target": "AWS_SQS" + }, + { + "source": "Boolean_algebra", + "target": "Distributivity" + }, + { + "source": "Boolean_algebra", + "target": "DeMorgan's_Laws" + }, + { + "source": "Boolean_algebra", + "target": "Logic_gates" + }, + { + "source": "Package_management_in_NodeJS", + "target": "Semantic_versioning" + }, + { + "source": "MongoDB_Introduction", + "target": "Relational_database_architecture" + }, + { + "source": "Containerization", + "target": "The_kernel" + }, + { + "source": "Containerization", + "target": "User_Space" + }, + { + "source": "Call_stack", + "target": "Stacks" + }, + { + "source": "Call_stack", + "target": "Stack_memory" + }, + { + "source": "Custom_types_in_TypeScript", + "target": "Classes" + }, + { + "source": "Linux_disk_partitions", + "target": "The_kernel" + }, + { + "source": "Linux_disk_partitions", + "target": "Creating_a_Linux_partition_table" + }, + { + "source": "Using_SQLite_with_Python", + "target": "Tuples_in_Python" + }, + { + "source": "Dividing_fractions", + "target": "Reciprocals" + }, + { + "source": "Network_card", + "target": "Link_Layer_of_Internet_Protocol" + }, + { + "source": "Network_card", + "target": "Motherboard" + }, + { + "source": "Network_card", + "target": "MAC_addresses" + }, + { + "source": "What_is_memory", + "target": "CPU_architecture" + }, + { + "source": "What_is_memory", + "target": "DRAM_and_SRAM_memory" + }, + { + "source": "CPU_architecture", + "target": "Bus" + }, + { + "source": "CPU_architecture", + "target": "The_kernel" + }, + { + "source": "CPU_architecture", + "target": "Arithmetic_Logic_Unit" + }, + { + "source": "CPU_architecture", + "target": "Chipset_and_controllers" + }, + { + "source": "CPU_architecture", + "target": "Logic_gates" + }, + { + "source": "CPU_architecture", + "target": "Clock_signals" + }, + { + "source": "CPU_architecture", + "target": "Fetch_decode_execute" + }, + { + "source": "CPU_architecture", + "target": "Electromagnetism" + }, + { + "source": "Truth_functional_connectives", + "target": "Atomic_and_molecular_propositions" + }, + { + "source": "Truth_functional_connectives", + "target": "Logical_indeterminacy" + }, + { + "source": "Lists_in_Python", + "target": "List_comprehension_in_Python" + }, + { + "source": "Lists_in_Python", + "target": "Sorting_lists_in_Python" + }, + { + "source": "IP_addresses", + "target": "Internet_Layer_of_Internet_Protocol" + }, + { + "source": "Classes_in_Python", + "target": "Functions_in_Python" + }, + { + "source": "Hardware_Description_Language", + "target": "Integrated_circuits" + }, + { + "source": "Hardware_Description_Language", + "target": "Hardware_simulation" + }, + { + "source": "Hardware_Description_Language", + "target": "Boolean_functions" + }, + { + "source": "React_useReducer", + "target": "React_useState" + }, + { + "source": "Network_requests_in_Python", + "target": "RESTful_APIs" + }, + { + "source": "Network_requests_in_Python", + "target": "Dictionaries_in_Python" + }, + { + "source": "Transport_Layer_of_Internet_Protocol", + "target": "Internet_Layer_of_Internet_Protocol" + }, + { + "source": "Transport_Layer_of_Internet_Protocol", + "target": "Link_Layer_of_Internet_Protocol" + }, + { + "source": "The_kernel", + "target": "Basic_model_of_the_operating_system" + }, + { + "source": "The_kernel", + "target": "User_Space" + }, + { + "source": "The_kernel", + "target": "Processes" + }, + { + "source": "Event_loop", + "target": "The_kernel" + }, + { + "source": "Event_loop", + "target": "Call_stack" + }, + { + "source": "Process_module_in_NodeJS", + "target": "Managing_environments_in_NodeJS" + }, + { + "source": "Creating_a_RESTful_API_Introduction", + "target": "RESTful_APIs" + }, + { + "source": "Creating_a_RESTful_API_Introduction", + "target": "HTTP_request_types" + }, + { + "source": "Creating_a_RESTful_API_Introduction", + "target": "Middleware_in_NodeJS" + }, + { + "source": "4a3dc316_key_figures_ARPANET", + "target": "385af4b4_Baran_distributed_networks" + }, + { + "source": "RESTful_APIs", + "target": "HTTP_request_types" + }, + { + "source": "Binary_number_system", + "target": "Hexadecimal_number_system" + }, + { + "source": "Torrenting", + "target": "Peer_to_peer_network" + }, + { + "source": "Torrenting", + "target": "Network_protocols" + }, + { + "source": "Application_state_management_with_React_hooks", + "target": "React_useReducer" + }, + { + "source": "Application_state_management_with_React_hooks", + "target": "React_useContext" + }, + { + "source": "Accessing_secrets_from_a_Lambda", + "target": "Fetch_from_Secrets_Manager" + }, + { + "source": "cfbef1c4_web_precursors", + "target": "Mainframe_computers" + }, + { + "source": "Internet_fundamentals", + "target": "Network_fundamentals" + }, + { + "source": "Internet_fundamentals", + "target": "Network_protocols" + }, + { + "source": "Internet_fundamentals", + "target": "Link_Layer_of_Internet_Protocol" + }, + { + "source": "Internet_fundamentals", + "target": "Internet_Layer_of_Internet_Protocol" + }, + { + "source": "Internet_fundamentals", + "target": "Transport_Layer_of_Internet_Protocol" + }, + { + "source": "Internet_fundamentals", + "target": "Application_Layer_of_Internet_Protocol" + }, + { + "source": "Internet_fundamentals", + "target": "Example_scenario_internet_data_transfer" + }, + { + "source": "Step_functions_and_state_machines", + "target": "Lambda_programming_model" + }, + { + "source": "Python_interpreter", + "target": "Binary_units_of_measurement" + }, + { + "source": "Stale_branches_and_pruning", + "target": "Remote_tracking_branches" + }, + { + "source": "Clock_signals", + "target": "Half_adder_and_full_adder" + }, + { + "source": "Clock_signals", + "target": "Latches" + }, + { + "source": "Clock_signals", + "target": "Electromagnetism" + }, + { + "source": "Memoization_in_React", + "target": "React_useEffect" + }, + { + "source": "API_Gateway", + "target": "HTTP_request_types" + }, + { + "source": "API_Gateway", + "target": "Lambda_handler_function" + }, + { + "source": "API_Gateway", + "target": "Practical_walkthrough_Lambda_creation_within_AWS" + }, + { + "source": "Filesystems", + "target": "Swap_space" + }, + { + "source": "Classes", + "target": "Functions" + }, + { + "source": "Connecting_a_frontend_to_a_Docker_backend", + "target": "Node_and_MySQL_db" + }, + { + "source": "Connecting_a_frontend_to_a_Docker_backend", + "target": "Docker_Compose" + }, + { + "source": "Cells_and_batteries", + "target": "Voltage" + }, + { + "source": "Logical_equivalence", + "target": "Biconditional_Introduction" + }, + { + "source": "Validating_Mongoose_schemas", + "target": "Validation_in_NodeJS" + }, + { + "source": "Middleware_in_NodeJS", + "target": "Ports_in_NodeJS" + }, + { + "source": "Middleware_in_NodeJS", + "target": "Morgan" + }, + { + "source": "Logical_consistency", + "target": "Negation_Elimination" + }, + { + "source": "4da22434_from_ARPANET_to_Internet", + "target": "Internet_Layer_of_Internet_Protocol" + }, + { + "source": "Using_arguments_with_Apollo_Client", + "target": "Apollo_Server" + }, + { + "source": "Network_fundamentals", + "target": "Network_hosts" + }, + { + "source": "Peer_to_peer_network", + "target": "Torrenting" + }, + { + "source": "Negation_Elimination", + "target": "Negation_Introduction" + }, + { + "source": "Machine_code", + "target": "Assembly" + }, + { + "source": "c301a0b3-1d8_Mosaic_Netscape_and_Browser_Wars", + "target": "Application_Layer_of_Internet_Protocol" + }, + { + "source": "Architecture_of_the_World_Wide_Web", + "target": "Transport_Layer_of_Internet_Protocol" + }, + { + "source": "Architecture_of_the_World_Wide_Web", + "target": "IP_addresses" + }, + { + "source": "Practical_walkthrough_Lambda_creation_within_AWS", + "target": "Lambda_triggers" + }, + { + "source": "Bus", + "target": "Motherboard" + }, + { + "source": "Testing_Python_code", + "target": "Python_package_management" + }, + { + "source": "Register_and_cache_memory", + "target": "DRAM_and_SRAM_memory" + }, + { + "source": "SQLite", + "target": "Lists_in_Python" + }, + { + "source": "SQLite", + "target": "Tuples_in_Python" + }, + { + "source": "Iterating_through_complex_data_structures_in_Python", + "target": "Sorting_lists_in_Python" + }, + { + "source": "Iterating_through_complex_data_structures_in_Python", + "target": "Lambdas_in_Python" + }, + { + "source": "Iterating_through_complex_data_structures_in_Python", + "target": "Map_and_filter_in_Python" + }, + { + "source": "Iterating_through_complex_data_structures_in_Python", + "target": "List_comprehension_in_Python" + }, + { + "source": "Lambdas_in_Python", + "target": "Map_and_filter_in_Python" + }, + { + "source": "Docker_general_overview", + "target": "Docker_architecture" + }, + { + "source": "Logical_truth_and_falsity", + "target": "Logical_consistency" + }, + { + "source": "Logical_truth_and_falsity", + "target": "Validity_and_entailment" + }, + { + "source": "Streams_in_NodeJS", + "target": "fs" + }, + { + "source": "Cherry_picking", + "target": "Remote_tracking_branches" + }, + { + "source": "React_useContext", + "target": "Application_state_management_with_React_hooks" + }, + { + "source": "Voltage_sources", + "target": "Cells_and_batteries" + }, + { + "source": "Relation_between_kernel_and_CPU", + "target": "Fetch_decode_execute" + }, + { + "source": "Motherboard", + "target": "CPU_architecture" + }, + { + "source": "Motherboard", + "target": "What_are_disks" + }, + { + "source": "Managing_environments_in_NodeJS", + "target": "Environmental_and_shell_variables" + }, + { + "source": "Hexadecimal_number_system", + "target": "Binary_number_system" + }, + { + "source": "Network_protocols", + "target": "Network_fundamentals" + }, + { + "source": "Network_protocols", + "target": "Internet_fundamentals" + }, + { + "source": "Test_values_in_Bash", + "target": "Lists_and_arrays_in_Bash" + }, + { + "source": "653c0b1d_host_protocols_of_ARPANET", + "target": "e470bf3d_IMPs_in_the_ARPANET" + }, + { + "source": "653c0b1d_host_protocols_of_ARPANET", + "target": "Link_Layer_of_Internet_Protocol" + }, + { + "source": "DRAM_and_SRAM_memory", + "target": "DRAM_and_SRAM_memory" + }, + { + "source": "DRAM_and_SRAM_memory", + "target": "Transistors" + }, + { + "source": "DRAM_and_SRAM_memory", + "target": "Current" + }, + { + "source": "DRAM_and_SRAM_memory", + "target": "Flip_flops" + }, + { + "source": "File_descriptors", + "target": "Redirection_in_Bash" + }, + { + "source": "Network_hosts", + "target": "Network_fundamentals" + }, + { + "source": "Half_adder_and_full_adder", + "target": "Logic_gates" + }, + { + "source": "Binary_units_of_measurement", + "target": "Binary_number_system" + }, + { + "source": "Binary_units_of_measurement", + "target": "Prefixes_for_units_of_electrical_measurement" + }, + { + "source": "React_useEffect", + "target": "Lifecycle_methods" + }, + { + "source": "React_useEffect", + "target": "Memory_leaks" + }, + { + "source": "With_open_in_Python", + "target": "Reading_files_in_Python" + }, + { + "source": "With_open_in_Python", + "target": "Writing_to_files_in_Python" + }, + { + "source": "With_open_in_Python", + "target": "Appending_to_files_in_Python" + }, + { + "source": "Strategies_for_constructing_proofs", + "target": "Recursion" + }, + { + "source": "Strategies_for_constructing_proofs", + "target": "Conjunction_Introduction" + }, + { + "source": "Strategies_for_constructing_proofs", + "target": "Conditional_Introduction" + }, + { + "source": "Strategies_for_constructing_proofs", + "target": "Biconditional_Elimination" + }, + { + "source": "Strategies_for_constructing_proofs", + "target": "Conjunction_Elimination" + }, + { + "source": "Strategies_for_constructing_proofs", + "target": "Conditional_Elimination" + }, + { + "source": "Strategies_for_constructing_proofs", + "target": "Disjunction_Introduction" + }, + { + "source": "Strategies_for_constructing_proofs", + "target": "Disjunction_Elimination" + }, + { + "source": "Strategies_for_constructing_proofs", + "target": "Negation_Elimination" + }, + { + "source": "Type_guarding_and_narrowing_in_TS", + "target": "Any" + }, + { + "source": "Type_guarding_and_narrowing_in_TS", + "target": "Unknown_type_in_TS" + }, + { + "source": "Single_file_Python_scripts", + "target": "Python_modules_and_imports" + }, + { + "source": "Processes", + "target": "systemd" + }, + { + "source": "Processes", + "target": "ps" + }, + { + "source": "Processes", + "target": "Monitoring_processes_and_resources" + }, + { + "source": "Formal_proofs_in_propositional_logic", + "target": "Negation_Introduction" + }, + { + "source": "Formal_proofs_in_propositional_logic", + "target": "Negation_Elimination" + }, + { + "source": "Formal_proofs_in_propositional_logic", + "target": "Conjunction_Introduction" + }, + { + "source": "Formal_proofs_in_propositional_logic", + "target": "Conditional_Elimination" + }, + { + "source": "Formal_proofs_in_propositional_logic", + "target": "Disjunction_Introduction" + }, + { + "source": "Formal_proofs_in_propositional_logic", + "target": "Disjunction_Elimination" + }, + { + "source": "Formal_proofs_in_propositional_logic", + "target": "Conditional_Introduction" + }, + { + "source": "Formal_proofs_in_propositional_logic", + "target": "Biconditional_Introduction" + }, + { + "source": "Formal_proofs_in_propositional_logic", + "target": "Biconditional_Elimination" + }, + { + "source": "systemd", + "target": "Boot_process" + }, + { + "source": "systemd", + "target": "Daemons" + }, + { + "source": "systemd", + "target": "Processes" + }, + { + "source": "SAM", + "target": "Lambda_programming_model" + }, + { + "source": "SAM", + "target": "Lambda_handler_function" + }, + { + "source": "SAM", + "target": "Local_AWS_development_with_SAM" + }, + { + "source": "Working_with_numbers_in_Bash", + "target": "Expansions_and_substitutions" + }, + { + "source": "Syntax_of_propositional_logic", + "target": "Atomic_and_molecular_propositions" + }, + { + "source": "Transistors", + "target": "Voltage" + }, + { + "source": "React_Components", + "target": "Functions" + }, + { + "source": "Read_command__in_Bash", + "target": "Split_into_array_in_Bash" + }, + { + "source": "Read_command__in_Bash", + "target": "Find_Bash_command" + }, + { + "source": "VirtualMemory", + "target": "Processes" + }, + { + "source": "VirtualMemory", + "target": "User_Space" + }, + { + "source": "VirtualMemory", + "target": "The_kernel" + }, + { + "source": "VirtualMemory", + "target": "Memory_addresses" + }, + { + "source": "VirtualMemory", + "target": "Register_and_cache_memory" + }, + { + "source": "VirtualMemory", + "target": "Swap_space" + }, + { + "source": "VirtualMemory", + "target": "Boot_process" + }, + { + "source": "Ohms_Law", + "target": "Current" + }, + { + "source": "Ohms_Law", + "target": "Voltage" + }, + { + "source": "Ohms_Law", + "target": "Resistance" + }, + { + "source": "Current", + "target": "Coulombs_Laws" + }, + { + "source": "Current", + "target": "Voltage" + }, + { + "source": "Lambda_programming_model", + "target": "Lambda_triggers" + }, + { + "source": "Lambda_programming_model", + "target": "Lambda_handler_function" + }, + { + "source": "ps", + "target": "The_kernel" + }, + { + "source": "Operating_system_API", + "target": "Intro_to_the_Unix_shell" + }, + { + "source": "Operating_system_API", + "target": "Instruction_set_architectures" + }, + { + "source": "Swap_space", + "target": "The_kernel" + }, + { + "source": "Expansions_and_substitutions", + "target": "Variables_and_data_types_in_Bash" + }, + { + "source": "Expansions_and_substitutions", + "target": "Shell_sessions" + }, + { + "source": "Expansions_and_substitutions", + "target": "Working_with_numbers_in_Bash" + }, + { + "source": "Using_GraphQL_with_Node", + "target": "Middleware_in_NodeJS" + }, + { + "source": "Network_debugging", + "target": "Network_scanning" + }, + { + "source": "journald", + "target": "systemd" + }, + { + "source": "journald", + "target": "The_kernel" + }, + { + "source": "Create_an_SQL_table", + "target": "Data_types_in_MySQL" + }, + { + "source": "Strings_in_Python", + "target": "Lists_in_Python" + }, + { + "source": "Example_scenario_internet_data_transfer", + "target": "Application_Layer_of_Internet_Protocol" + }, + { + "source": "Example_scenario_internet_data_transfer", + "target": "Basic_model_of_the_operating_system" + }, + { + "source": "Example_scenario_internet_data_transfer", + "target": "Transport_Layer_of_Internet_Protocol" + }, + { + "source": "Example_scenario_internet_data_transfer", + "target": "Internet_Layer_of_Internet_Protocol" + }, + { + "source": "Example_scenario_internet_data_transfer", + "target": "Link_Layer_of_Internet_Protocol" + }, + { + "source": "Example_scenario_internet_data_transfer", + "target": "MAC_addresses" + }, + { + "source": "Add_Subtract_Fractions", + "target": "Factors_and_divisors" + }, + { + "source": "Forms_in_React", + "target": "Forms_in_React" + }, + { + "source": "List_comprehension_in_Python", + "target": "Map_and_filter_in_Python" + }, + { + "source": "List_comprehension_in_Python", + "target": "Lambdas_in_Python" + }, + { + "source": "Python_data_types", + "target": "Strings_in_Python" + }, + { + "source": "Magnetic_tape", + "target": "The_History_of_Computing_Swade" + }, + { + "source": "Instruction_set_architectures", + "target": "Signed_and_unsigned_numbers" + }, + { + "source": "Creating_a_RESTful_API_POST", + "target": "Validation_in_NodeJS" + }, + { + "source": "Lists_and_arrays_in_Bash", + "target": "Test_values_in_Bash" + }, + { + "source": "Lists_and_arrays_in_Bash", + "target": "Functions_in_Bash" + }, + { + "source": "Redirection_in_Bash", + "target": "File_descriptors" + }, + { + "source": "Redirection_in_Bash", + "target": "Redirect_to_dev_null" + }, + { + "source": "Binary_encoding_of_text", + "target": "Binary_encoding" + }, + { + "source": "Arithmetic_Logic_Unit", + "target": "CPU_architecture" + }, + { + "source": "Arithmetic_Logic_Unit", + "target": "Logic_gates" + }, + { + "source": "Arithmetic_Logic_Unit", + "target": "Half_adder_and_full_adder" + }, + { + "source": "Arithmetic_Logic_Unit", + "target": "Fetch_decode_execute" + }, + { + "source": "Joins_in_SQL", + "target": "Create_an_SQL_table" + }, + { + "source": "File_system_error_handling_in_Python", + "target": "Error_handling_in_Python" + }, + { + "source": "Turing_completeness", + "target": "Turing_machines" + }, + { + "source": "Multiplying_fractions", + "target": "Reducing_fractions" + }, + { + "source": "The_History_of_Computing_Swade", + "target": "Logarithms" + }, + { + "source": "The_History_of_Computing_Swade", + "target": "Integrated_circuits" + }, + { + "source": "The_History_of_Computing_Swade", + "target": "CPU_architecture" + }, + { + "source": "The_History_of_Computing_Swade", + "target": "Relays" + }, + { + "source": "The_History_of_Computing_Swade", + "target": "Delay_line_memory" + }, + { + "source": "The_History_of_Computing_Swade", + "target": "Turing_machines" + }, + { + "source": "The_History_of_Computing_Swade", + "target": "Magnetic_tape" + }, + { + "source": "The_History_of_Computing_Swade", + "target": "Magnetic_drum_memory" + }, + { + "source": "The_History_of_Computing_Swade", + "target": "Magnetic_core_memory" + }, + { + "source": "The_History_of_Computing_Swade", + "target": "Transistors" + }, + { + "source": "Set_DNS_settings", + "target": "Network_scanning" + }, + { + "source": "Set_DNS_settings", + "target": "Network_debugging" + }, + { + "source": "Docker_Compose", + "target": "Node_and_MySQL_db" + }, + { + "source": "Dates_in_Python", + "target": "Time_and_computers" + }, + { + "source": "Monitoring_processes_and_resources", + "target": "Processes" + }, + { + "source": "Monitoring_processes_and_resources", + "target": "Swap_space" + }, + { + "source": "Monitoring_processes_and_resources", + "target": "The_kernel" + }, + { + "source": "Apollo_Server", + "target": "Using_arguments_with_Apollo_Client" + }, + { + "source": "e470bf3d_IMPs_in_the_ARPANET", + "target": "Network_hosts" + }, + { + "source": "e470bf3d_IMPs_in_the_ARPANET", + "target": "Network_fundamentals" + }, + { + "source": "Magnetic_drum_memory", + "target": "Williams_Tube_memory" + }, + { + "source": "Magnetic_drum_memory", + "target": "Delay_line_memory" + }, + { + "source": "Magnetic_drum_memory", + "target": "The_History_of_Computing_Swade" + }, + { + "source": "fs", + "target": "Event_loop" + }, + { + "source": "fs", + "target": "Streams_in_NodeJS" + }, + { + "source": "AWS_SQS", + "target": "Queue" + }, + { + "source": "AWS_SQS", + "target": "API_Gateway" + }, + { + "source": "AWS_SQS", + "target": "AWS_CloudWatch" + }, + { + "source": "AWS_SQS", + "target": "AWS_SQS_SDK" + }, + { + "source": "Passing_arguments_and_options_to_Bash_scripts", + "target": "The_PATH" + }, + { + "source": "Relays", + "target": "The_History_of_Computing_Swade" + }, + { + "source": "Electromagnetism", + "target": "Current" + }, + { + "source": "Sliding_window", + "target": "Multiple_pointers" + }, + { + "source": "Flip_flops", + "target": "Latches" + }, + { + "source": "Flip_flops", + "target": "Clock_signals" + }, + { + "source": "Resistance", + "target": "Current" + }, + { + "source": "Resistance", + "target": "Ohms_Law" + }, + { + "source": "Role_of_memory_in_computation", + "target": "Boot_process" + }, + { + "source": "Role_of_memory_in_computation", + "target": "Bus" + }, + { + "source": "Role_of_memory_in_computation", + "target": "Chipset_and_controllers" + }, + { + "source": "Creating_a_Mongo_schema_and_model", + "target": "MongoDB_Introduction" + }, + { + "source": "Creating_a_Mongo_schema_and_model", + "target": "Validating_Mongoose_schemas" + }, + { + "source": "NodeJS_scripts", + "target": "Single_file_Python_scripts" + }, + { + "source": "Usenet", + "target": "385af4b4_Baran_distributed_networks" + }, + { + "source": "Usenet", + "target": "Transport_Layer_of_Internet_Protocol" + }, + { + "source": "Usenet", + "target": "Torrenting" + }, + { + "source": "82f9c228_dissolution_of_ARPANET", + "target": "cfbef1c4_web_precursors" + }, + { + "source": "82f9c228_dissolution_of_ARPANET", + "target": "Link_Layer_of_Internet_Protocol" + }, + { + "source": "a4601796_trapdoor_functions", + "target": "bbdcb54f_public_key_cryptography" + }, + { + "source": "Devices", + "target": "Redirect_to_dev_null" + }, + { + "source": "Node_and_MySQL_db", + "target": "Docker_Compose" + }, + { + "source": "Node_and_MySQL_db", + "target": "Managing_environments_in_NodeJS" + }, + { + "source": "Hardware_simulation", + "target": "Hardware_Description_Language" + }, + { + "source": "Internet_Layer_of_Internet_Protocol", + "target": "IP_addresses" + }, + { + "source": "Internet_Layer_of_Internet_Protocol", + "target": "Link_Layer_of_Internet_Protocol" + }, + { + "source": "Restructure_URLs_lambda", + "target": "Lambda_handler_function" + }, + { + "source": "241fe1a3_the_Web_versus_modem_BBSs", + "target": "c301a0b3-1d8_Mosaic_Netscape_and_Browser_Wars" + }, + { + "source": "Link_Layer_of_Internet_Protocol", + "target": "Network_hosts" + }, + { + "source": "Link_Layer_of_Internet_Protocol", + "target": "MAC_addresses" + }, + { + "source": "DynamoDB_data_structure", + "target": "Foreign_keys_in_SQL" + }, + { + "source": "Terraform", + "target": "AWS_CLI" + }, + { + "source": "Voltage", + "target": "Current" + }, + { + "source": "Voltage", + "target": "Voltage_sources" + }, + { + "source": "Voltage", + "target": "Cells_and_batteries" + }, + { + "source": "Voltage", + "target": "Ohms_Law" + }, + { + "source": "Fetch_decode_execute", + "target": "CPU_architecture" + }, + { + "source": "Fetch_decode_execute", + "target": "Logic_gates" + }, + { + "source": "MAC_addresses", + "target": "Link_Layer_of_Internet_Protocol" + }, + { + "source": "MAC_addresses", + "target": "Network_card" + }, + { + "source": "MAC_addresses", + "target": "Hexadecimal_number_system" + }, + { + "source": "Update_a_Mongo_document", + "target": "Querying_a_Mongo_collection" + }, + { + "source": "Logic_gates", + "target": "Integrated_circuits" + }, + { + "source": "Logic_gates", + "target": "Transistors" + }, + { + "source": "Logic_gates", + "target": "Half_adder_and_full_adder" + }, + { + "source": "Logic_gates", + "target": "Latches" + }, + { + "source": "Logic_gates", + "target": "Hardware_abstraction_and_modularity" + }, + { + "source": "What_are_disks", + "target": "Devices" + }, + { + "source": "What_are_disks", + "target": "User_Space" + }, + { + "source": "Creating_a_Linux_partition_table", + "target": "Linux_disk_partitions" + }, + { + "source": "Primitive_types", + "target": "Any" + }, + { + "source": "Primitive_types", + "target": "Custom_types_in_TypeScript" + }, + { + "source": "Creating_a_RESTful_API_Integrating_the_Database", + "target": "Connect_to_Mongo_database" + }, + { + "source": "Creating_a_RESTful_API_Integrating_the_Database", + "target": "Create_Mongo_database" + }, + { + "source": "Creating_a_RESTful_API_Integrating_the_Database", + "target": "Querying_a_Mongo_collection" + }, + { + "source": "Creating_a_RESTful_API_Integrating_the_Database", + "target": "Adding_documents_to_a_Mongo_collection" + }, + { + "source": "Prefixes_for_units_of_electrical_measurement", + "target": "Exponents" + }, + { + "source": "Working_with_JSON_in_Python", + "target": "Error_handling_in_Python" + }, + { + "source": "Boot_process", + "target": "The_kernel" + }, + { + "source": "Boot_process", + "target": "Filesystems" + }, + { + "source": "Boot_process", + "target": "User_Space" + }, + { + "source": "Boot_process", + "target": "journald" + }, + { + "source": "Docker_architecture", + "target": "RESTful_APIs" + }, + { + "source": "Three_bit_counter", + "target": "Flip_flops" + }, + { + "source": "Three_bit_counter", + "target": "Clock_signals" + }, + { + "source": "The_PATH", + "target": "Environmental_and_shell_variables" + }, + { + "source": "Apollo_Client", + "target": "Apollo_Server" + }, + { + "source": "Threads", + "target": "Processes" + }, + { + "source": "Threads", + "target": "User_Space" + }, + { + "source": "Threads", + "target": "The_kernel" + }, + { + "source": "Threads", + "target": "CPU_architecture" + }, + { + "source": "Threads", + "target": "Clock_signals" + }, + { + "source": "Capturing_user_input_in_Bash", + "target": "Passing_arguments_and_options_to_Bash_scripts" + }, + { + "source": "f6564af9_AOL_and_early_internet_enclosure", + "target": "cfbef1c4_web_precursors" + }, + { + "source": "f6564af9_AOL_and_early_internet_enclosure", + "target": "c301a0b3-1d8_Mosaic_Netscape_and_Browser_Wars" + }, + { + "source": "Syllogism", + "target": "Logical_consistency" + }, + { + "source": "Chipset_and_controllers", + "target": "Motherboard" + }, + { + "source": "Chipset_and_controllers", + "target": "What_are_disks" + }, + { + "source": "Chipset_and_controllers", + "target": "Bus" + }, + { + "source": "Boolean_function_synthesis", + "target": "Boolean_functions" + }, + { + "source": "Boolean_function_synthesis", + "target": "Logic_gates" + }, + { + "source": "Logical_possibility_and_necessity", + "target": "Logical_consistency" + }, + { + "source": "Logical_possibility_and_necessity", + "target": "Validity_and_entailment" + }, + { + "source": "Magnetic_core_memory", + "target": "Magnetic_drum_memory" + }, + { + "source": "Magnetic_core_memory", + "target": "Delay_line_memory" + } + ] +} \ No newline at end of file diff --git a/src/cli.py b/src/cli.py index 159b6bd..7960048 100644 --- a/src/cli.py +++ b/src/cli.py @@ -3,6 +3,7 @@ import argparse from constants import EOLAS_DIRECTORY from controllers.controller import Controller from services.database_service import DatabaseService +from services.graph_service import GraphService from services.parse_file_service import ParseFileService from services.table_service import TableService @@ -10,7 +11,10 @@ database_service = DatabaseService("eolas") database_connection = database_service.connect() table_service = TableService(database_connection) parse_file_service = ParseFileService(EOLAS_DIRECTORY) -controller = Controller(database_service, table_service, parse_file_service) +graph_service = GraphService(database_connection) +controller = Controller( + database_service, table_service, parse_file_service, graph_service +) def main(): @@ -18,13 +22,18 @@ def main(): prog="eolas-db", description="Eolas database manager." ) parser.add_argument( - "command", choices=["populate-database"], help="Command to execute" + "command", + choices=["populate-database", "generate-graph"], + help="Command to execute", ) args = parser.parse_args() if args.command == "populate-database": controller.populate_database() + if args.command == "generate-graph": + controller.generate_graph() + if __name__ == "__main__": main() diff --git a/src/constants.py b/src/constants.py index 206c36e..15362b5 100644 --- a/src/constants.py +++ b/src/constants.py @@ -1 +1,2 @@ EOLAS_DIRECTORY = "/home/thomas/repos/eolas/zk" +GRAPH_OUTPUT_DIRECTORY = "/home/thomas/repos/eolas-db/out" diff --git a/src/controllers/controller.py b/src/controllers/controller.py index d16c494..df80f6a 100644 --- a/src/controllers/controller.py +++ b/src/controllers/controller.py @@ -1,12 +1,30 @@ +from termcolor import colored + class Controller: - def __init__(self, database_service, table_service, parse_file_service): + def __init__( + self, database_service, table_service, parse_file_service, graph_service + ): self.database_service = database_service self.table_service = table_service self.parse_file_service = parse_file_service + self.graph_service = graph_service def populate_database(self): try: entries = self.parse_file_service.parse_source_directory() self.table_service.populate_tables(entries) + print(colored("SUCCESS Database populated", "green")) + except Exception as e: + raise Exception(colored(f"ERROR {e}", "red")) finally: self.database_service.disconnect() + print(colored("INFO Database connection closed", "blue")) + def generate_graph(self): + try: + self.graph_service.generate_graph() + print(colored("SUCCESS Graph generated", "green")) + except Exception as e: + raise Exception(colored(f"ERROR {e}"), "red") + finally: + self.database_service.disconnect() + print(colored("INFO Database connection closed", "blue")) diff --git a/src/models/entry.py b/src/models/entry.py index e94b844..cbc622e 100644 --- a/src/models/entry.py +++ b/src/models/entry.py @@ -1,7 +1,7 @@ from typing import List, TypedDict -class Entry(TypedDict): +class IEntry(TypedDict): title: str last_modified: str size: int diff --git a/src/models/graph_edge.py b/src/models/graph_edge.py new file mode 100644 index 0000000..0e920fb --- /dev/null +++ b/src/models/graph_edge.py @@ -0,0 +1,7 @@ +from typing import TypedDict + + +class IGraphEdge(TypedDict): + source: str + target: str + diff --git a/src/models/graph_node.py b/src/models/graph_node.py new file mode 100644 index 0000000..1a91580 --- /dev/null +++ b/src/models/graph_node.py @@ -0,0 +1,7 @@ +from typing import TypedDict + + +class IGraphNode(TypedDict): + id: str + type: str + diff --git a/src/services/database_service.py b/src/services/database_service.py index 9737c5a..ee5c116 100644 --- a/src/services/database_service.py +++ b/src/services/database_service.py @@ -18,10 +18,10 @@ class DatabaseService: try: if not os.path.exists(self.db_path): os.makedirs(self.db_path) - print(colored("INFO Created database directory", "light_blue")) + print(colored("INFO Created database directory", "blue")) self.connection = sqlite3.connect(f"{self.db_path}/{self.db_name}.db") self.connection.execute("PRAGMA foreign_keys = ON") - print(colored("INFO Database connection established", "light_blue")) + print(colored("INFO Database connection established", "blue")) return self.connection except Exception as e: diff --git a/src/services/graph_service.py b/src/services/graph_service.py new file mode 100644 index 0000000..a20dad1 --- /dev/null +++ b/src/services/graph_service.py @@ -0,0 +1,49 @@ +import json +from constants import GRAPH_OUTPUT_DIRECTORY +from services.sqlite_service import SqliteService +from models.graph_node import IGraphNode +from models.graph_edge import IGraphEdge + +class GraphService(SqliteService): + error_message_stub = "Could not retrieve contents of table:" + + def __init__(self, db_connection): + super().__init__(db_connection) + + def __get_nodes(self) -> list[IGraphNode]: + tags = self._query( + "SELECT * FROM tags", + error_message=f"{self.error_message_stub} tags", + ) + tags = [IGraphNode(id=f"#{tag[0]}", type="tag") for tag in tags] + entries = self._query( + "SELECT title FROM entries", + error_message=f"{self.error_message_stub} entries", + ) + + entries = [IGraphNode(id=entry[0], type="entry") for entry in entries] + return tags + entries + + def __get_edges(self): + tags = self._query( + "SELECT * FROM entries_tags", + error_message=f"{self.error_message_stub} entries_tags", + ) + + tags = [IGraphEdge(source=f"#{tag[1]}", target=tag[0]) for tag in tags] + + backlinks = self._query( + "SELECT * FROM backlinks", + error_message=f"{self.error_message_stub} backlinks", + ) + + backlinks = [IGraphEdge(source=f"{backlink[0]}", target = backlink[1]) for backlink in backlinks] + + + return tags + backlinks + + def generate_graph(self): + graph = {"nodes": self.__get_nodes(), "edges": self.__get_edges()} + + with open(f"{GRAPH_OUTPUT_DIRECTORY}/eolas-graph.json", "w") as f: + json.dump(graph, f, indent=4) diff --git a/src/services/parse_file_service.py b/src/services/parse_file_service.py index 0f46f93..d540c03 100644 --- a/src/services/parse_file_service.py +++ b/src/services/parse_file_service.py @@ -4,7 +4,7 @@ from pathlib import Path from termcolor import colored -from models.entry import Entry +from models.entry import IEntry from services.parse_markdown_service import ParseMarkdownService @@ -16,7 +16,7 @@ class ParseFileService: def __get_title(self, file): return os.path.splitext(os.path.basename(file))[0] - def __parse_file(self, file) -> Entry: + def __parse_file(self, file) -> IEntry: markdown_data = self.parse_markdown_service.parse(file) return { "title": self.__get_title(file), @@ -29,8 +29,8 @@ class ParseFileService: "body": markdown_data.get("body", []), } - def parse_source_directory(self) -> list[Entry]: - print(colored("INFO Indexing entries in source directory", "light_blue")) + def parse_source_directory(self) -> list[IEntry]: + print(colored("INFO Indexing entries in source directory", "blue")) parsed_entries = [] with os.scandir(self.source_directory) as dir: for file in dir: diff --git a/src/services/sqlite_service.py b/src/services/sqlite_service.py index 159dd9f..9c92b48 100644 --- a/src/services/sqlite_service.py +++ b/src/services/sqlite_service.py @@ -1,18 +1,13 @@ -import sqlite3 from typing import Optional -from termcolor import colored - -from models.entry import Entry -from sql.create_tables import tables - class SqliteService: def __init__(self, db_connection): self.connection = db_connection self.cursor = db_connection.cursor() - def _query(self, sql, params=None, errorMessage: Optional[str] = None): + def _execute(self, sql, params=None, error_message: Optional[str] = None): + """Use for CREATE, INSERT, UPDATE, DELETE""" try: if params: self.cursor.execute(sql, params) @@ -21,6 +16,20 @@ class SqliteService: self.connection.commit() except Exception as e: - if errorMessage: - raise Exception(f"ERROR {errorMessage}: {e}") + if error_message: + raise Exception(f"ERROR {error_message}: {e}") + raise + + def _query(self, sql, params=None, error_message: Optional[str] = None): + """Use for SELECT""" + try: + if params: + self.cursor.execute(sql, params) + else: + self.cursor.execute(sql) + return self.cursor.fetchall() + + except Exception as e: + if error_message: + raise Exception(f"ERROR {error_message}: {e}") raise diff --git a/src/services/table_service.py b/src/services/table_service.py index 930bde1..5802ae3 100644 --- a/src/services/table_service.py +++ b/src/services/table_service.py @@ -1,6 +1,6 @@ from termcolor import colored -from models.entry import Entry +from models.entry import IEntry from services.sqlite_service import SqliteService from sql.create_tables import tables @@ -11,58 +11,58 @@ class TableService(SqliteService): def __create_tables(self): for table in tables: - self._query( + self._execute( table["create_statement"], - errorMessage=f"Problem creating table {table['name']}", + error_message=f"Problem creating table {table['name']}", ) - print(colored("INFO Created tables", "light_blue")) + print(colored("INFO Created tables", "blue")) def __drop_tables(self): # Reverse the order of `tables` list to avoid foreign key violation when # deleting for table in reversed(tables): - self._query( + self._execute( f"DROP TABLE IF EXISTS {table['name']}", - errorMessage=f"Problem truncating table {table['name']}", + error_message=f"Problem truncating table {table['name']}", ) - print(colored("INFO Cleared tables", "light_blue")) + print(colored("INFO Cleared tables", "blue")) def __entry_exists(self, title) -> bool: - self._query("SELECT 1 FROM entries WHERE title = :title", {"title": title}) + self._execute("SELECT 1 FROM entries WHERE title = :title", {"title": title}) result = self.cursor.fetchone() return result is not None - def __populate_base_tables(self, entries: list[Entry]): + def __populate_base_tables(self, entries: list[IEntry]): for entry in entries: - self._query( + self._execute( "INSERT INTO entries (title, last_modified, size, body) VALUES (:title, :last_modified, :size, :body)", entry, - errorMessage=f"The following entry could not be added to `entries` table: {entry}", + error_message=f"The following entry could not be added to `entries` table: {entry}", ) tags = entry.get("tags") if tags: for tag in tags: - self._query( + self._execute( "INSERT OR IGNORE INTO tags (name) VALUES (:tag_name)", {"tag_name": tag}, ) - print(colored("INFO Base tables populated", "light_blue")) + print(colored("INFO Base tables populated", "blue")) - def __populate_junction_tables(self, entries: list[Entry]): + def __populate_junction_tables(self, entries: list[IEntry]): for entry in entries: tags = entry.get("tags") links = entry.get("links") if tags: for tag in tags: - self._query( + self._execute( "INSERT INTO entries_tags (entry_title, tag_name) VALUES (:entry_title, :tag_name)", {"entry_title": entry.get("title"), "tag_name": tag}, ) if links: for link in links: if self.__entry_exists(link): - self._query( + self._execute( "INSERT OR IGNORE INTO backlinks (source_entry_title, target_entry_title) VALUES (:source_entry_title, :target_entry_title)", { "source_entry_title": entry.get("title"), @@ -70,9 +70,9 @@ class TableService(SqliteService): }, ) - print(colored("INFO Junction tables populated", "light_blue")) + print(colored("INFO Junction tables populated", "blue")) - def populate_tables(self, entries: list[Entry]): + def populate_tables(self, entries: list[IEntry]): self.__drop_tables() self.__create_tables() self.__populate_base_tables(entries)