# notes

path: zk/Mapped_types_in_TS.md
sortable_path: zkMapped_types_in_TS.md
title: Mapped types in TypeScript
lead:
  A mapped type is a way to create new types based on existing ones by
  transforming their properties

checksum: ccabedb3387b7583fb0265e8e625b02b3cfe9ddc04875240fe8f29b61a4fab8e
created: 2024-06-16 17:37:31.534288441+00:00
modified: 2024-03-27 10:45:52.503525368+00:00
metadata: {"tags":["typescript"]}
body:
  A mapped type is a way to create new types based on existing ones by
  transforming their properties

  As it works on a single type and typically narrows or limits the properties it
  works in a way that is opposite to a [union]() or [intersection]() type.

  > Mapped types are an example of when `type` is preferable to `interface`, since
  > you cannot generate mapped types as interfaces, although you may generate a
  > mapped type from an interface.

  For the demonstrations we will use the following type as the example that we
  will map from:

  ```ts
  type Person = {
    name: string;
    age: number;
    city: string;
    country: string;
  };
  ```

  ## Main varieties of mapped types

  ### Read only

  Creates a type with all properties of the given type set to `readonly`:

  ```ts
  type Readonly<T> = {
    readonly [P in keyof T]: T[P];
  };

  type ReadonlyPerson = Readonly<Person>;
  ```

  This is equivalent to:

  ```ts
  type ReadonlyPerson = {
    readonly name: string;
    readonly age: number;
    readonly city: string;
    readonly country: string;
  };
  ```

  ### Partial

  Creates a type with all properties of the given type set to optional.

  ```ts
  type Partial<T> = {
    [P in keyof T]?: T[P];
  };

  type PartialPerson = Partial<Person>;
  ```

  This is equivalent to:

  ```ts
  type PartialPerson = {
    name?: string;
    age?: number;
    city?: string;
    country?: string;
  };
  ```

  ### Pick

  This is useful when you want to create a new type based on a subset of
  properties from an existing type.

  ```ts
  type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
  };

  type PersonNameAndAge = Pick<Person, "name" | "age">;
  ```

  This is equivalent to:

  ```ts
  type PersonNameAndAge = {
    name: string;
    age: number;
  };
  ```

  ### Record

  Creates a type with keys of the given type and values of the specified type. It
  is a way of shoehorning keys from an existing type with new values.

  Basic syntax:

  ```ts
  Record<Keys, ValueType>;
  ```

  Example:

  ```ts
  type UserRole = "admin" | "user" | "guest";

  // Create a Record type to store user role descriptions
  type UserRoleDescriptions = Record<UserRole, string>;

  // Create an object that implements the UserRoleDescriptions type
  const roleDescriptions: UserRoleDescriptions = {
    admin: "Has full access to the system",
    user: "Can access limited resources",
    guest: "Can view public resources only",
  };
  ```

  Here is a simpler example

  ```ts
  type Person = {
    name: string;
    nationality: string;
  };

  type PersonInstance = Record<string, Person>;
  const thomasInstance: PersonInstance = {
    thomas: {
      name: "Thomas",
      nationality: "British",
    },
  };
  ```

  ### Exclude

  Creates a type by excluding specific properties from the given type.

  ```ts
  type Exclude<T, U> = T extends U ? never : T;

  type KeysWithoutAge = Exclude<keyof Person, "age">;
  ```

  This is equivalent to:

  ```ts
  type KeysWithoutAge = "name" | "city" | "country";
  ```

  ### Extract

  Creates a type by extracting specific properties from the given type. Basically
  the opposite operation to Exclude.

  ```ts
  type Extract<T, U> = T extends U ? T : never;

  type NameKey = Extract<keyof Person, "name">;
  ```

  This is equivalent to:

  ```ts
  type NameKey = "name";
  ```

  ### Non-nullable

  Creates a type by removing null and undefined from the given type.

  ```ts
  type NonNullable<T> = T extends null | undefined ? never : T;

  type NullablePerson = {
    name: string | null;
    age: number | null;
    city: string | null;
    country: string | null;
  };

  type NonNullablePerson = NonNullable<NullablePerson>;
  ```

  Equivalent to:

  ```ts
  type NonNullablePerson = {
    name: string;
    age: number;
    city: string;
    country: string;
  };
  ```

raw_content:
  ---
  tags:
    - typescript
  ---

  # Mapped types in TypeScript

  A mapped type is a way to create new types based on existing ones by
  transforming their properties

  As it works on a single type and typically narrows or limits the properties it
  works in a way that is opposite to a [union]() or [intersection]() type.

  > Mapped types are an example of when `type` is preferable to `interface`, since
  > you cannot generate mapped types as interfaces, although you may generate a
  > mapped type from an interface.

  For the demonstrations we will use the following type as the example that we
  will map from:

  ```ts
  type Person = {
    name: string;
    age: number;
    city: string;
    country: string;
  };
  ```

  ## Main varieties of mapped types

  ### Read only

  Creates a type with all properties of the given type set to `readonly`:

  ```ts
  type Readonly<T> = {
    readonly [P in keyof T]: T[P];
  };

  type ReadonlyPerson = Readonly<Person>;
  ```

  This is equivalent to:

  ```ts
  type ReadonlyPerson = {
    readonly name: string;
    readonly age: number;
    readonly city: string;
    readonly country: string;
  };
  ```

  ### Partial

  Creates a type with all properties of the given type set to optional.

  ```ts
  type Partial<T> = {
    [P in keyof T]?: T[P];
  };

  type PartialPerson = Partial<Person>;
  ```

  This is equivalent to:

  ```ts
  type PartialPerson = {
    name?: string;
    age?: number;
    city?: string;
    country?: string;
  };
  ```

  ### Pick

  This is useful when you want to create a new type based on a subset of
  properties from an existing type.

  ```ts
  type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
  };

  type PersonNameAndAge = Pick<Person, "name" | "age">;
  ```

  This is equivalent to:

  ```ts
  type PersonNameAndAge = {
    name: string;
    age: number;
  };
  ```

  ### Record

  Creates a type with keys of the given type and values of the specified type. It
  is a way of shoehorning keys from an existing type with new values.

  Basic syntax:

  ```ts
  Record<Keys, ValueType>;
  ```

  Example:

  ```ts
  type UserRole = "admin" | "user" | "guest";

  // Create a Record type to store user role descriptions
  type UserRoleDescriptions = Record<UserRole, string>;

  // Create an object that implements the UserRoleDescriptions type
  const roleDescriptions: UserRoleDescriptions = {
    admin: "Has full access to the system",
    user: "Can access limited resources",
    guest: "Can view public resources only",
  };
  ```

  Here is a simpler example

  ```ts
  type Person = {
    name: string;
    nationality: string;
  };

  type PersonInstance = Record<string, Person>;
  const thomasInstance: PersonInstance = {
    thomas: {
      name: "Thomas",
      nationality: "British",
    },
  };
  ```

  ### Exclude

  Creates a type by excluding specific properties from the given type.

  ```ts
  type Exclude<T, U> = T extends U ? never : T;

  type KeysWithoutAge = Exclude<keyof Person, "age">;
  ```

  This is equivalent to:

  ```ts
  type KeysWithoutAge = "name" | "city" | "country";
  ```

  ### Extract

  Creates a type by extracting specific properties from the given type. Basically
  the opposite operation to Exclude.

  ```ts
  type Extract<T, U> = T extends U ? T : never;

  type NameKey = Extract<keyof Person, "name">;
  ```

  This is equivalent to:

  ```ts
  type NameKey = "name";
  ```

  ### Non-nullable

  Creates a type by removing null and undefined from the given type.

  ```ts
  type NonNullable<T> = T extends null | undefined ? never : T;

  type NullablePerson = {
    name: string | null;
    age: number | null;
    city: string | null;
    country: string | null;
  };

  type NonNullablePerson = NonNullable<NullablePerson>;
  ```

  Equivalent to:

  ```ts
  type NonNullablePerson = {
    name: string;
    age: number;
    city: string;
    country: string;
  };
  ```


path: zk/Maps_and_sets_in_JS.md
sortable_path: zkMaps_and_sets_in_JS.md
title: Maps and Sets
checksum: 391de8d7c7b97236ff25a0ce78fc54bd629b9d1010dd5c1ed91b6de808339bac
created: 2024-06-16 17:37:31.540343064+00:00
modified: 2024-03-27 10:45:52.503525368+00:00
metadata: {"tags":["javascript"]}
lead:
  > Both `Map` and `Set` are new data structures introduced with ES6. They combine
  > the properties of the pre-existing data structures: arrays and objects and
  > offer advantages in certain non-typical use cases.

body:
  > Both `Map` and `Set` are new data structures introduced with ES6. They combine
  > the properties of the pre-existing data structures: arrays and objects and
  > offer advantages in certain non-typical use cases.

  ## Maps

  ### Concepts

  A map (not to be confused with the array map method) introduces something like
  the associative array model to JavaScript. Prior to ES6 the closest thing JS had
  to this was an object.

  Maps are like objects in that their structure consists in key/map pairs but like
  arrays in that the order in which the entries are placed is retained and can be
  referred to throughout the lifecycle of the Map. Also, the length of the Map is
  a known and easily returnable quantity, with objects we have to do some
  wrangling with `Object.keys` and `Object.entries` to retrieve meta data about
  the object itself. Moreover, with an object the order in which the keys are
  stored is not recorded.

  At the same time Maps are different from arrays because the index of an array
  element is not unique, it will always be a number of the form `[0], [1], [2]...`
  .

  Finally, the key can be any data type not just a string. This is an important
  characteristic of maps because although you can use numbers or booleans as the
  keys in an object, they are not actually numbers, they are converted to strings
  at execution. With Maps, whatever data type you assign as a key, retains its
  type.

  Maps

  - Have key/value pair structure
  - Have length property
  - Order of entries and insertions is maintained
  - Can use any data type as a key
  - Disallow duplicate keys

  ### Creating a Map and adding entries

  ```jsx
  const map = new Map();

  // We then pass in key/value pairs using `set`:
  map.set("firstName", "Luke");
  map.set("lastName", "Skywalker");
  map.set("occupation", "Jedi Knight");
  ```

  There is an alternative method for defining a map:

  ```jsx
  const map = new Map([
    ["firstName", "Luke"],
    ["lastName", "Skywalker"],
    ["occupation", "Jedi Knight"],
  ]);
  ```

  Internally, this data will be represented as follows:

  ```
  Map(3)
  0: {"firstName" => "Luke"}
  1: {"lastName" => "Skywalker"}
  2: {"occupation" => "Jedi Knight"}
  ```

  ### Working with map elements

  ```jsx
  // check for the existence of an item in a map by searching for existence of key
  map.has("firstName"); // return boolean

  // return all keys in a Map as iterator
  map.keys(); // MapIterator {'firstName', 'lastName', 'occupation'}

  // return all values as iterator
  map.values();

  // return array of key/value pairs
  map.entries(); // {"firstName" => "Luke", "lastName" => "Skywalker", "occupation" => "Jedi Knight"}
  // retrieve an item from a Map
  map.get("lastName"); // Skywalker

  // delete an item from a map by key, returns boolean as confirmation
  map.delete("occupation"); // true

  //return the length of a map (just like array.length)
  map.size; // 3
  // clear all values
  map.clear();
  ```

  ### Looping

  ```jsx
  // Map has its own .forEach method, like with arrays. Hewre they are side by side

  // Map
  Map.prototype.forEach((value, key, map) = () => {})

  // Array
  Array.prototype.forEach((item, index, array) = () => {})

  // You can also use a for of loop
  // Destructure the key and value out of the Map item
  for (const [key, value] of map) {
    // Log the keys and values of the Map with for...of
    console.log(`${key}: ${value}`)
  }
  ```

  ### Interfacing between Maps and other reference types

  Given that we can create a map with both object and array-style syntax, its easy
  to convert maps to and from the more established data structures.

  It's easy to convert an object to a map:

  ```jsx
  const luke = {
    firstName: "Luke",
    lastName: "Skywalker",
    occupation: "Jedi Knight",
  };

  const map = new Map(Object.entries(luke));
  ```

  And a map to an object:

  ```jsx
  const obj = Object.fromEntries(map);
  ```

  A map to an array:

  ```jsx
  const arr = Array.from(map);
  ```

  We saw earlier that a Map is a multidimensional array, so any multidimensional
  array can be used in the Map constructor invocation to turn it into a Map.

  ## Sets

  A set is special kind of array, an atypical supplement to arrays. It is
  basically an array of unique values. If you try to add a duplicate entry to a
  set it will be ignored.

  ```jsx
  const set = new Set();
  set.add("Beethoven");
  set.add("Bach");

  // Or:
  const set = new Set(["Beethoven", "Bach"]);

  // Convert array to set (note, this will remove duplicates on initialisation)
  const arr = [...set];
  ```

  We can use `keys()`, `values()`, and `entries()` with sets but obviously, `keys`
  and `values` will be identical.

raw_content:
  ---
  tags: [javascript]
  ---

  # Maps and Sets

  > Both `Map` and `Set` are new data structures introduced with ES6. They combine
  > the properties of the pre-existing data structures: arrays and objects and
  > offer advantages in certain non-typical use cases.

  ## Maps

  ### Concepts

  A map (not to be confused with the array map method) introduces something like
  the associative array model to JavaScript. Prior to ES6 the closest thing JS had
  to this was an object.

  Maps are like objects in that their structure consists in key/map pairs but like
  arrays in that the order in which the entries are placed is retained and can be
  referred to throughout the lifecycle of the Map. Also, the length of the Map is
  a known and easily returnable quantity, with objects we have to do some
  wrangling with `Object.keys` and `Object.entries` to retrieve meta data about
  the object itself. Moreover, with an object the order in which the keys are
  stored is not recorded.

  At the same time Maps are different from arrays because the index of an array
  element is not unique, it will always be a number of the form `[0], [1], [2]...`
  .

  Finally, the key can be any data type not just a string. This is an important
  characteristic of maps because although you can use numbers or booleans as the
  keys in an object, they are not actually numbers, they are converted to strings
  at execution. With Maps, whatever data type you assign as a key, retains its
  type.

  Maps

  - Have key/value pair structure
  - Have length property
  - Order of entries and insertions is maintained
  - Can use any data type as a key
  - Disallow duplicate keys

  ### Creating a Map and adding entries

  ```jsx
  const map = new Map();

  // We then pass in key/value pairs using `set`:
  map.set("firstName", "Luke");
  map.set("lastName", "Skywalker");
  map.set("occupation", "Jedi Knight");
  ```

  There is an alternative method for defining a map:

  ```jsx
  const map = new Map([
    ["firstName", "Luke"],
    ["lastName", "Skywalker"],
    ["occupation", "Jedi Knight"],
  ]);
  ```

  Internally, this data will be represented as follows:

  ```
  Map(3)
  0: {"firstName" => "Luke"}
  1: {"lastName" => "Skywalker"}
  2: {"occupation" => "Jedi Knight"}
  ```

  ### Working with map elements

  ```jsx
  // check for the existence of an item in a map by searching for existence of key
  map.has("firstName"); // return boolean

  // return all keys in a Map as iterator
  map.keys(); // MapIterator {'firstName', 'lastName', 'occupation'}

  // return all values as iterator
  map.values();

  // return array of key/value pairs
  map.entries(); // {"firstName" => "Luke", "lastName" => "Skywalker", "occupation" => "Jedi Knight"}
  // retrieve an item from a Map
  map.get("lastName"); // Skywalker

  // delete an item from a map by key, returns boolean as confirmation
  map.delete("occupation"); // true

  //return the length of a map (just like array.length)
  map.size; // 3
  // clear all values
  map.clear();
  ```

  ### Looping

  ```jsx
  // Map has its own .forEach method, like with arrays. Hewre they are side by side

  // Map
  Map.prototype.forEach((value, key, map) = () => {})

  // Array
  Array.prototype.forEach((item, index, array) = () => {})

  // You can also use a for of loop
  // Destructure the key and value out of the Map item
  for (const [key, value] of map) {
    // Log the keys and values of the Map with for...of
    console.log(`${key}: ${value}`)
  }
  ```

  ### Interfacing between Maps and other reference types

  Given that we can create a map with both object and array-style syntax, its easy
  to convert maps to and from the more established data structures.

  It's easy to convert an object to a map:

  ```jsx
  const luke = {
    firstName: "Luke",
    lastName: "Skywalker",
    occupation: "Jedi Knight",
  };

  const map = new Map(Object.entries(luke));
  ```

  And a map to an object:

  ```jsx
  const obj = Object.fromEntries(map);
  ```

  A map to an array:

  ```jsx
  const arr = Array.from(map);
  ```

  We saw earlier that a Map is a multidimensional array, so any multidimensional
  array can be used in the Map constructor invocation to turn it into a Map.

  ## Sets

  A set is special kind of array, an atypical supplement to arrays. It is
  basically an array of unique values. If you try to add a duplicate entry to a
  set it will be ignored.

  ```jsx
  const set = new Set();
  set.add("Beethoven");
  set.add("Bach");

  // Or:
  const set = new Set(["Beethoven", "Bach"]);

  // Convert array to set (note, this will remove duplicates on initialisation)
  const arr = [...set];
  ```

  We can use `keys()`, `values()`, and `entries()` with sets but obviously, `keys`
  and `values` will be identical.


path: zk/Middleware_in_NodeJS.md
sortable_path: zkMiddleware_in_NodeJS.md
title: Middleware
lead: ## What is middleware?
checksum: cc530669082b3716b21388f1c2ef4e95e3e1c2d678e96e586dec2cc8a3f66f4b
created: 2024-06-16 17:37:31.546028105+00:00
modified: 2024-06-16 17:18:22.098336515+00:00
metadata: {"tags":["node-js","middleware"]}
body:
  ## What is middleware?

  - Anything that terminates the `req, res` cycle counts as middleware. It is
    basically anything that acts as an intermediary once the request is received
    but before the resource is sent. A good example would be the
    `app.use(express.json()` or `app.use(bodyParser.json)` functions we call in
    order to be able to parse JSON that is sent from the client.
  - You will most likely have multiple middleware functions running at once. We
    call this intermediary part of the cycle the **request processing pipeline**.
  - Generally all middleware will be added as a property on the Express `app`
    instance with the `app.use(...)` syntax.

  ## Creating custom middleware functions

  ### Basic schema

  ```js
  app.use((req, res, next) => {
    // do some middleware
    next();
  });
  ```

  ### `next`

  The `next` parameter is key, it allows Express to move onto the next middleware
  function once the custom middleware executes. Without it, the request processing
  pipeline will get blocked.

  Middleware functions are basically asynchronous requests and as such they use a
  similar syntax as Promises (e.g `then`) for sequencing processes.

  ### Example of sequence

  ```js
  app.use((req, res, next) => {
    console.log("Do process A...");
    next();
  });

  app.use((req, res, next) => {
    console.log("Do process B...");
    next();
  });
  ```

  > It makes more sense of course to define our middleware within a function and
  > then pass it as an argument to `app.use()`

  ## Including middleware based on environment

  With a full-scale Node application you will typically run three environments:

  - Development
  - Testing
  - Production

  We will not want to run certain types of middleware in all environments. For
  example, it would be costly to run logging in the app's production environment.
  It would make more sense to run this only in development.

  ### Accessing current Node environment

  We can control which middleware we run via the Node envrionment variables:
  `process.env` (see for instance [ports](Ports_in_NodeJS.md)).

  We could set
  [Morgan](Morgan.md) to run
  only in development with:

  ```js
  if (app.get("env") === "development") {
    app.use(morgan("common"));
    console.log("Morgan enabled");
  }
  ```

raw_content:
  ---
  tags:
    - node-js
    - middleware
  ---

  # Middleware

  ## What is middleware?

  - Anything that terminates the `req, res` cycle counts as middleware. It is
    basically anything that acts as an intermediary once the request is received
    but before the resource is sent. A good example would be the
    `app.use(express.json()` or `app.use(bodyParser.json)` functions we call in
    order to be able to parse JSON that is sent from the client.
  - You will most likely have multiple middleware functions running at once. We
    call this intermediary part of the cycle the **request processing pipeline**.
  - Generally all middleware will be added as a property on the Express `app`
    instance with the `app.use(...)` syntax.

  ## Creating custom middleware functions

  ### Basic schema

  ```js
  app.use((req, res, next) => {
    // do some middleware
    next();
  });
  ```

  ### `next`

  The `next` parameter is key, it allows Express to move onto the next middleware
  function once the custom middleware executes. Without it, the request processing
  pipeline will get blocked.

  Middleware functions are basically asynchronous requests and as such they use a
  similar syntax as Promises (e.g `then`) for sequencing processes.

  ### Example of sequence

  ```js
  app.use((req, res, next) => {
    console.log("Do process A...");
    next();
  });

  app.use((req, res, next) => {
    console.log("Do process B...");
    next();
  });
  ```

  > It makes more sense of course to define our middleware within a function and
  > then pass it as an argument to `app.use()`

  ## Including middleware based on environment

  With a full-scale Node application you will typically run three environments:

  - Development
  - Testing
  - Production

  We will not want to run certain types of middleware in all environments. For
  example, it would be costly to run logging in the app's production environment.
  It would make more sense to run this only in development.

  ### Accessing current Node environment

  We can control which middleware we run via the Node envrionment variables:
  `process.env` (see for instance [ports](Ports_in_NodeJS.md)).

  We could set
  [Morgan](Morgan.md) to run
  only in development with:

  ```js
  if (app.get("env") === "development") {
    app.use(morgan("common"));
    console.log("Morgan enabled");
  }
  ```


path: zk/Modules_in_NodeJS.md
sortable_path: zkModules_in_NodeJS.md
title: Modules
checksum: 9d03b5ccc104e11c3ef76f35571497cf375083499eb5f3b5f78548785b8d21f0
created: 2024-06-16 17:37:31.573910162+00:00
modified: 2024-06-15 09:50:29.696637857+00:00
metadata: {"tags":["node-js"]}
lead:
  > Modules are partitioned files where we define our variables and functions.
  > Values defined in modules are scoped to that specific module, constituting a
  > unique name space. This avoids name clashes in large programs.

body:
  > Modules are partitioned files where we define our variables and functions.
  > Values defined in modules are scoped to that specific module, constituting a
  > unique name space. This avoids name clashes in large programs.

  - Every file in a Node application is considered a module.

  - The variables and methods in a module are equivalent to `private` properties
    and methods in object-oriented programming.

  - If you wish to use a function or variable defined in a module outside of its
    modular container you need to explicitly export it and make it public.

  ## Structure of a module

  Node keeps an internal record of the properties of a module. To see this we can
  log the property `module` to the console.

  ```js
  // index.js
  console.log(module);
  ```

  This gives us:

  ```plaintext
  Module {
   id: '.',
   path: '/home/thomas/repos/node-learning',
   exports: {},
   filename: '/home/thomas/repos/node-learning/index.js',
   loaded: false,
   children: [],
   paths: [
     '/home/thomas/repos/node-learning/node_modules',
     '/home/thomas/repos/node_modules',
     '/home/thomas/node_modules',
     '/home/node_modules',
     '/node_modules'
   ]
  }
  ```

  ## Exports

  - Whenever we export a property or method from a module we are directly
    targeting the `exports` property of the module object.
  - Once we add exports to a file they will be displayed under that property of
    the module object.
  - We can export the entire module itself as the export (typically used when the
    module is a single function or class) or individual properties.

  ### Exporting a whole module

  _The example below is a module file that consists in a single function_

  ```js
  module.exports = function (...params) {
    // function body
  };
  ```

  Note the module is unnamed. We would name it when we import:

  ```js
  const myFunction = require("./filenme");
  ```

  ### Exporting sub-components from a module

  In the example below we export a variable and function from the same module.
  Note only those values prefixed with `exports` are exported.

  ```js
  exports.myFunc = (...params) => {
    // function bod[]()y
  };

  exports.aVar = 321.3;

  var nonExportedVar = true;
  ```

  This time the exports are already name so we would import with the following:

  ```js
  const { myFunc, aVar } = require("./filename");
  ```

  We can also do the exporting at the bottom when the individual components are
  named:

  ```js
  const myNamedFunc = (val) => {
    return val + 1;
  };

  function anotherNamedFunc(val) {
    return val * 2;
  }

  // This time we export at the bottom
  exports.myNamedFunc = myNamedFunc;
  exports.differentName = anotherNamedFunc; // We can use different names

  // Or we could export them together
  module.exports = { myNamedFunc, anotherNamedFunc };
  ```

  The import is the same:

  ```js
  const { myNamedFunc, anotherNamedFunc } = require("./modules/multiExports");
  ```

  ## Structuring modules

  The techniques above are useful to know but generally you would want to enforce
  a stricter structure than a mix of exported and private values in the one file.
  The best way to do this is with a single default export.

  Here the thing exported could be a composite function or an object that
  basically acts like a class with methods and properties.

  _Export a composite single function_

  ```js

  module.exports = () => {
  	foo() {...}
  	bar() {...}
  }
  ```

  _Export an object_

  ```js

  module.exports = {
  	foo : () => {...},
      bar: () => {...}
  }
  ```

  **Both of these structures would be referred to in the same way when importing
  and using them.**

  Or you could export an actual class as the default. This is practically the same
  as the two above other than that you would have to use `new` to initiate an
  instance of the class.

  ```js
  export default class {
    foo() {}
    bar() {}
  }
  ```

  Every method and property within the export will be public by default, whether
  it is an object, class or function. If you wanted to keep certain
  methods/properties private, the best approach is to define them as variables and
  functions within the module file but outside of the `export` block.

raw_content:
  ---
  tags:
    - node-js
  ---

  # Modules

  > Modules are partitioned files where we define our variables and functions.
  > Values defined in modules are scoped to that specific module, constituting a
  > unique name space. This avoids name clashes in large programs.

  - Every file in a Node application is considered a module.

  - The variables and methods in a module are equivalent to `private` properties
    and methods in object-oriented programming.

  - If you wish to use a function or variable defined in a module outside of its
    modular container you need to explicitly export it and make it public.

  ## Structure of a module

  Node keeps an internal record of the properties of a module. To see this we can
  log the property `module` to the console.

  ```js
  // index.js
  console.log(module);
  ```

  This gives us:

  ```plaintext
  Module {
   id: '.',
   path: '/home/thomas/repos/node-learning',
   exports: {},
   filename: '/home/thomas/repos/node-learning/index.js',
   loaded: false,
   children: [],
   paths: [
     '/home/thomas/repos/node-learning/node_modules',
     '/home/thomas/repos/node_modules',
     '/home/thomas/node_modules',
     '/home/node_modules',
     '/node_modules'
   ]
  }
  ```

  ## Exports

  - Whenever we export a property or method from a module we are directly
    targeting the `exports` property of the module object.
  - Once we add exports to a file they will be displayed under that property of
    the module object.
  - We can export the entire module itself as the export (typically used when the
    module is a single function or class) or individual properties.

  ### Exporting a whole module

  _The example below is a module file that consists in a single function_

  ```js
  module.exports = function (...params) {
    // function body
  };
  ```

  Note the module is unnamed. We would name it when we import:

  ```js
  const myFunction = require("./filenme");
  ```

  ### Exporting sub-components from a module

  In the example below we export a variable and function from the same module.
  Note only those values prefixed with `exports` are exported.

  ```js
  exports.myFunc = (...params) => {
    // function bod[]()y
  };

  exports.aVar = 321.3;

  var nonExportedVar = true;
  ```

  This time the exports are already name so we would import with the following:

  ```js
  const { myFunc, aVar } = require("./filename");
  ```

  We can also do the exporting at the bottom when the individual components are
  named:

  ```js
  const myNamedFunc = (val) => {
    return val + 1;
  };

  function anotherNamedFunc(val) {
    return val * 2;
  }

  // This time we export at the bottom
  exports.myNamedFunc = myNamedFunc;
  exports.differentName = anotherNamedFunc; // We can use different names

  // Or we could export them together
  module.exports = { myNamedFunc, anotherNamedFunc };
  ```

  The import is the same:

  ```js
  const { myNamedFunc, anotherNamedFunc } = require("./modules/multiExports");
  ```

  ## Structuring modules

  The techniques above are useful to know but generally you would want to enforce
  a stricter structure than a mix of exported and private values in the one file.
  The best way to do this is with a single default export.

  Here the thing exported could be a composite function or an object that
  basically acts like a class with methods and properties.

  _Export a composite single function_

  ```js

  module.exports = () => {
  	foo() {...}
  	bar() {...}
  }
  ```

  _Export an object_

  ```js

  module.exports = {
  	foo : () => {...},
      bar: () => {...}
  }
  ```

  **Both of these structures would be referred to in the same way when importing
  and using them.**

  Or you could export an actual class as the default. This is practically the same
  as the two above other than that you would have to use `new` to initiate an
  instance of the class.

  ```js
  export default class {
    foo() {}
    bar() {}
  }
  ```

  Every method and property within the export will be public by default, whether
  it is an object, class or function. If you wanted to keep certain
  methods/properties private, the best approach is to define them as variables and
  functions within the module file but outside of the `export` block.


path: zk/Non_null_assertion_in_TypeScript.md
sortable_path: zkNon_null_assertion_in_TypeScript.md
title: Non-null assertion
lead: Oftentimes you will encounter errors of the form:
checksum: 3afb6d654d3d9d9c24f9155a366976af6b70dc7f501848f73c2cb17e7c8e6455
created: 2024-06-16 17:37:31.703255445+00:00
modified: 2024-03-27 10:45:52.503525368+00:00
metadata: {"tags":["typescript"]}
body:
  Oftentimes you will encounter errors of the form:

  `Property [property_name] does not exist on type [type_name].ts(2339)`

  This means the interpreter is not able to determine whether the property which
  you are seeking to change exists. It can't be sure that you are not trying to
  update a property that is either `null` or `undefined`. This is good type
  checking but it means that in cases when _you know_ the property either exists
  or _will_ exist at runtime, you are going to face a code-breaking error.

  To get around this you can use non-null assertion. Like the name suggests, here
  you are saying to TypeScript: thanks but I am sure this property exists. When
  you do this you get the value you are trying to change with `null` and
  `undefined` excluded from it.

  This typically occurs when you are assigning a property to a value and TS
  doesn't know whether the value will exist or be accessible at this point in the
  runtime. A good scenario would be dynamic data passed into a function:

  ```ts
  function doSomethingWith(typeAlias: ITypeAlias) {
    let x = typeAlias!.somePropertyEvidentAtRuntime;
  }
  ```

  However it should be used carefully and sparingly because you are obviously
  turning off core type-checking and overuse nullifies the purpose of TypeScript.

  One way to get around it is to use better
  [type-guarding](Type_guarding_and_narrowing.md) and conditionality and to
  cover cases where the value may be undefined.

raw_content:
  ---
  tags:
    - typescript
  ---

  # Non-null assertion

  Oftentimes you will encounter errors of the form:

  `Property [property_name] does not exist on type [type_name].ts(2339)`

  This means the interpreter is not able to determine whether the property which
  you are seeking to change exists. It can't be sure that you are not trying to
  update a property that is either `null` or `undefined`. This is good type
  checking but it means that in cases when _you know_ the property either exists
  or _will_ exist at runtime, you are going to face a code-breaking error.

  To get around this you can use non-null assertion. Like the name suggests, here
  you are saying to TypeScript: thanks but I am sure this property exists. When
  you do this you get the value you are trying to change with `null` and
  `undefined` excluded from it.

  This typically occurs when you are assigning a property to a value and TS
  doesn't know whether the value will exist or be accessible at this point in the
  runtime. A good scenario would be dynamic data passed into a function:

  ```ts
  function doSomethingWith(typeAlias: ITypeAlias) {
    let x = typeAlias!.somePropertyEvidentAtRuntime;
  }
  ```

  However it should be used carefully and sparingly because you are obviously
  turning off core type-checking and overuse nullifies the purpose of TypeScript.

  One way to get around it is to use better
  [type-guarding](Type_guarding_and_narrowing.md) and conditionality and to
  cover cases where the value may be undefined.


path: zk/Package_management_in_NodeJS.md
sortable_path: zkPackage_management_in_NodeJS.md
title: Package management
lead: ## List installed packages
checksum: a4752920727fecb5b8ce97d7572b92652a86d679349fb8b71c6d9695790bc888
created: 2024-06-16 17:37:31.719175457+00:00
modified: 2024-06-15 09:50:35.966759132+00:00
metadata: {"tags":["node-js"]}
body:
  ## List installed packages

  ```bash
  npm list
  ```

  This will return a recursive tree that lists dependencies, dependences of
  dependencies, ... and so on. To limit the depth you can add the `--depth=` flag.
  For example to see only your installed packages and their versions use
  `npm list --depth=0`.

  ## View `package.json` data for an installed package

  We could go to the NPM registry and view details or we can quickly view the
  `package.json` for the dependency with the command `npm view [package_name]`

  We can pinpoint specific dependencies in the `package.json`, e.g.
  `npm view [package_name] dependencies `

  ## View outdated modules

  See whether your dependency version is out of date use `npm outdated`. This
  gives us a table, for example:

  ![Pasted image 20220411082627.png](Pasted_image_20220411082627.png)

  - _Latest_ tells us the latest release available from the developers
  - _Wanted_ tells us the version that our `package.json` rules target. To take
    the first dependency as an example. We must have set our SemVer syntax to
    `^0.4.x` since it is telling us that there is a minor release that is more
    recent than the one we have installed but is not advising that we update to
    the latest major release.
  - _Current_ tells us which version we currently have installed regardless of the
    version that our `package.json` is targeting or the most recent version
    available.

  ## Updating

  `npm update` only updates from _current_ to _wanted_. In other words it only
  updates in accordance with your caret and tilde rules applied to
  [semantic versioning](Semantic_versioning.md).

raw_content:
  ---
  tags:
    - node-js
  ---

  # Package management

  ## List installed packages

  ```bash
  npm list
  ```

  This will return a recursive tree that lists dependencies, dependences of
  dependencies, ... and so on. To limit the depth you can add the `--depth=` flag.
  For example to see only your installed packages and their versions use
  `npm list --depth=0`.

  ## View `package.json` data for an installed package

  We could go to the NPM registry and view details or we can quickly view the
  `package.json` for the dependency with the command `npm view [package_name]`

  We can pinpoint specific dependencies in the `package.json`, e.g.
  `npm view [package_name] dependencies `

  ## View outdated modules

  See whether your dependency version is out of date use `npm outdated`. This
  gives us a table, for example:

  ![Pasted image 20220411082627.png](Pasted_image_20220411082627.png)

  - _Latest_ tells us the latest release available from the developers
  - _Wanted_ tells us the version that our `package.json` rules target. To take
    the first dependency as an example. We must have set our SemVer syntax to
    `^0.4.x` since it is telling us that there is a minor release that is more
    recent than the one we have installed but is not advising that we update to
    the latest major release.
  - _Current_ tells us which version we currently have installed regardless of the
    version that our `package.json` is targeting or the most recent version
    available.

  ## Updating

  `npm update` only updates from _current_ to _wanted_. In other words it only
  updates in accordance with your caret and tilde rules applied to
  [semantic versioning](Semantic_versioning.md).


path: zk/Ports_in_NodeJS.md
sortable_path: zkPorts_in_NodeJS.md
title: Ports
checksum: c9975673e974869e0d02f1f89f50d66c63960e6cdd9b0af1d6d5912241e71bb3
created: 2024-06-16 17:37:31.730278283+00:00
modified: 2024-06-15 09:50:38.086800108+00:00
metadata: {"tags":["node-js"]}
lead:
  When working in development we are able to specify the specific port from which
  we want top serve our application. In production, we do not always have this
  control: the port will most likely be set by the provider of the server
  environment.

body:
  When working in development we are able to specify the specific port from which
  we want top serve our application. In production, we do not always have this
  control: the port will most likely be set by the provider of the server
  environment.

  While we may not know the specific port, whatever it is, it will be accessible
  via the `PORT` environment variable. So we can use this when writing our
  [event listeners](Events%20module.md#event-emitters):

  ```js
  const port = process.env.PORT || 3000;
  ```

  This way, if a port is set by the provider it will use it. If not, it will fall
  back to 3000.

raw_content:
  ---
  tags:
    - node-js
  ---

  # Ports

  When working in development we are able to specify the specific port from which
  we want top serve our application. In production, we do not always have this
  control: the port will most likely be set by the provider of the server
  environment.

  While we may not know the specific port, whatever it is, it will be accessible
  via the `PORT` environment variable. So we can use this when writing our
  [event listeners](Events%20module.md#event-emitters):

  ```js
  const port = process.env.PORT || 3000;
  ```

  This way, if a port is set by the provider it will use it. If not, it will fall
  back to 3000.


path: zk/Printing_values_in_C.md
sortable_path: zkPrinting_values_in_C.md
title: Printing values in C
lead: # Printing values in C
checksum: 16d854f6517315d8456373ef1c9943b600da2024d010a6029f9fc1e6cd9f20a2
created: 2024-06-16 17:37:31.744437412+00:00
modified: 2024-06-16 17:19:46.997337347+00:00
body:
  # Printing values in C

  ## To print a literal

  ```c
  printf("hello world")
  ```

  ## To print a variable

  ```c
  int age = 25
  print("%d", age)

  ```

  The `%d` is an example of a [format specifier](./zk/format-specifiers-in-c.md).
  It is the decimal integer format specifier.

raw_content:
  ---
  id: 3hcv0amc
  title: Printing values in C
  tags:
    - C
  created: Thursday, February 29, 2024 | 17:33
  ---

  # Printing values in C

  ## To print a literal

  ```c
  printf("hello world")
  ```

  ## To print a variable

  ```c
  int age = 25
  print("%d", age)

  ```

  The `%d` is an example of a [format specifier](./zk/format-specifiers-in-c.md).
  It is the decimal integer format specifier.

metadata:
  {"created":"Thursday, February 29, 2024 | 17:33","id":"3hcv0amc","tags":["C"],"title":"Printing values in C"}


path: zk/Process_module_in_NodeJS.md
sortable_path: zkProcess_module_in_NodeJS.md
title: The process module in Node.js
checksum: c0471abbd224662b086b5b3f40c8d67e46decb2adefb72bb979d0b92686a0b94
created: 2024-06-16 17:37:31.760848902+00:00
modified: 2024-06-16 17:15:36.691080654+00:00
metadata: {"tags":["node-js"]}
lead:
  `process` is a core module and a global object accessible from anywhere in a
  Node.js application. It contains functionality that allows us to interact with
  information about the current process instance of Node.

body:
  `process` is a core module and a global object accessible from anywhere in a
  Node.js application. It contains functionality that allows us to interact with
  information about the current process instance of Node.

  For example, we can use it to get environment information, read environment
  variables, parse arguments that are passed to the run command, communicate with
  the terminal and exit the current process.

  ## Managing runtime environments

  See
  [Managing Environments](Managing_environments_in_NodeJS.md).

  ## Accessing arguments: `process.argv`

  We can use `process.argv` to return an array containing the command-line
  arguments passed when a Node process is launched. This could be a whole-app
  entrypoint (i.e. `index.js`) or a single file we are running.

  For instance if we run the following file:

  ```js
  // process-demo.js
  console.log(3 + 3);
  console.log(process.argv);
  ```

  We get:

  ```bash
  6
  [
    '/Users/thomasbishop/.nvm/versions/node/v16.10.0/bin/node',
    '/Users/thomasbishop/prepos/testNode.js'
  ]
  ```

  The first item is the last executed process. The second is the array of
  arguments.

  In the array, the first value is a reference to the Node runtime binary. The
  second is the file that was passed to Node.

  If we passed in a parameter we would get that too:

  ```
  node process-demo.js --fakeFlag
  ```

  Gives us:

  ```bash
  [
    "/Users/thomasbishop/.nvm/versions/node/v16.10.0/bin/node",
    "/Users/thomasbishop/prepos/testNode.js",
    "--fake-flag",
  ]
  ```

  When writing Node CLI applications we can write functions that parse standard
  input. For example:

  ```js
  function parseStandardInput(flag) {
    let indexAfterFlag = process.argv.indexOf(flag);
    console.log(process.argv[indexAfterFlag]);
  }
  ```

  Say we ran a program that took in a username:

  ```bash
  node userName.js --user Thomas
  ```

  Then `parseStandardInput("--user")` would give us `"thomas"`

  ## Standard input and output

  Below is the most basic use case: writing to the output.

  ```js
  // alpha.js
  process.stdout.write("Hello from file \n");
  ```

  ```
  node alpha.js
  Hello from file
  ```

  Typically we want to write and read data that the user provides. To do this we
  need to wait on that event. So we use Node's asynchonous
  [event listeners](events.md). We wait
  on the `data` event:

  ```js
  process.stdin.on("data", (data) => {
    process.stdout.write(data.toString().trim());
  });

  process.stdout.write("\n What is your name? \n");
  process.stdout.write(` \n > `);
  ```

  This waits for whatever input is given and then echoes it.

  Currently there is no way to end this process; it will just keep echoing the
  input.

  So we add an exit clause:

  ```js
  process.stdin.on("data", (data) => {
    process.stdout.write(data.toString().trim());
    process.exit();
  });
  ```

  We can also execute functionality on the exit event:

  ```js
  process.on("exit", () => {
    // Do something
  });
  ```

  > Timings can also obviously be managed via the `setTimeout` and `setInterval`
  > methods.

  ### Additional useful methods

  ```js
  process.stdout.clearLine();
  process.stdout.cursorTo([int]);
  ```

  ### `readline`

  The core `readline` module simplifies the handling of standard input and output
  by providing a wrapper. It reads the input stream line by line. Basic usage:

  ```js
  var readline = require("readline");

  var rl = readline.createInterface(process.stdin, process.stdout);

  rl.question("What is your age? ", (age) => {
    console.log("Your age is: " + age);
  });
  ```

  Usage scenarios at: https://www.geeksforgeeks.org/node-js-readline-module/

raw_content:
  ---
  tags:
    - node-js
  ---

  # The `process` module in Node.js

  `process` is a core module and a global object accessible from anywhere in a
  Node.js application. It contains functionality that allows us to interact with
  information about the current process instance of Node.

  For example, we can use it to get environment information, read environment
  variables, parse arguments that are passed to the run command, communicate with
  the terminal and exit the current process.

  ## Managing runtime environments

  See
  [Managing Environments](Managing_environments_in_NodeJS.md).

  ## Accessing arguments: `process.argv`

  We can use `process.argv` to return an array containing the command-line
  arguments passed when a Node process is launched. This could be a whole-app
  entrypoint (i.e. `index.js`) or a single file we are running.

  For instance if we run the following file:

  ```js
  // process-demo.js
  console.log(3 + 3);
  console.log(process.argv);
  ```

  We get:

  ```bash
  6
  [
    '/Users/thomasbishop/.nvm/versions/node/v16.10.0/bin/node',
    '/Users/thomasbishop/prepos/testNode.js'
  ]
  ```

  The first item is the last executed process. The second is the array of
  arguments.

  In the array, the first value is a reference to the Node runtime binary. The
  second is the file that was passed to Node.

  If we passed in a parameter we would get that too:

  ```
  node process-demo.js --fakeFlag
  ```

  Gives us:

  ```bash
  [
    "/Users/thomasbishop/.nvm/versions/node/v16.10.0/bin/node",
    "/Users/thomasbishop/prepos/testNode.js",
    "--fake-flag",
  ]
  ```

  When writing Node CLI applications we can write functions that parse standard
  input. For example:

  ```js
  function parseStandardInput(flag) {
    let indexAfterFlag = process.argv.indexOf(flag);
    console.log(process.argv[indexAfterFlag]);
  }
  ```

  Say we ran a program that took in a username:

  ```bash
  node userName.js --user Thomas
  ```

  Then `parseStandardInput("--user")` would give us `"thomas"`

  ## Standard input and output

  Below is the most basic use case: writing to the output.

  ```js
  // alpha.js
  process.stdout.write("Hello from file \n");
  ```

  ```
  node alpha.js
  Hello from file
  ```

  Typically we want to write and read data that the user provides. To do this we
  need to wait on that event. So we use Node's asynchonous
  [event listeners](events.md). We wait
  on the `data` event:

  ```js
  process.stdin.on("data", (data) => {
    process.stdout.write(data.toString().trim());
  });

  process.stdout.write("\n What is your name? \n");
  process.stdout.write(` \n > `);
  ```

  This waits for whatever input is given and then echoes it.

  Currently there is no way to end this process; it will just keep echoing the
  input.

  So we add an exit clause:

  ```js
  process.stdin.on("data", (data) => {
    process.stdout.write(data.toString().trim());
    process.exit();
  });
  ```

  We can also execute functionality on the exit event:

  ```js
  process.on("exit", () => {
    // Do something
  });
  ```

  > Timings can also obviously be managed via the `setTimeout` and `setInterval`
  > methods.

  ### Additional useful methods

  ```js
  process.stdout.clearLine();
  process.stdout.cursorTo([int]);
  ```

  ### `readline`

  The core `readline` module simplifies the handling of standard input and output
  by providing a wrapper. It reads the input stream line by line. Basic usage:

  ```js
  var readline = require("readline");

  var rl = readline.createInterface(process.stdin, process.stdout);

  rl.question("What is your age? ", (age) => {
    console.log("Your age is: " + age);
  });
  ```

  Usage scenarios at: https://www.geeksforgeeks.org/node-js-readline-module/


path: zk/Prop_types_in_React.md
sortable_path: zkProp_types_in_React.md
title: Prop types
checksum: 727c77a483cc8cd4beceb26f9145e1f40aef386f77b3ac6c2f4b43d874e30039
created: 2024-06-16 17:37:31.788664835+00:00
modified: 2024-03-27 10:45:52.506858751+00:00
metadata: {"tags":["javascript","react","data-types"]}
lead:
  **The `prop-types` package allows us to introduce type-checking during the
  development runtime of a React application. With larger applications or those
  with complex data flows, this can help reduce errors and bugs during
  development. This is a bit like using TypeScript but on a more minimal level.**

body:
  **The `prop-types` package allows us to introduce type-checking during the
  development runtime of a React application. With larger applications or those
  with complex data flows, this can help reduce errors and bugs during
  development. This is a bit like using TypeScript but on a more minimal level.**

  ## Install

  ```
  npm install prop-types
  ```

  ## Usage

  ```jsx
  import PropTypes from "prop-types";
  ```

  ## Examples

  Say we have a component with the following props:

  ```jsx
  function Page(props) {
    const classes = useStyles();
    return (
      <React.Fragment>
        <Typography className={classes.heading} variant="h1">
          {props.h1}
        </Typography>
        {props.h2 !== "" && <Typography variant="h2">{props.h2}</Typography>}
        {props.paras.map((paragraph, index) => (
          <Typography
            className={classes.paragraph}
            key={index}
            variant="body1"
            gutterBottom
          >
            {paragraph}
          </Typography>
        ))}
        {props.children}
        <Button
          className={classes.button}
          variant="contained"
          color="primary"
          disableElevation
          component={Link}
          to={props.buttonLink}
        >
          {props.buttonText}
        </Button>
      </React.Fragment>
    );
  }
  ```

  Before the final `export default` statement, we would add a PropTypes object
  that specifies the data or reference type that is required by each prop cited in
  the component:

  ```jsx
  Page.propTypes = {
    h1: PropTypes.string.isRequired, // should be string data type, must be present
    h2: PropTypes.string, // as above but optional
    paras: PropTypes.array, // should be array reference type
    buttonLink: PropTypes.string,
    buttonText: PropTypes.string,
    children: PropTypes.node, // can be anything (element, type, JSX) that is rendered to the screen
  };
  ```

  If one of these type checks failed you get a very semantic Warning in the
  console specifying which prop is not consistent with your prop type declaration.

  ## Additional checks

  Above are the most frequent and basic checks, but there are many other
  conditions you can check for:

  ```jsx
  // The full list of types
  [propName]: PropTypes.array,
  [propName]: PropTypes.bool,
  [propName]: PropTypes.func,
  [propName]: PropTypes.number,
  [propName]: PropTypes.object,
  [propName]: PropTypes.string,
  [propName]: PropTypes.symbol,

  // Anything that can be rendered: numbers, strings, elements or an arrayor fragment) containing these types.
  [propName]: PropTypes.node,

  // A function

  [propName]: PropTypes.func

  // An object that could be one of many types
  [objectProp]: PropTypes.oneOfType([
      PropTypes.string,
      PropTypes.number,
    ]),

  // An array of a certain type
  [arrayProp]: PropTypes.arrayOf(PropTypes.number),

  // An object with property values of a certain type
  [objectProp]: PropTypes.objectOf(PropTypes.number),
  ```

raw_content:
  ---
  tags:
    - javascript
    - react
    - data-types
  ---

  # Prop types

  **The `prop-types` package allows us to introduce type-checking during the
  development runtime of a React application. With larger applications or those
  with complex data flows, this can help reduce errors and bugs during
  development. This is a bit like using TypeScript but on a more minimal level.**

  ## Install

  ```
  npm install prop-types
  ```

  ## Usage

  ```jsx
  import PropTypes from "prop-types";
  ```

  ## Examples

  Say we have a component with the following props:

  ```jsx
  function Page(props) {
    const classes = useStyles();
    return (
      <React.Fragment>
        <Typography className={classes.heading} variant="h1">
          {props.h1}
        </Typography>
        {props.h2 !== "" && <Typography variant="h2">{props.h2}</Typography>}
        {props.paras.map((paragraph, index) => (
          <Typography
            className={classes.paragraph}
            key={index}
            variant="body1"
            gutterBottom
          >
            {paragraph}
          </Typography>
        ))}
        {props.children}
        <Button
          className={classes.button}
          variant="contained"
          color="primary"
          disableElevation
          component={Link}
          to={props.buttonLink}
        >
          {props.buttonText}
        </Button>
      </React.Fragment>
    );
  }
  ```

  Before the final `export default` statement, we would add a PropTypes object
  that specifies the data or reference type that is required by each prop cited in
  the component:

  ```jsx
  Page.propTypes = {
    h1: PropTypes.string.isRequired, // should be string data type, must be present
    h2: PropTypes.string, // as above but optional
    paras: PropTypes.array, // should be array reference type
    buttonLink: PropTypes.string,
    buttonText: PropTypes.string,
    children: PropTypes.node, // can be anything (element, type, JSX) that is rendered to the screen
  };
  ```

  If one of these type checks failed you get a very semantic Warning in the
  console specifying which prop is not consistent with your prop type declaration.

  ## Additional checks

  Above are the most frequent and basic checks, but there are many other
  conditions you can check for:

  ```jsx
  // The full list of types
  [propName]: PropTypes.array,
  [propName]: PropTypes.bool,
  [propName]: PropTypes.func,
  [propName]: PropTypes.number,
  [propName]: PropTypes.object,
  [propName]: PropTypes.string,
  [propName]: PropTypes.symbol,

  // Anything that can be rendered: numbers, strings, elements or an arrayor fragment) containing these types.
  [propName]: PropTypes.node,

  // A function

  [propName]: PropTypes.func

  // An object that could be one of many types
  [objectProp]: PropTypes.oneOfType([
      PropTypes.string,
      PropTypes.number,
    ]),

  // An array of a certain type
  [arrayProp]: PropTypes.arrayOf(PropTypes.number),

  // An object with property values of a certain type
  [objectProp]: PropTypes.objectOf(PropTypes.number),
  ```


path: zk/Props_in_React.md
sortable_path: zkProps_in_React.md
title: Props
lead: ## Types or interfaces?
checksum: 5932443b8d7abf3608aa338b3410754fc1976a0a2fc49a45a3a865dba90389b0
created: 2024-06-16 17:37:31.795292542+00:00
modified: 2024-03-27 10:45:52.506858751+00:00
metadata: {"tags":["typescript","react"]}
body:
  ## Types or interfaces?

  They are mostly interchangeable but there are some specific differences

  ### Interfaces

  - Classes and other interfaces can extend an interface but not a type

    ```ts
    interface Animal {
      name: string;
    }

    interface Bear extends Animal {
      honey: boolean;
    }
    ```

  - You can add properties to an interface without generating a double declaration
    error:

    ```ts
    interface Window {
        }

    interface Window {
      ts: TypeScriptAPI;
    }
    ```

  ### Types

  You can create unions with types but not interfaces.

  > The consensus seems to be that interfaces should be used over types unless
  > there are ocassions when you do not want a type to be extendable /
  > redeclarable. Or when you want to use unions.

  ## How we type props

  The custom is to type props as an interface. This way we can easily type
  function prop types.

  ```tsx
  interface IProps {
    people: {
      name: string;
      age: number;
      note?: string;
    }[];
  }

  const List: React.FC<IProps> = ({people}: IProps) => {
      return()
  }

  // Note we say that the props into the func component are of type IProps
  // And we destructure the people key

  ```

  Then in the parent:

  ```tsx

  const [people, setPeople] = useState<IState['people']>({});

  <List props={people}>

  ```

  ## Common types for props

  ### Object with any number of properties

  ```tsx
  interface IProps {
    obj: {};
  }
  ```

  ### Array of objects

  ```tsx
  interface IProps {
    val1: string;
    val2: boolean;
  }
  [];
  ```

  ### Functions

  ```tsx

  // Function that doesn't receive or return anything
  interface IProps {
      onClick: () => void;
  }[]

  // Function with named parameter
  interface IProps {
      onClick: (id: number) => void;
  }[]

  // Function that takes an event
  onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
  ```

  ### Other React components

  ```js
  interface IProps {
    children: React.ReactNode;
  }

  interface IProps {
    children: JSX.Element;
  }
  ```

  `React.ReactNode` covers everything that React can render. This should be
  definitely used when the prop is a child component, otherwise `JSX.element` is
  ok.

  <p style="color: red;">Should I use type or interface? What is consensus?</p>

raw_content:
  ---
  tags:
    - typescript
    - react
  ---

  # Props

  ## Types or interfaces?

  They are mostly interchangeable but there are some specific differences

  ### Interfaces

  - Classes and other interfaces can extend an interface but not a type

    ```ts
    interface Animal {
      name: string;
    }

    interface Bear extends Animal {
      honey: boolean;
    }
    ```

  - You can add properties to an interface without generating a double declaration
    error:

    ```ts
    interface Window {
        }

    interface Window {
      ts: TypeScriptAPI;
    }
    ```

  ### Types

  You can create unions with types but not interfaces.

  > The consensus seems to be that interfaces should be used over types unless
  > there are ocassions when you do not want a type to be extendable /
  > redeclarable. Or when you want to use unions.

  ## How we type props

  The custom is to type props as an interface. This way we can easily type
  function prop types.

  ```tsx
  interface IProps {
    people: {
      name: string;
      age: number;
      note?: string;
    }[];
  }

  const List: React.FC<IProps> = ({people}: IProps) => {
      return()
  }

  // Note we say that the props into the func component are of type IProps
  // And we destructure the people key

  ```

  Then in the parent:

  ```tsx

  const [people, setPeople] = useState<IState['people']>({});

  <List props={people}>

  ```

  ## Common types for props

  ### Object with any number of properties

  ```tsx
  interface IProps {
    obj: {};
  }
  ```

  ### Array of objects

  ```tsx
  interface IProps {
    val1: string;
    val2: boolean;
  }
  [];
  ```

  ### Functions

  ```tsx

  // Function that doesn't receive or return anything
  interface IProps {
      onClick: () => void;
  }[]

  // Function with named parameter
  interface IProps {
      onClick: (id: number) => void;
  }[]

  // Function that takes an event
  onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
  ```

  ### Other React components

  ```js
  interface IProps {
    children: React.ReactNode;
  }

  interface IProps {
    children: JSX.Element;
  }
  ```

  `React.ReactNode` covers everything that React can render. This should be
  definitely used when the prop is a child component, otherwise `JSX.element` is
  ok.

  <p style="color: red;">Should I use type or interface? What is consensus?</p>


path: zk/Read_command__in_Bash.md
sortable_path: zkRead_command__in_Bash.md
title: read
checksum: c9fb9f3512d6c4406ed8ab423f11a31c5c9e23de462b89c7dd18af357cccc1d0
created: 2024-06-16 17:37:31.802939842+00:00
modified: 2024-06-16 17:24:02.465309515+00:00
metadata: {"tags":["shell"]}
lead:
  The primary use of `read` is to capture user input from `stdin`. It can also be
  used to parse strings or files that are redirected to it (with `<` and `<<`) or
  piped to it. In each case, what is read is stored as a variable.

body:
  The primary use of `read` is to capture user input from `stdin`. It can also be
  used to parse strings or files that are redirected to it (with `<` and `<<`) or
  piped to it. In each case, what is read is stored as a variable.

  `read` will parse line by line using a space (`\n`) as the default delimiter.
  You can use IFS to parse by other characters and/or
  [split the contents into an array](Split_into_array_in_Bash.md).

  ## Example of capturing user input

  When we use `read` to gather user input, the script will pause until the input
  is provided.

  ```bash
  echo "What is your name?"
  read name

  echo "What is your password?"
  read -s pass

  read

  ```

  > If you don't specify variables, `read` will automatically parse using
  > whitespace

  ## Example of piping to read

  Here we use [find](Find_Bash_command.md) to collate the files in
  the current directory and then pipe them to read.

  ```bash
  find -type -f  -not -path "./.git/" | read $fname
  ```

  ## Example of parsing a file

  We will typically read from a source and then do something with each variable
  that `read` returns, e.g:

  ```bash
  while read line; do
    if [ var == 'something' ]; then
      # do something
  done < './input-file.txt
  ```

  ## $REPLY

  If you do not assign a variable name to store the value that `read` reads a
  default (`$REPLY`) is applied. You can reference this value in your code.

  For example the following loop does something if `$REPLY` is equal to an empty
  string:

  ```bash
  while read;
  do
      ((count++))
      if [[ -z "$REPLY" ]]; then
          echo "$count"
      fi
  done < "$input
  ```

raw_content:
  ---
  tags:
    - shell
  ---

  # read

  The primary use of `read` is to capture user input from `stdin`. It can also be
  used to parse strings or files that are redirected to it (with `<` and `<<`) or
  piped to it. In each case, what is read is stored as a variable.

  `read` will parse line by line using a space (`\n`) as the default delimiter.
  You can use IFS to parse by other characters and/or
  [split the contents into an array](Split_into_array_in_Bash.md).

  ## Example of capturing user input

  When we use `read` to gather user input, the script will pause until the input
  is provided.

  ```bash
  echo "What is your name?"
  read name

  echo "What is your password?"
  read -s pass

  read

  ```

  > If you don't specify variables, `read` will automatically parse using
  > whitespace

  ## Example of piping to read

  Here we use [find](Find_Bash_command.md) to collate the files in
  the current directory and then pipe them to read.

  ```bash
  find -type -f  -not -path "./.git/" | read $fname
  ```

  ## Example of parsing a file

  We will typically read from a source and then do something with each variable
  that `read` returns, e.g:

  ```bash
  while read line; do
    if [ var == 'something' ]; then
      # do something
  done < './input-file.txt
  ```

  ## $REPLY

  If you do not assign a variable name to store the value that `read` reads a
  default (`$REPLY`) is applied. You can reference this value in your code.

  For example the following loop does something if `$REPLY` is equal to an empty
  string:

  ```bash
  while read;
  do
      ((count++))
      if [[ -z "$REPLY" ]]; then
          echo "$count"
      fi
  done < "$input
  ```


path: zk/Redirection_in_Bash.md
sortable_path: zkRedirection_in_Bash.md
title: Redirection
lead: ## Redirecting outputs
checksum: e64c3fd247bb692dbe02ecb5f5d645298857b8d8675be4a8a9e3532475b2fc00
created: 2024-06-16 17:37:31.825481372+00:00
modified: 2024-03-27 10:45:52.506858751+00:00
metadata: {"tags":["shell"]}
body:
  ## Redirecting outputs

  The symbol `>` is called the **redirection operator** because it redirects
  `stdout` to another program or file. You most frequently use this when you want
  to save contents to a file rather than standard output.

  ```bash
  ls | grep d* > result.txt
  ```

  ### Combining redirection with file escriptors

  It is common practice to combine redirection with the
  [file descriptors](File_descriptors.md) to redirect
  the output of `stdout` and `stderr`. A common case is to
  [redirect error output to `/dev/null`](Redirect_to_dev_null.md).

  Redirection defaults to interpreting `>` as the redirection of `stdout` (`1`);

  ## Redirecting inputs

  We can also switch the direction of the redirection symbol and pass in a file to
  a command rather than command ouput to a file:

  ```bash
  sql-processing-program < data.sql
  ```

  We can redirect a string with three carets:

  ```bash
  program <<< "this is a string input"
  ```

  ## Appending

  We use `>>` to append contents on the next available line of a pre-existing
  file. Continuing on from the example above:

  ```bash
  echo 'These are the files I just grepped' >> result.txt
  ```

raw_content:
  ---
  tags:
    - shell
  ---

  # Redirection

  ## Redirecting outputs

  The symbol `>` is called the **redirection operator** because it redirects
  `stdout` to another program or file. You most frequently use this when you want
  to save contents to a file rather than standard output.

  ```bash
  ls | grep d* > result.txt
  ```

  ### Combining redirection with file escriptors

  It is common practice to combine redirection with the
  [file descriptors](File_descriptors.md) to redirect
  the output of `stdout` and `stderr`. A common case is to
  [redirect error output to `/dev/null`](Redirect_to_dev_null.md).

  Redirection defaults to interpreting `>` as the redirection of `stdout` (`1`);

  ## Redirecting inputs

  We can also switch the direction of the redirection symbol and pass in a file to
  a command rather than command ouput to a file:

  ```bash
  sql-processing-program < data.sql
  ```

  We can redirect a string with three carets:

  ```bash
  program <<< "this is a string input"
  ```

  ## Appending

  We use `>>` to append contents on the next available line of a pre-existing
  file. Continuing on from the example above:

  ```bash
  echo 'These are the files I just grepped' >> result.txt
  ```


path: zk/Restructure_URLs_lambda.md
sortable_path: zkRestructure_URLs_lambda.md
title: AWS Lambda examples
lead: ## Reconstruct CloudFront URLs
checksum: 6a911ce9d3aa21da4b42240dc00369ab6f54b0e35dca6f1cd3d11e804463b857
created: 2024-06-16 17:37:31.847347532+00:00
modified: 2024-06-15 09:50:42.956894178+00:00
metadata: {"tags":["AWS","aws-lambda"]}
body:
  ## Reconstruct CloudFront URLs

  ```js
  exports.handler = (event, context, callback) => {
    // Extract the request from the CloudFront event that is sent to Lambda@Edge
    var request = event.Records[0].cf.request;

    // Extract the URI from the request
    var olduri = request.uri;

    // Match any '/' that occurs at the end of a URI. Replace it with a default index
    var newuri = olduri.replace(/\/$/, "/index.html");

    // Replace the received URI with the URI that includes the index page
    request.uri = newuri;

    // Return to CloudFront
    return callback(null, request);
  };
  ```

  Let's walk through the above example making reference to the general structure
  of the
  [AWS Lambda handler function](Lambda_handler_function.md):

  1. The `event` parameter is invoked to gain access to the event that triggered
     the function. This is a CloudFront request event which is targetted with
     `event.Records[0].cf.request`
  2. We classify this request as the `olduri` since it doesn't have the form we
     want.
  3. We mutate the original request by replacing `/` with `/index.html`
  4. We then re-assign the `request.uri` value to the value of the new URI.
  5. Finally we invoke the `callback` parameter to signal the completion of the
     transformation and return the new request as the return value.

raw_content:
  ---
  tags:
    - AWS
    - aws-lambda
  ---

  # AWS Lambda examples

  ## Reconstruct CloudFront URLs

  ```js
  exports.handler = (event, context, callback) => {
    // Extract the request from the CloudFront event that is sent to Lambda@Edge
    var request = event.Records[0].cf.request;

    // Extract the URI from the request
    var olduri = request.uri;

    // Match any '/' that occurs at the end of a URI. Replace it with a default index
    var newuri = olduri.replace(/\/$/, "/index.html");

    // Replace the received URI with the URI that includes the index page
    request.uri = newuri;

    // Return to CloudFront
    return callback(null, request);
  };
  ```

  Let's walk through the above example making reference to the general structure
  of the
  [AWS Lambda handler function](Lambda_handler_function.md):

  1. The `event` parameter is invoked to gain access to the event that triggered
     the function. This is a CloudFront request event which is targetted with
     `event.Records[0].cf.request`
  2. We classify this request as the `olduri` since it doesn't have the form we
     want.
  3. We mutate the original request by replacing `/` with `/index.html`
  4. We then re-assign the `request.uri` value to the value of the new URI.
  5. Finally we invoke the `callback` parameter to signal the completion of the
     transformation and return the new request as the return value.


path: zk/Routing_on_link_click_in_React.md
sortable_path: zkRouting_on_link_click_in_React.md
title: Test: Routing on link click
lead: ## Component
checksum: 0935aa4e5e1e4051e4ca684aa0735d3b0fb3a555a93412746712f20724dee40b
created: 2024-06-16 17:37:31.858850096+00:00
modified: 2024-03-27 10:45:52.506858751+00:00
metadata: {"tags":["javascript","react","testing"]}
body:
  ## Component

  ```jsx
  const CertificateHtmlLink = () => {
    return (
      <div className="certificate-html-link html-version-message">
        <Link className="btn btn-primary ml-2" to="/some-location">
          View HTML version
        </Link>
      </div>
    );
  };
  ```

  ## Test

  ```js
  import { render, fireEvent } from "@testing-library/react";
  import { Router } from "react-router-dom";

  describe("<CertificateHtmlLink", () => {
    it("should link to dynamic HTML certificate page URL on click event", () => {
      // Arrange:
      const history = createMemoryHistory({ initialEntries: ["/"] });

      // Act:
      const { getByText } = render(
        <Router history={history}>
          <CertificateHtmlLink to="/certificate/123" />
        </Router>
      );

      // Assert:
      expect(history.location.pathname).toBe("/");
      fireEvent.click(getByText("View HTML version"));
      expect(history.location.pathname).toBe("/certificate/123");
    });
  });
  ```

raw_content:
  ---
  tags:
    - javascript
    - react
    - testing
  ---

  # Test: Routing on link click

  ## Component

  ```jsx
  const CertificateHtmlLink = () => {
    return (
      <div className="certificate-html-link html-version-message">
        <Link className="btn btn-primary ml-2" to="/some-location">
          View HTML version
        </Link>
      </div>
    );
  };
  ```

  ## Test

  ```js
  import { render, fireEvent } from "@testing-library/react";
  import { Router } from "react-router-dom";

  describe("<CertificateHtmlLink", () => {
    it("should link to dynamic HTML certificate page URL on click event", () => {
      // Arrange:
      const history = createMemoryHistory({ initialEntries: ["/"] });

      // Act:
      const { getByText } = render(
        <Router history={history}>
          <CertificateHtmlLink to="/certificate/123" />
        </Router>
      );

      // Assert:
      expect(history.location.pathname).toBe("/");
      fireEvent.click(getByText("View HTML version"));
      expect(history.location.pathname).toBe("/certificate/123");
    });
  });
  ```


path: zk/Schema_Definition_Language_in_GraphQL.md
sortable_path: zkSchema_Definition_Language_in_GraphQL.md
title: Schema Definition Language
lead: SDL is the formal name for the syntax of GraphQL schemas.
checksum: c50d5b10c7f9a915e1d4d5d9bb67ef337b59f126f97bfda5c6bfeba74d25ac1c
created: 2024-06-16 17:37:31.863579167+00:00
modified: 2024-03-27 10:45:52.506858751+00:00
metadata: {"tags":["graphql"]}
body:
  SDL is the formal name for the syntax of GraphQL schemas.

  ## Types

  A schema is a collection of object types that contain fields. Each field has a
  type of its own. A field's type can be a primitive/scalar value (such as an
  `Int` or a `String`), or it can be another object type (just like a custom type
  in TS).

  A schema's type can be non-nullable which is to say, a required field. We
  indicate this with `!`.

  A type for a field can be a collection/array of a given type.

  The following example indicates these properties:

  ```gql
  type Person {
    age: Int
    name: String
    pets: [Pet]!
  }

  type Pet {
    species: String
    name: String
    age: Int
  }
  ```

  ## Queries

  A query is also a schema type but of a special sort.

  > The fields of this type are entry points into the rest of the schema. These
  > are the top-level fields that the client can query for.

  For example if we had this type:

  ```graphql
  type Track {
    id: ID!
      author: Author!
    thumbnail: String
    length: Int
    modulesCount: Int
  }
  ```

  We could define a type to access a give `Track` as follows:

  ```graphql
  type Query {
    tracksForHomePage: [Track!]!
  }
  ```

  Then use this type as the basis for a query:

  ```

  ```

  ## Descriptions

  Descriptions are comments that allow you to document your Schema

  Single line:

  ```gql
  "Single line comment"
  ```

  ```gql
  """
  Multi
  line
  comment
  """
  ```

raw_content:
  ---
  tags: [graphql]
  ---

  # Schema Definition Language

  SDL is the formal name for the syntax of GraphQL schemas.

  ## Types

  A schema is a collection of object types that contain fields. Each field has a
  type of its own. A field's type can be a primitive/scalar value (such as an
  `Int` or a `String`), or it can be another object type (just like a custom type
  in TS).

  A schema's type can be non-nullable which is to say, a required field. We
  indicate this with `!`.

  A type for a field can be a collection/array of a given type.

  The following example indicates these properties:

  ```gql
  type Person {
    age: Int
    name: String
    pets: [Pet]!
  }

  type Pet {
    species: String
    name: String
    age: Int
  }
  ```

  ## Queries

  A query is also a schema type but of a special sort.

  > The fields of this type are entry points into the rest of the schema. These
  > are the top-level fields that the client can query for.

  For example if we had this type:

  ```graphql
  type Track {
    id: ID!
      author: Author!
    thumbnail: String
    length: Int
    modulesCount: Int
  }
  ```

  We could define a type to access a give `Track` as follows:

  ```graphql
  type Query {
    tracksForHomePage: [Track!]!
  }
  ```

  Then use this type as the basis for a query:

  ```

  ```

  ## Descriptions

  Descriptions are comments that allow you to document your Schema

  Single line:

  ```gql
  "Single line comment"
  ```

  ```gql
  """
  Multi
  line
  comment
  """
  ```


path: zk/Secrets_or_env_vars_in_AWS.md
sortable_path: zkSecrets_or_env_vars_in_AWS.md
title: Secrets or environment variables?
checksum: 5dbb25aea37698bb6cf861e39dfd15ee9823b0e0e928f76e9d1d4e3899538a9b
created: 2024-06-16 17:37:31.867266988+00:00
modified: 2024-03-27 10:45:52.506858751+00:00
metadata: {"tags":["AWS","aws-lambda"]}
lead:
  Choosing between environment variables and AWS Secrets Manager hinges on factors
  such as use case, security needs, and the data type. Environment variables are
  easier to use, free, and offer fast access but are less secure and lack features
  like versioning. On the other hand, AWS Secrets Manager provides robust security
  through encryption, access control, audit trails, and supports secret versioning
  and rotation. However, it comes with additional costs and can introduce latency
  and rate limits.

body:
  Choosing between environment variables and AWS Secrets Manager hinges on factors
  such as use case, security needs, and the data type. Environment variables are
  easier to use, free, and offer fast access but are less secure and lack features
  like versioning. On the other hand, AWS Secrets Manager provides robust security
  through encryption, access control, audit trails, and supports secret versioning
  and rotation. However, it comes with additional costs and can introduce latency
  and rate limits.

  General recommendations suggest using AWS Secrets Manager for storing sensitive
  data like API keys and passwords, due to its enhanced security features. For
  less sensitive, non-critical data such as feature flags or environment-specific
  URLs, environment variables are often adequate. Cost-conscious users who don't
  need advanced features may find environment variables more economical.
  Ultimately, the best choice depends on your specific requirements and
  limitations.

raw_content:
  ---
  tags: [AWS, aws-lambda]
  ---

  # Secrets or environment variables?

  Choosing between environment variables and AWS Secrets Manager hinges on factors
  such as use case, security needs, and the data type. Environment variables are
  easier to use, free, and offer fast access but are less secure and lack features
  like versioning. On the other hand, AWS Secrets Manager provides robust security
  through encryption, access control, audit trails, and supports secret versioning
  and rotation. However, it comes with additional costs and can introduce latency
  and rate limits.

  General recommendations suggest using AWS Secrets Manager for storing sensitive
  data like API keys and passwords, due to its enhanced security features. For
  less sensitive, non-critical data such as feature flags or environment-specific
  URLs, environment variables are often adequate. Cost-conscious users who don't
  need advanced features may find environment variables more economical.
  Ultimately, the best choice depends on your specific requirements and
  limitations.


path: zk/Setting_up_and_configuring_TypeScript.md
sortable_path: zkSetting_up_and_configuring_TypeScript.md
title: Setup and configuration
lead: ## Installation and configuration
checksum: 7ad962fc516dcea03815580140ae449dfaeb4c74b9e330cc4b8199af5454edf1
created: 2024-06-16 17:37:31.871578494+00:00
modified: 2024-03-27 10:45:52.506858751+00:00
metadata: {"tags":["typescript"]}
body:
  ## Installation and configuration

  TypeScript offers custom installations for most modern JS-based frameworks
  including Webpack, React.js and Vue.js. The instructions below cover minimal TS
  set-up outside of a specific framework. TypeScript adds an additional step to
  any build process since your code must compile to JS before any bundling and
  transpilation can occur.

  ## Installation

  ```
  mkdir typescript-project
  cd typescript-project
  npm i typescript --save-dev
  ```

  ## Initialise project

  ```
  npx tsc --init
  ```

  ## Basic configuration

  ```json
  "compilerOptions": {
  	"target" : "es2020", //es2015 for prod
  	"module" : "es2020",
    	"allowJs": true,
    	"checkJs": true,
    	"strict": true,
    	"esModuleInterop": true
  }
  ```

  ### Specify output paths (for production code)

  ```json
  "compilerOptions": {
  	...
  	"outDir": "dist",
  	"sourceMap": true,
  }
  ```

  ### Compile-time commands

  ```
  tsc --noEmit
  ```

  ```
  tsc --noEmit --watch
  ```

  ## Global requirements

  ```
  npm install -g typescript
  npm install -g ts-node
  ```

  `ts-node` allows you to run TS files the way you would with standard JS, i.e.
  `node [filename]`, you just use `ts-node filename` .

  This is a convenience that saves you compiling from TS → JS and then running
  Node against the compiled JS. Which is useful for debugging and checking values
  as you work.

  ## Imports and exports

  You may wish to define your custom types outside of their application, for
  instance in a `/types/` directory. The custom type or types can then be imported
  using standard ES6 imports:

  ```tsx
  export type Article = {
  		price: number,
  }

  export type AnotherType = {
  ...
  }
  ```

  ```tsx
  import { Article, AnotherType } from "./types/allTypes.js";
  import Article from "./types/allTypes.js";
  ```

  TypeScript also provides a specific import keyword `type` so that you can
  distinguish type imports from other module imports. This is handy when you have
  multiple components in the one file:

  ```tsx
  import type { Article } from "./types/allTypes.js";
  ```

raw_content:
  ---
  tags:
    - typescript
  ---

  # Setup and configuration

  ## Installation and configuration

  TypeScript offers custom installations for most modern JS-based frameworks
  including Webpack, React.js and Vue.js. The instructions below cover minimal TS
  set-up outside of a specific framework. TypeScript adds an additional step to
  any build process since your code must compile to JS before any bundling and
  transpilation can occur.

  ## Installation

  ```
  mkdir typescript-project
  cd typescript-project
  npm i typescript --save-dev
  ```

  ## Initialise project

  ```
  npx tsc --init
  ```

  ## Basic configuration

  ```json
  "compilerOptions": {
  	"target" : "es2020", //es2015 for prod
  	"module" : "es2020",
    	"allowJs": true,
    	"checkJs": true,
    	"strict": true,
    	"esModuleInterop": true
  }
  ```

  ### Specify output paths (for production code)

  ```json
  "compilerOptions": {
  	...
  	"outDir": "dist",
  	"sourceMap": true,
  }
  ```

  ### Compile-time commands

  ```
  tsc --noEmit
  ```

  ```
  tsc --noEmit --watch
  ```

  ## Global requirements

  ```
  npm install -g typescript
  npm install -g ts-node
  ```

  `ts-node` allows you to run TS files the way you would with standard JS, i.e.
  `node [filename]`, you just use `ts-node filename` .

  This is a convenience that saves you compiling from TS → JS and then running
  Node against the compiled JS. Which is useful for debugging and checking values
  as you work.

  ## Imports and exports

  You may wish to define your custom types outside of their application, for
  instance in a `/types/` directory. The custom type or types can then be imported
  using standard ES6 imports:

  ```tsx
  export type Article = {
  		price: number,
  }

  export type AnotherType = {
  ...
  }
  ```

  ```tsx
  import { Article, AnotherType } from "./types/allTypes.js";
  import Article from "./types/allTypes.js";
  ```

  TypeScript also provides a specific import keyword `type` so that you can
  distinguish type imports from other module imports. This is handy when you have
  multiple components in the one file:

  ```tsx
  import type { Article } from "./types/allTypes.js";
  ```


path: zk/Split_into_array_in_Bash.md
sortable_path: zkSplit_into_array_in_Bash.md
title: Splitting input into an array
lead: ## readarray
checksum: b613cfe6a16f00e820880c671aeeccbf3f0ecdae9e3770fc68016d7b50c6b413
created: 2024-06-16 17:37:31.906852767+00:00
modified: 2024-03-27 10:45:52.506858751+00:00
metadata: {"tags":["shell"]}
body:
  ## readarray

  `readarray` makes it really easy to split input into an array based on new
  lines. Say we have this file as input:

  ```
  123
  456
  789
  ```

  Then we can split like so:

  ```bash
  readarray -t name_for_array < ./input.text

  # Print all elements
  echo "${name_for_array[@]}"

  # Print element by index

  echo "${name_for_array[1]}"
  456
  ```

  If we want to read a string directly:

  ```bash
  readarray -t new_name_for_array <<< "here
  is
  some
  text"

  echo "${new_name_for_array[1]}"
  is
  ```

  > The _-t_ flag removes the trailing newline

  See more: https://linuxhint.com/split-string-array-bash/

  ## read

  For delimiters other than a space we have to use `read`, combined with `IFS` the
  **Internal Field Separator**.

  For example, to split by comma:

  ```plaintext
  # comma-input.txt
  something,something else,something more
  ```

  ```bash
  IFS=',' read -a arr < ./comma_inputs.txt
  ```

  > We use the `-a` flag to signal that we want each item read returned as an
  > element in an array

  ## mapfile

  We can use `mapfile` to read the lines of a input file in set segments.

  For the following file:

  ```
  line one
  line two
  line three
  line four
  ```

  We could generate the following output:

  ```
  -----SNIP-----
  line one
  line two
  -----SNIP-----
  line three
  line four
  ```

  With:

  ```bash
  while mapfile -t -n 2 ary && ((${#ary[@]})); do
    printf '%s\n' "${ary[@]}"
    printf -- '--- SNIP ---\n'
   done < $testInput
  ```

  So, while there are input lines, map each line into an array and return it in
  groups of 2.

raw_content:
  ---
  tags:
    - shell
  ---

  # Splitting input into an array

  ## readarray

  `readarray` makes it really easy to split input into an array based on new
  lines. Say we have this file as input:

  ```
  123
  456
  789
  ```

  Then we can split like so:

  ```bash
  readarray -t name_for_array < ./input.text

  # Print all elements
  echo "${name_for_array[@]}"

  # Print element by index

  echo "${name_for_array[1]}"
  456
  ```

  If we want to read a string directly:

  ```bash
  readarray -t new_name_for_array <<< "here
  is
  some
  text"

  echo "${new_name_for_array[1]}"
  is
  ```

  > The _-t_ flag removes the trailing newline

  See more: https://linuxhint.com/split-string-array-bash/

  ## read

  For delimiters other than a space we have to use `read`, combined with `IFS` the
  **Internal Field Separator**.

  For example, to split by comma:

  ```plaintext
  # comma-input.txt
  something,something else,something more
  ```

  ```bash
  IFS=',' read -a arr < ./comma_inputs.txt
  ```

  > We use the `-a` flag to signal that we want each item read returned as an
  > element in an array

  ## mapfile

  We can use `mapfile` to read the lines of a input file in set segments.

  For the following file:

  ```
  line one
  line two
  line three
  line four
  ```

  We could generate the following output:

  ```
  -----SNIP-----
  line one
  line two
  -----SNIP-----
  line three
  line four
  ```

  With:

  ```bash
  while mapfile -t -n 2 ary && ((${#ary[@]})); do
    printf '%s\n' "${ary[@]}"
    printf -- '--- SNIP ---\n'
   done < $testInput
  ```

  So, while there are input lines, map each line into an array and return it in
  groups of 2.


path: zk/Streams_in_NodeJS.md
sortable_path: zkStreams_in_NodeJS.md
title: Handling streams with fs
checksum: f8299b5e6a1242c1e024952c4e37aaa85dbc54a9b22f1a262b3658605e2ec655
created: 2024-06-16 17:37:31.912375997+00:00
modified: 2024-06-15 09:50:45.043601129+00:00
metadata: {"tags":["node-js"]}
lead:
  When reading from a file, the
  [`fs.readFile()`](fs.md) method waits
  until the entire file has been read before executing the callback. It's obvious
  why this might not be ideal in certain cases. If the file is very large you are
  utilising a lot of [memory](Memory.md) for a
  single process. Additionally, the data you need might appear early in the file,
  in which case, once you find the data you want, there is no need to read to the
  end of the file.

body:
  When reading from a file, the
  [`fs.readFile()`](fs.md) method waits
  until the entire file has been read before executing the callback. It's obvious
  why this might not be ideal in certain cases. If the file is very large you are
  utilising a lot of [memory](Memory.md) for a
  single process. Additionally, the data you need might appear early in the file,
  in which case, once you find the data you want, there is no need to read to the
  end of the file.

  > An example of this in practice is watching a Netflix film: we don't have to
  > wait for the whole film to download, we can start watching it immediately
  > because it is passed to us in chunks.

  ## Reading streams

  This is why the ability to read files and data as streams exists in Node.js.
  Streams promote memory and time efficiency. As you are not necessarily reading
  the whole file, you can extract the data you need quickly and you are not
  putting the whole file in memory.

  When read as a stream, the file is broken up into smaller chunks. Readable
  streams raise data events and pass the chunks to our callbacks. Hence we don't
  have to wait for the whole file before registering data chunks.

  ## Implementation

  Instead of, e.g :

  ```js
  fs.readFile("./lorem.md", "UTF-8", function (err, fileContents) {
    console.log(fileContents);
  });
  ```

  We would:

  ```js
  let stream = fs.createReadStream("./lorem.md", "UTF-8");

  let data;

  stream.once("data", (chunk) => {
    console.log("read stream started");
  });

  stream.on("data", (chunk) => {
    data += chunk;
    console.log(data);
  });

  stream.on("end", () => console.log("stream ends"));
  ```

  We use `once` to do something at the moment the stream starts to be read.

  We use `on` to target the `"data"` and `"end"` events. We use this to log the
  chunks via the `data` variable.

  ## Writing streams

  When we write as a stream, we break data up and pass this to a reader as a
  stream. It is what creates a stream in the first place.

  For example we could create a stream that handles `stdin` and writes this to a
  file in chunks:

  ```js
  var stream = fs.createWriteStream("lorem.txt")

  process.stdin.once("data", (data) => {
      stream.write(data, function() => {
          // data is now written.
      })
  })

  process.on("exit", function () {
      stream.close()
  })
  ```

  Note that we always have to close the stream on exit

raw_content:
  ---
  tags:
    - node-js
  ---

  # Handling streams with fs

  When reading from a file, the
  [`fs.readFile()`](fs.md) method waits
  until the entire file has been read before executing the callback. It's obvious
  why this might not be ideal in certain cases. If the file is very large you are
  utilising a lot of [memory](Memory.md) for a
  single process. Additionally, the data you need might appear early in the file,
  in which case, once you find the data you want, there is no need to read to the
  end of the file.

  > An example of this in practice is watching a Netflix film: we don't have to
  > wait for the whole film to download, we can start watching it immediately
  > because it is passed to us in chunks.

  ## Reading streams

  This is why the ability to read files and data as streams exists in Node.js.
  Streams promote memory and time efficiency. As you are not necessarily reading
  the whole file, you can extract the data you need quickly and you are not
  putting the whole file in memory.

  When read as a stream, the file is broken up into smaller chunks. Readable
  streams raise data events and pass the chunks to our callbacks. Hence we don't
  have to wait for the whole file before registering data chunks.

  ## Implementation

  Instead of, e.g :

  ```js
  fs.readFile("./lorem.md", "UTF-8", function (err, fileContents) {
    console.log(fileContents);
  });
  ```

  We would:

  ```js
  let stream = fs.createReadStream("./lorem.md", "UTF-8");

  let data;

  stream.once("data", (chunk) => {
    console.log("read stream started");
  });

  stream.on("data", (chunk) => {
    data += chunk;
    console.log(data);
  });

  stream.on("end", () => console.log("stream ends"));
  ```

  We use `once` to do something at the moment the stream starts to be read.

  We use `on` to target the `"data"` and `"end"` events. We use this to log the
  chunks via the `data` variable.

  ## Writing streams

  When we write as a stream, we break data up and pass this to a reader as a
  stream. It is what creates a stream in the first place.

  For example we could create a stream that handles `stdin` and writes this to a
  file in chunks:

  ```js
  var stream = fs.createWriteStream("lorem.txt")

  process.stdin.once("data", (data) => {
      stream.write(data, function() => {
          // data is now written.
      })
  })

  process.on("exit", function () {
      stream.close()
  })
  ```

  Note that we always have to close the stream on exit


path: zk/Strings_in_Bash.md
sortable_path: zkStrings_in_Bash.md
title: Strings in bash
lead: ## Return a substring by index
checksum: 2530f2db53c8899fd0d79f4d754052143e4479eb4e64620e2cc4cc233aca8321
created: 2024-06-16 17:37:31.925959714+00:00
modified: 2024-03-27 10:45:52.506858751+00:00
metadata: {"tags":["shell","data-types"]}
body:
  ## Return a substring by index

  ```bash
  myString="hello"
  substring=${myString:0:3}
  # hel
  ```

  This is often used when looping through each character in a string.

  ## Loop through each character in a string

  ```bash
  str="hallelujah"
  stringLength=$(expr length str)

  for (( i=0; i<=${stringLength}; i++ )); do
      echo "${str:$i:1}"
  done
  ```

raw_content:
  ---
  tags:
    - shell
    - data-types
  ---

  # Strings in bash

  ## Return a substring by index

  ```bash
  myString="hello"
  substring=${myString:0:3}
  # hel
  ```

  This is often used when looping through each character in a string.

  ## Loop through each character in a string

  ```bash
  str="hallelujah"
  stringLength=$(expr length str)

  for (( i=0; i<=${stringLength}; i++ )); do
      echo "${str:$i:1}"
  done
  ```


path: zk/Text_manipulation_in_Bash.md
sortable_path: zkText_manipulation_in_Bash.md
title: Text manipulation
lead: ## Sorting strings: `sort`
checksum: 16bd858534a5e8bb07228d40c6a8984bad8a4b74cf7a8c1b32bae9ae2ba8dfe1
created: 2024-06-16 17:37:31.952865941+00:00
modified: 2024-03-27 10:45:52.506858751+00:00
metadata: {"tags":["shell"]}
body:
  ## Sorting strings: `sort`

  If you have a `.txt` file containing text strings, each on a new line you can
  use the sort function to quickly put them in alphabetical order:

  ```bash
  sort file.txt
  ```

  Note that this will not save the sort, it only presents it as a standard output.
  To save the sort you need to direct the sort to a file in the standard way:

  ```bash
  sort file.txt > output.txt
  ```

  ### Options

  - `-r`
    - reverse sort
  - `c`
    - check if file is already sorted. If not, it will highlight the strings which
      are not sorted

  ## Find and replace: `sed`

  The `sed` programme can be used to implement find and replace procedures. In
  `sed`, find and replace are covered by the substitution option: `/s` :

  ```bash
  sed ‘s/word/replacement word/’ file.txt
  ```

  This however will only change the first instance of word to be replaced, in
  order to apply to every instance you need to add the global option: `-g` .

  As sed is a stream editor, any changes you make using it, will only occur within
  the standard output , they will not be saved to file. In order to save to file
  you need to specify a new file output (using `> output.txt`) in addition to the
  original file. This hasthe benefit of leaving the original file untouched whilst
  ensuring the desired outcome is stored permanently.

  Alternatively, you can use the `-i` option which will make the changes take
  place in the source file as well as in standard input.

  Note that this will overwrite the original version of the file and it cannot be
  regained. If this is an issue then it is recommended to include a backup command
  in the overall argument like so:

  ```bash
  sed -i.bak ‘s/word/replacement word/’ file.txt
  ```

  This will create the file `file.txt.bak` in the directory you are working within
  which is the original file before the replacement was carried out.

  ### Remove duplicates

  We can use the `sort -u` command can be used to remove duplicates:

  ```bash
  sort -u file.txt
  ```

  It is important to sort before attempting to remove duplicates since the `-u`
  flag works on the basis of the strings being adjacent.

  ## Split a large file into multiple smaller files: `split`

  Suppose you have a file containing 1000 lines. You want to break the file up
  into five separate files, each containing two hundred lines. You can use `split`
  to accomplish this, like so:

  ```bash
  split -l 200 big-file.txt new-files
  ```

  `split` will categorise the resulting five files as follows:

  - new-file-aa,
  - new-file-ab
  - new-file-ac,
  - newfile-ad,
  - new-file-ae.

  If you would rather have numeric suffixes, use the option `-d` . You can also
  split a file by its number of bytes, using the option `-b` and specifying a
  constituent file size.

  ## Merge multiple files into one with `cat`

  We can use `cat` read multiple files at once and then append a redirect to save
  them to a file:

  ```bash
  cat file_a.txt file_b.txt file_c.txt > merged-file.txt
  ```

  ## Count lines, words, etc: `wc`

  To count words:

  ```bash
  wc file.txt
  ```

  When we use the command three numbers are outputted, in order: lines, words,
  bytes.

  You can use modifiers to get just one of the numbers: `-l`, `-w` , `-b` .

raw_content:
  ---
  tags:
    - shell
  ---

  # Text manipulation

  ## Sorting strings: `sort`

  If you have a `.txt` file containing text strings, each on a new line you can
  use the sort function to quickly put them in alphabetical order:

  ```bash
  sort file.txt
  ```

  Note that this will not save the sort, it only presents it as a standard output.
  To save the sort you need to direct the sort to a file in the standard way:

  ```bash
  sort file.txt > output.txt
  ```

  ### Options

  - `-r`
    - reverse sort
  - `c`
    - check if file is already sorted. If not, it will highlight the strings which
      are not sorted

  ## Find and replace: `sed`

  The `sed` programme can be used to implement find and replace procedures. In
  `sed`, find and replace are covered by the substitution option: `/s` :

  ```bash
  sed ‘s/word/replacement word/’ file.txt
  ```

  This however will only change the first instance of word to be replaced, in
  order to apply to every instance you need to add the global option: `-g` .

  As sed is a stream editor, any changes you make using it, will only occur within
  the standard output , they will not be saved to file. In order to save to file
  you need to specify a new file output (using `> output.txt`) in addition to the
  original file. This hasthe benefit of leaving the original file untouched whilst
  ensuring the desired outcome is stored permanently.

  Alternatively, you can use the `-i` option which will make the changes take
  place in the source file as well as in standard input.

  Note that this will overwrite the original version of the file and it cannot be
  regained. If this is an issue then it is recommended to include a backup command
  in the overall argument like so:

  ```bash
  sed -i.bak ‘s/word/replacement word/’ file.txt
  ```

  This will create the file `file.txt.bak` in the directory you are working within
  which is the original file before the replacement was carried out.

  ### Remove duplicates

  We can use the `sort -u` command can be used to remove duplicates:

  ```bash
  sort -u file.txt
  ```

  It is important to sort before attempting to remove duplicates since the `-u`
  flag works on the basis of the strings being adjacent.

  ## Split a large file into multiple smaller files: `split`

  Suppose you have a file containing 1000 lines. You want to break the file up
  into five separate files, each containing two hundred lines. You can use `split`
  to accomplish this, like so:

  ```bash
  split -l 200 big-file.txt new-files
  ```

  `split` will categorise the resulting five files as follows:

  - new-file-aa,
  - new-file-ab
  - new-file-ac,
  - newfile-ad,
  - new-file-ae.

  If you would rather have numeric suffixes, use the option `-d` . You can also
  split a file by its number of bytes, using the option `-b` and specifying a
  constituent file size.

  ## Merge multiple files into one with `cat`

  We can use `cat` read multiple files at once and then append a redirect to save
  them to a file:

  ```bash
  cat file_a.txt file_b.txt file_c.txt > merged-file.txt
  ```

  ## Count lines, words, etc: `wc`

  To count words:

  ```bash
  wc file.txt
  ```

  When we use the command three numbers are outputted, in order: lines, words,
  bytes.

  You can use modifiers to get just one of the numbers: `-l`, `-w` , `-b` .


path: zk/The_kernel.md
sortable_path: zkThe_kernel.md
title: The kernel
checksum: 96c9ce4e7d5964c10b9af81b81e350210f24146bc8a16245169ff057cdb3dd4f
created: 2024-06-16 17:37:31.958371212+00:00
modified: 2024-06-21 05:06:21.705739867+00:00
metadata: {"tags":["systems-programming","memory","operating-systems","computer-architecture"]}
lead:
  Within the [hierarchy of the OS](./Basic_model_of_the_operating_system.md), the
  kernel acts as the primary mediator between the hardware (CPU, memory) and
  [user](./User_Space.md) [processes](Processes.md). Let's look at each of its
  responsibilities in greater depth:

body:
  Within the [hierarchy of the OS](./Basic_model_of_the_operating_system.md), the
  kernel acts as the primary mediator between the hardware (CPU, memory) and
  [user](./User_Space.md) [processes](Processes.md). Let's look at each of its
  responsibilities in greater depth:

  - process management
  - memory management
  - device drivers
  - system calls

  ## Process management

  > A process is just another name for a running program. Process management is
  > the starting, pausing, resuming, scheduling and terminating of processes.

  On modern computers it appears that multiple processes can run simultaneously at
  once. This is only because the processor is so fast that we do not detect
  changes. In fact access to the CPU is always sequential. The sequence in which
  multiple programs are allowed to access the CPU is managed by the kernel.

  > Consider a system with a one-core CPU. Many processes may be _able_ to use the
  > CPU, but only one process can actually use the CPU at any given time...Each
  > process uses the CPU for a fraction of a second, then pauses, then another
  > process uses it for a fraction of a second and so on... (_How Linux Works:
  > Third Edition_, Brian Ward 2021)

  This process of the CPU shuffling between multiple processes is called _context
  switching_.

  The role of the kernel in facilitating this, is as follows:

  1. CPU runs process for a time slice based on its internal time. Then hands
     control back to the kernel (kernel mode)
  2. Kernel records current state of CPU and memory. This is necessary in order to
     resume the progress that was just interupted.
  3. The kernel executes any tasks that arose in the last timeslice executed by
     the CPU (e.g. collecting data from I/0)
  4. Kernel then analyses the list of processes that are ready to run next and
     chooses one.
  5. Kernel prepares memory for this new process and prepares the CPU.
  6. Kernel tells CPU how long the time slice for the new process will last.
  7. Kernel switches the CPU into user mode and hands control of CPU to the
     process.

  ## Memory management

  During the context switch from CPU to user space, the kernel allocates memory.
  It has the following jobs to manage:

  - Keeping its own private area in memory for itself that user processes cannot
    access
  - Assigning each user process its own section of memory
  - Managing shared memory between processes and ensuring the private memory of
    processes is not accessed by others
  - Managing read-only memory
  - Allowing for the use of disk space as auxiliary memory

  > Modern CPUs include a
  > [memory management unit](Virtual_memory_and_the_MMU_in_Linux.md#the-memory-management-unit-mmu)
  > which provides the kernel with **virtual** memory. In this scenario, memory
  > isn't directly accessed by the process instead it works on the assumption that
  > is has access to the entire memory of the machine and this is then translated
  > into a map that is applied to the real memory and managed by the kernel.

  ## Device drivers

  Devices are managed by the kernal and are not accessible directly via user
  space, since improper usage could crash the whole machine. There is little
  uniformity between devices and as a result drivers are needed. Thes are kernl
  code that enable different OS kernels to access and control the devices.

  ## System calls

  Syscalls are what enable programs to start and are required for the acts of
  opening, reading and writing files. System calls in Linux are typically managed
  via C.

  In Linux there are two particularly important system calls:

  - `fork()`
    - When a process calls fork, the kernel creates a nearly identical copy of
      this running process
  - `exec()`
    - When a process calls exec it passes a program name as a parameter. Then the
      kernel loads and starts this program, replacing the current process.

  Example with a terminal program like `ls`:

  > When you enter `ls` into the terminal window, the shell that's running inside
  > the terminal window calls `fork()` to create a copy of the shell, and then the
  > new copy of the shell calls `exec(ls)` to run `ls`. (_Ibid._)

  ## Controlling processes

  In Linux we can view, kill, pause and resume processes using [ps](Processes.md).

raw_content:
  ---
  tags:
    - systems-programming
    - memory
    - operating-systems
    - computer-architecture
  ---

  # The kernel

  Within the [hierarchy of the OS](./Basic_model_of_the_operating_system.md), the
  kernel acts as the primary mediator between the hardware (CPU, memory) and
  [user](./User_Space.md) [processes](Processes.md). Let's look at each of its
  responsibilities in greater depth:

  - process management
  - memory management
  - device drivers
  - system calls

  ## Process management

  > A process is just another name for a running program. Process management is
  > the starting, pausing, resuming, scheduling and terminating of processes.

  On modern computers it appears that multiple processes can run simultaneously at
  once. This is only because the processor is so fast that we do not detect
  changes. In fact access to the CPU is always sequential. The sequence in which
  multiple programs are allowed to access the CPU is managed by the kernel.

  > Consider a system with a one-core CPU. Many processes may be _able_ to use the
  > CPU, but only one process can actually use the CPU at any given time...Each
  > process uses the CPU for a fraction of a second, then pauses, then another
  > process uses it for a fraction of a second and so on... (_How Linux Works:
  > Third Edition_, Brian Ward 2021)

  This process of the CPU shuffling between multiple processes is called _context
  switching_.

  The role of the kernel in facilitating this, is as follows:

  1. CPU runs process for a time slice based on its internal time. Then hands
     control back to the kernel (kernel mode)
  2. Kernel records current state of CPU and memory. This is necessary in order to
     resume the progress that was just interupted.
  3. The kernel executes any tasks that arose in the last timeslice executed by
     the CPU (e.g. collecting data from I/0)
  4. Kernel then analyses the list of processes that are ready to run next and
     chooses one.
  5. Kernel prepares memory for this new process and prepares the CPU.
  6. Kernel tells CPU how long the time slice for the new process will last.
  7. Kernel switches the CPU into user mode and hands control of CPU to the
     process.

  ## Memory management

  During the context switch from CPU to user space, the kernel allocates memory.
  It has the following jobs to manage:

  - Keeping its own private area in memory for itself that user processes cannot
    access
  - Assigning each user process its own section of memory
  - Managing shared memory between processes and ensuring the private memory of
    processes is not accessed by others
  - Managing read-only memory
  - Allowing for the use of disk space as auxiliary memory

  > Modern CPUs include a
  > [memory management unit](Virtual_memory_and_the_MMU_in_Linux.md#the-memory-management-unit-mmu)
  > which provides the kernel with **virtual** memory. In this scenario, memory
  > isn't directly accessed by the process instead it works on the assumption that
  > is has access to the entire memory of the machine and this is then translated
  > into a map that is applied to the real memory and managed by the kernel.

  ## Device drivers

  Devices are managed by the kernal and are not accessible directly via user
  space, since improper usage could crash the whole machine. There is little
  uniformity between devices and as a result drivers are needed. Thes are kernl
  code that enable different OS kernels to access and control the devices.

  ## System calls

  Syscalls are what enable programs to start and are required for the acts of
  opening, reading and writing files. System calls in Linux are typically managed
  via C.

  In Linux there are two particularly important system calls:

  - `fork()`
    - When a process calls fork, the kernel creates a nearly identical copy of
      this running process
  - `exec()`
    - When a process calls exec it passes a program name as a parameter. Then the
      kernel loads and starts this program, replacing the current process.

  Example with a terminal program like `ls`:

  > When you enter `ls` into the terminal window, the shell that's running inside
  > the terminal window calls `fork()` to create a copy of the shell, and then the
  > new copy of the shell calls `exec(ls)` to run `ls`. (_Ibid._)

  ## Controlling processes

  In Linux we can view, kill, pause and resume processes using [ps](Processes.md).


path: zk/Troubleshooting_MongoDB.md
sortable_path: zkTroubleshooting_MongoDB.md
title: Troubleshooting MongoDB connection issues
lead: ## Arch Linux troubleshooting
checksum: 764b19f1d36a6c0d05f28bf1f30d52c829fe3030cef31f8e3c8efabf28f1f4c3
created: 2024-06-16 17:37:32.020694929+00:00
modified: 2024-03-27 10:45:52.506858751+00:00
metadata: {"tags":["mongo-db"]}
body:
  ## Arch Linux troubleshooting

  Most times any problems will be a result of a Mongo process that is already
  running. Resolve with:

  ```bash
  # Kill running Mongo process...
  # Identify PID
  sudo lsof -iTCP -sTCP:LISTEN -n -P
  sudo kill [pid]
  ```

  Otherwise try the below.

  ```bash
  # Check that the systemd service is runnign for Mongo
  sudo systemctl status mongodb

  # If not, enable and start service (only need to do this once for machine)
  sudo systemctl enable --now mongodb
  sudo systemctl start --now mongodb

  # If issues with Mongo daemon...
  # Remove the current socket
  rm /tmp/mongodb-27017.sock
  ```

  For additional command line utilities you will also need to install
  `mongodb-tools` from the AUR.

raw_content:
  ---
  tags: [mongo-db]
  ---

  # Troubleshooting MongoDB connection issues

  ## Arch Linux troubleshooting

  Most times any problems will be a result of a Mongo process that is already
  running. Resolve with:

  ```bash
  # Kill running Mongo process...
  # Identify PID
  sudo lsof -iTCP -sTCP:LISTEN -n -P
  sudo kill [pid]
  ```

  Otherwise try the below.

  ```bash
  # Check that the systemd service is runnign for Mongo
  sudo systemctl status mongodb

  # If not, enable and start service (only need to do this once for machine)
  sudo systemctl enable --now mongodb
  sudo systemctl start --now mongodb

  # If issues with Mongo daemon...
  # Remove the current socket
  rm /tmp/mongodb-27017.sock
  ```

  For additional command line utilities you will also need to install
  `mongodb-tools` from the AUR.


path: zk/Type_guarding_and_narrowing_in_TS.md
sortable_path: zkType_guarding_and_narrowing_in_TS.md
title: Type narrowing and guarding
checksum: 490017e14d24edb1d0dbb214c845e7c0f56679e29856822fd555a7f4d46e88b5
created: 2024-06-16 17:37:32.164007308+00:00
modified: 2024-06-16 17:27:18.625450007+00:00
metadata: {"tags":["typescript"]}
lead:
  Type narrowing is the process of working out from a supertype like
  [any](Any.md) or [unknown](Unknown_type_in_TS.md) whic type the value should be in the
  x course of your code. This is necessary since a process will not necessarily
  always return or involve homogenous types.

body:
  Type narrowing is the process of working out from a supertype like
  [any](Any.md) or [unknown](Unknown_type_in_TS.md) whic type the value should be in the
  x course of your code. This is necessary since a process will not necessarily
  always return or involve homogenous types.

  Related to this is type guarding: ensuring that a value is of the suitable type
  as a factor of control flow. For instance using typeof to ensure that an input
  is numerical before proceeding with a function's logic.

raw_content:
  ---
  tags:
    - typescript
  ---

  # Type narrowing and guarding

  Type narrowing is the process of working out from a supertype like
  [any](Any.md) or [unknown](Unknown_type_in_TS.md) whic type the value should be in the
  x course of your code. This is necessary since a process will not necessarily
  always return or involve homogenous types.

  Related to this is type guarding: ensuring that a value is of the suitable type
  as a factor of control flow. For instance using typeof to ensure that an input
  is numerical before proceeding with a function's logic.


path: zk/Union_types_in_TS.md
sortable_path: zkUnion_types_in_TS.md
title: Union types
checksum: c821ae262bc36f541ebebc61d22c3d5bd95bb51fa3dd7b44522c80fe2956ee3f
created: 2024-06-16 17:37:32.182332489+00:00
modified: 2024-03-27 10:45:52.506858751+00:00
metadata: {"tags":["typescript"]}
lead:
  Like intersection types, union types allow us to combine the properties of
  existing primitive and custom types to make composites.

body:
  Like intersection types, union types allow us to combine the properties of
  existing primitive and custom types to make composites.

  Intersection types work well when you have complete knowledge of what form your
  data will take. This approach only works if you know in advance that your data
  will be and that it will share properties from more than one type. But what if
  you don't have this knowledge? You only know that it will be one of the three
  possible types? This is where union types become helpful. Instead of saying that
  event X will be of type A we say that event X may be one of types A or B or C.

  > A union type is a type formed from two or more other types, representing
  > values that may be any one of those types. We refer to each of these types as
  > the union’s members.

  ## Demonstration

  ```ts
  type Petrol = {
    maxSpeed: number;
    tankVolume: number; // unique property
  };

  type Electric = {
    maxSpeed: number;
    maxCharge: number; // unique property
  };

  type Car = Petrol | Electric;

  const tesla: Car = {
    maxSpeed: 120,
    maxCharge: 22,
  };
  ```

  - We have defined two custom types: `Petrol` and `Electric`
  - We have unified them to make a new custom type of `Car`
  - `tesla` is an instance of the union type

  ## Usage with functions

  Union type syntax is not limited to the declaration phase. You can also use them
  as parameters to functions or function return types:

  ```ts
  function generateCar(car: Petrol | Electric): void {
    console.log(`The car has a max speed of ${car.maxSpeed}`);
  }
  ```

  ## Unifying primitive and custom types

  We can also use unions with primitive types as well as custom types:

  ```ts
  function printId(id: number | string): void {
    console.log(`Your id is ${id}`);
  }
  ```

  We can also combine primitive and custom types in the same union:

  ```ts
  function printStringOrNumber(): string | Petrol {}
  ```

  ## Set theory: understanding errors

  In JavaScript we have the primitive types of string , number , boolean etc. In
  TS, these types are distinct and exclusive: if you declare that x : string you
  cannot redefine it as boolean or expect Boolean properties and methods to belong
  to a string type. For instance a string type is incapable of having as its value
  false.

  This is not true in the case of unions.

  With a union of `string | boolean` a value `x` could be `'banana'` or `true`. We
  are allowing for all values that are either from the set string or the set
  boolean. Logically this is equivalent to the OR operator: a value of type
  `string | boolean` could be one of infinite possible strings or true/false. With
  union types then, we radically widen the scope of possible values for the type.
  a

  These constraints don't just apply to the values themselves but the methods and
  properties you can use with the values. For instance a boolean doesn't have the
  property of `length`. Therefore if you have a union type of `string|boolean` you
  are going to get an error if you apply `length` to it since **the property must
  exist on both types that comprise the union**. The way round this is to use type
  narrowing and execute control flow based on the parameter that is passed to a
  function that is declared to be of this mixed type.

  Here is an example of this:

  ```ts
  function printId(id: number | string) {
    if (typeof id === "string") {
      // In this branch, id is of type 'string'
      console.log(id.toUpperCase());
    } else {
      // Here, id is of type 'number'
      console.log(id);
    }
  }
  ```

raw_content:
  ---
  tags:
    - typescript
  ---

  # Union types

  Like intersection types, union types allow us to combine the properties of
  existing primitive and custom types to make composites.

  Intersection types work well when you have complete knowledge of what form your
  data will take. This approach only works if you know in advance that your data
  will be and that it will share properties from more than one type. But what if
  you don't have this knowledge? You only know that it will be one of the three
  possible types? This is where union types become helpful. Instead of saying that
  event X will be of type A we say that event X may be one of types A or B or C.

  > A union type is a type formed from two or more other types, representing
  > values that may be any one of those types. We refer to each of these types as
  > the union’s members.

  ## Demonstration

  ```ts
  type Petrol = {
    maxSpeed: number;
    tankVolume: number; // unique property
  };

  type Electric = {
    maxSpeed: number;
    maxCharge: number; // unique property
  };

  type Car = Petrol | Electric;

  const tesla: Car = {
    maxSpeed: 120,
    maxCharge: 22,
  };
  ```

  - We have defined two custom types: `Petrol` and `Electric`
  - We have unified them to make a new custom type of `Car`
  - `tesla` is an instance of the union type

  ## Usage with functions

  Union type syntax is not limited to the declaration phase. You can also use them
  as parameters to functions or function return types:

  ```ts
  function generateCar(car: Petrol | Electric): void {
    console.log(`The car has a max speed of ${car.maxSpeed}`);
  }
  ```

  ## Unifying primitive and custom types

  We can also use unions with primitive types as well as custom types:

  ```ts
  function printId(id: number | string): void {
    console.log(`Your id is ${id}`);
  }
  ```

  We can also combine primitive and custom types in the same union:

  ```ts
  function printStringOrNumber(): string | Petrol {}
  ```

  ## Set theory: understanding errors

  In JavaScript we have the primitive types of string , number , boolean etc. In
  TS, these types are distinct and exclusive: if you declare that x : string you
  cannot redefine it as boolean or expect Boolean properties and methods to belong
  to a string type. For instance a string type is incapable of having as its value
  false.

  This is not true in the case of unions.

  With a union of `string | boolean` a value `x` could be `'banana'` or `true`. We
  are allowing for all values that are either from the set string or the set
  boolean. Logically this is equivalent to the OR operator: a value of type
  `string | boolean` could be one of infinite possible strings or true/false. With
  union types then, we radically widen the scope of possible values for the type.
  a

  These constraints don't just apply to the values themselves but the methods and
  properties you can use with the values. For instance a boolean doesn't have the
  property of `length`. Therefore if you have a union type of `string|boolean` you
  are going to get an error if you apply `length` to it since **the property must
  exist on both types that comprise the union**. The way round this is to use type
  narrowing and execute control flow based on the parameter that is passed to a
  function that is declared to be of this mixed type.

  Here is an example of this:

  ```ts
  function printId(id: number | string) {
    if (typeof id === "string") {
      // In this branch, id is of type 'string'
      console.log(id.toUpperCase());
    } else {
      // Here, id is of type 'number'
      console.log(id);
    }
  }
  ```


path: zk/Unknown_type_in_TS.md
sortable_path: zkUnknown_type_in_TS.md
title: Unknown
checksum: 8c0f68fad261ac22cf13cf968e917e2308e19247798725d27b71e2be1a1a3da2
created: 2024-06-16 17:37:32.188926698+00:00
modified: 2024-03-27 10:45:52.506858751+00:00
metadata: {"tags":["typescript"]}
lead:
  You might think that a good use case for `any` is a scenario where you don't
  know in advance what the data type is going to be.

body:
  You might think that a good use case for `any` is a scenario where you don't
  know in advance what the data type is going to be.

  In order to mark that this is the case, you type the value as `any`. In fact,
  TypeScript provides a type for this specific scenario: `unknown`.

  Like `any`, `unknown` is equivalent to every type in TS (it is also a supertype)
  but it is deliberately inhibiting, in contrast to `any`. When you use `unknown`
  you have to use type narrowing to avoid it being returned. So if your code
  starts with `unknown`, you should filter out scenarios where it evaluates to
  each of the possible types otherwise if `unknown` is returned it will cause an
  error.

raw_content:
  ---
  tags:
    - typescript
  ---

  # Unknown

  You might think that a good use case for `any` is a scenario where you don't
  know in advance what the data type is going to be.

  In order to mark that this is the case, you type the value as `any`. In fact,
  TypeScript provides a type for this specific scenario: `unknown`.

  Like `any`, `unknown` is equivalent to every type in TS (it is also a supertype)
  but it is deliberately inhibiting, in contrast to `any`. When you use `unknown`
  you have to use type narrowing to avoid it being returned. So if your code
  starts with `unknown`, you should filter out scenarios where it evaluates to
  each of the possible types otherwise if `unknown` is returned it will cause an
  error.


path: zk/User_management_in_Linux.md
sortable_path: zkUser_management_in_Linux.md
title: User management
lead: ## Switch user
checksum: e5c96a6157409e2d25e0f6278475b4bb97323774450952af78f3ad3ea1369622
created: 2024-06-16 17:37:32.196102048+00:00
modified: 2024-06-16 17:33:56.283646467+00:00
metadata: {"tags":["Linux","procedural"]}
body:
  ## Switch user

  If already logged in as a user you can switch users with the command
  `su - [username]`.

  ## Login as root

  If you are logged in as a standard user, if you use `su -` without specifying a
  username, then it will assume you wish to log in as root.

  If you wish to login as root in the tty at startup, then use `root` as the
  username.

raw_content:
  ---
  tags:
    - Linux
    - procedural
  ---

  # User management

  ## Switch user

  If already logged in as a user you can switch users with the command
  `su - [username]`.

  ## Login as root

  If you are logged in as a standard user, if you use `su -` without specifying a
  username, then it will assume you wish to log in as root.

  If you wish to login as root in the tty at startup, then use `root` as the
  username.


path: zk/Utilities_operators_flags.md
sortable_path: zkUtilities_operators_flags.md
title: Flags
lead: ### Prevent newline
checksum: a337ba34dc84259e41d04f49430beff149ec176bc74d5f2bf49b7b17623cd857
created: 2024-06-16 17:37:32.208963277+00:00
modified: 2024-03-27 10:45:52.506858751+00:00
metadata: {"tags":["shell"]}
body:
  ### Prevent newline

  Prevent bash from adding a new line after an echo:

  ```bash
  echo 'Your name is Thomas'
  echo 'and you are 33 years old'

  # Your name is Thomas
  # and you are 33 years old
  ```

  ```bash
  echo -n 'Your name is Thomas '
  echo 'and you are 33 years old'

  # Your name is Thomas and you are 33 years old
  ```

  ## Operators

  ### Mathematical

  ```bash
  -lt , -gt,
  ```

raw_content:
  ---
  tags:
    - shell
  ---

  The following are useful built-in utility methods that you can use for checking
  and validation in the course of your bash scripts.

  ## Flags

  ### Prevent newline

  Prevent bash from adding a new line after an echo:

  ```bash
  echo 'Your name is Thomas'
  echo 'and you are 33 years old'

  # Your name is Thomas
  # and you are 33 years old
  ```

  ```bash
  echo -n 'Your name is Thomas '
  echo 'and you are 33 years old'

  # Your name is Thomas and you are 33 years old
  ```

  ## Operators

  ### Mathematical

  ```bash
  -lt , -gt,
  ```


path: zk/Validation_in_NodeJS.md
sortable_path: zkValidation_in_NodeJS.md
title: Creating a RESTful API: Validation
checksum: 6f0c4e7f0af95a7522c442d4991bd06ab0a817dac6eabb19ed81afb036089759
created: 2024-06-16 17:37:32.228913914+00:00
modified: 2024-06-15 09:50:54.243778564+00:00
metadata: {"tags":["node-js","REST","APIs"]}
lead:
  We can provide server-side validation for our projects by using a **schema
  validator**. This is a program that declaratively parses the JSON values
  received as requests from the client. This makes it easy to systematically
  validate the data that we receive from any HTTP requests where the client sends
  a body to the endpoint.

body:
  We can provide server-side validation for our projects by using a **schema
  validator**. This is a program that declaratively parses the JSON values
  received as requests from the client. This makes it easy to systematically
  validate the data that we receive from any HTTP requests where the client sends
  a body to the endpoint.

  One of the most popular schema validators for NodeJS is
  [joi](joi).

  ## Demonstration

  Let's say we have a POST request that expects a single field as the body that
  must be a string and greater than two characters long. First we define our
  schema:

  ```js
  const schema = Joi.object({
    name: Joi.string().min(3).required(),
  });

  const { error } = schema.validate(req.body);
  ```

  The `schema` variable is an object whose keys should match those of the intended
  request body. Instead of actual values we provide Joi's in-built validators,
  concatenated as necessary. We then store the results of the validation in a
  variable.

  Next we add handling in the case of errors:

  ```js
  if (error) {
    error.details.map((joiErr) => res.status(400).send(joiErr.message));
    return;
  }
  ```

  We loop through the error array and return 400s as the response if they are
  found. If there are no errors, the Joi object will return `undefined`.

raw_content:
  ---
  tags:
    - node-js
    - REST
    - APIs
  ---

  # Creating a RESTful API: Validation

  We can provide server-side validation for our projects by using a **schema
  validator**. This is a program that declaratively parses the JSON values
  received as requests from the client. This makes it easy to systematically
  validate the data that we receive from any HTTP requests where the client sends
  a body to the endpoint.

  One of the most popular schema validators for NodeJS is
  [joi](joi).

  ## Demonstration

  Let's say we have a POST request that expects a single field as the body that
  must be a string and greater than two characters long. First we define our
  schema:

  ```js
  const schema = Joi.object({
    name: Joi.string().min(3).required(),
  });

  const { error } = schema.validate(req.body);
  ```

  The `schema` variable is an object whose keys should match those of the intended
  request body. Instead of actual values we provide Joi's in-built validators,
  concatenated as necessary. We then store the results of the validation in a
  variable.

  Next we add handling in the case of errors:

  ```js
  if (error) {
    error.details.map((joiErr) => res.status(400).send(joiErr.message));
    return;
  }
  ```

  We loop through the error array and return 400s as the response if they are
  found. If there are no errors, the Joi object will return `undefined`.


path: zk/Variable_indirection_in_Bash.md
sortable_path: zkVariable_indirection_in_Bash.md
title: Variable indirection
lead: > Write proper notes on this
checksum: 6682743efcc1a97b2ba0760899b1690e9af193e72e3df5a957904ab8e01726a5
created: 2024-06-16 17:37:32.243804241+00:00
modified: 2024-03-27 10:45:52.506858751+00:00
metadata: {"tags":["shell"]}
body:
  > Write proper notes on this

  ```sh
  function array_empty() {
      declare -n arr=$1
      # Proceed if array not empty:
      if [ ${#arr[@]} -gt 0 ]; then
          return 1 # array is not empty
      else
          return 0 # array is empty
      fi
  }

  my_array=(1 2 3)

  function push() {
      # $1 = stack name
      local stack_name="$1"
      if [ "${stack_name}" ]; then # stack exists
          if array_empty "${!stack_name}"; then
              echo "stack is empty"
          else
              echo "stack is not empty"
          fi
      else
          echo "Error: ${stack_name} does not exist."
      fi
  }

  push "my_array"

  ```

  In Bash scripting, ${!stack_name} is an example of indirect variable referencing
  or variable indirection. It's a way to use a variable whose name is stored in
  another variable.

  Let's break it down:

  `${stack_name}`: This syntax is used to reference the value of a variable. So if
  stack_name="my_array", then ${stack_name} would return "my_array".

  `${!stack_name}`: Adding the ! introduces indirection. Now, instead of getting
  the value of stack_name, you get the value of the variable whose name is stored
  in stack_name. So if stack_name="my_array" and my_array=(1 2 3), then
  ${!stack_name} would return (1 2 3).

  So, in the context of your script, `${!stack_name} allows you to pass the name
  of an array (as a string) to your push function, and then use that string to
  indirectly reference the actual array within the function.

raw_content:
  ---
  tags:
    - shell
  ---

  # Variable indirection

  > Write proper notes on this

  ```sh
  function array_empty() {
      declare -n arr=$1
      # Proceed if array not empty:
      if [ ${#arr[@]} -gt 0 ]; then
          return 1 # array is not empty
      else
          return 0 # array is empty
      fi
  }

  my_array=(1 2 3)

  function push() {
      # $1 = stack name
      local stack_name="$1"
      if [ "${stack_name}" ]; then # stack exists
          if array_empty "${!stack_name}"; then
              echo "stack is empty"
          else
              echo "stack is not empty"
          fi
      else
          echo "Error: ${stack_name} does not exist."
      fi
  }

  push "my_array"

  ```

  In Bash scripting, ${!stack_name} is an example of indirect variable referencing
  or variable indirection. It's a way to use a variable whose name is stored in
  another variable.

  Let's break it down:

  `${stack_name}`: This syntax is used to reference the value of a variable. So if
  stack_name="my_array", then ${stack_name} would return "my_array".

  `${!stack_name}`: Adding the ! introduces indirection. Now, instead of getting
  the value of stack_name, you get the value of the variable whose name is stored
  in stack_name. So if stack_name="my_array" and my_array=(1 2 3), then
  ${!stack_name} would return (1 2 3).

  So, in the context of your script, `${!stack_name} allows you to pass the name
  of an array (as a string) to your push function, and then use that string to
  indirectly reference the actual array within the function.


path: zk/Variables_and_data_types_in_Bash.md
sortable_path: zkVariables_and_data_types_in_Bash.md
title: Types
lead: ## Variables
checksum: 5d0734a826d4cd925e0eac4fc3da7eb6b0ad3cbedebb3da59ffefc3189d0347e
created: 2024-06-16 17:37:32.248470584+00:00
modified: 2024-03-27 10:45:52.506858751+00:00
metadata: {"tags":["shell"]}
body:
  ## Variables

  We use the equality symbol to create a variable:

  ```bash
  stringVar="My first variable"
  floatVar="50.3"
  boolVar="true"
  ```

  As there is no typing in bash, the names of these variables are purely notional.

  To invoke a variable we use special brackets:

  ```bash
  echo ${stringVar} # My first variable
  echo ${floatVar} # 50.3
  echo ${boolVar} # true
  ```

  - Quotation marks at declaration are also not strictly necessary however they
    can help avoid bugs. Also serves as a reminder that every type is basically a
    string at the end of the day

  ## Common operations

  ### Check if a variable exists

  ```sh
  if [ -v variable_name ]; then
      echo "The variable exists."
  else
      echo "The variable does not exist."
  fi
  ```

  ### Check if a variable is set (defined)

  ```sh
  if [ -z "${variable_name+x}" ]; then
      echo "The variable does not exist."
  else
      echo "The variable exists."
  fi
  ```

  ## Parameter expansion

  Still not very clear on this.

raw_content:
  ---
  tags:
    - shell
  ---

  ## Types

  ## Variables

  We use the equality symbol to create a variable:

  ```bash
  stringVar="My first variable"
  floatVar="50.3"
  boolVar="true"
  ```

  As there is no typing in bash, the names of these variables are purely notional.

  To invoke a variable we use special brackets:

  ```bash
  echo ${stringVar} # My first variable
  echo ${floatVar} # 50.3
  echo ${boolVar} # true
  ```

  - Quotation marks at declaration are also not strictly necessary however they
    can help avoid bugs. Also serves as a reminder that every type is basically a
    string at the end of the day

  ## Common operations

  ### Check if a variable exists

  ```sh
  if [ -v variable_name ]; then
      echo "The variable exists."
  else
      echo "The variable does not exist."
  fi
  ```

  ### Check if a variable is set (defined)

  ```sh
  if [ -z "${variable_name+x}" ]; then
      echo "The variable does not exist."
  else
      echo "The variable exists."
  fi
  ```

  ## Parameter expansion

  Still not very clear on this.


path: zk/Variables_in_C.md
sortable_path: zkVariables_in_C.md
title: Variables in C
lead: # Variables in C
body:
  # Variables in C

  ```c
  int age = 25
  ```

checksum: b702bec2aebc256d92e83e60ef9beefdd46605d1a435691d4936b840e6ba160c
created: 2024-06-16 17:37:32.252810994+00:00
modified: 2024-03-27 10:45:52.510192133+00:00
raw_content:
  ---
  id: r4i16p1x
  title: Variables in C
  tags: [C]
  created: Thursday, February 29, 2024 | 17:20
  ---

  # Variables in C

  ```c
  int age = 25
  ```

metadata:
  {"created":"Thursday, February 29, 2024 | 17:20","id":"r4i16p1x","tags":["C"],"title":"Variables in C"}


path: zk/Virtual_memory_and_the_MMU_in_Linux.md
sortable_path: zkVirtual_memory_and_the_MMU_in_Linux.md
title: Virtual memory and the Memory Management Unit
lead: ## What is virtual memory?
checksum: 97de11ae4898b66ca13b10f813679b7fcb402c812769f6cf9f37fe552e54a93e
created: 2024-06-16 17:37:32.259874958+00:00
modified: 2024-06-16 17:35:22.5769918+00:00
metadata: {"tags":["memory","Linux"]}
body:
  ## What is virtual memory?

  Virtual memory is implemented at the level of the operating system and is an
  abstraction on top of 'real', physical memory (i.e the charges stored within the
  actual DRAM component.).

  When virtual memory is used, the CPU handles physical memory allocation and
  presents this to the kernel as an idealised representation. This means that the
  kernel and, by extension, programs and processes do not need to think about
  accessing the real memory blocks. This reduces complexity because often memory
  will be allocated in places that are non-contiguous with similar running
  processes or be located in the cache or swap memory on the disk.

  ![](/img/virtual-memory-diagram.jpg)

  It would require considerable processing work for the kernel to be tracing these
  disparate memory sources at every instance. By working on an idealised
  (contiguous, unlimited) memory set the kernel can focus on task management and
  CPU sequencing as its primary task.

  The memory is idealised in that all locations are represented virtually as being
  contiguous (even when this is not physically the case). Secondly, quantities of
  available memory can be presented as much larger than is actually the case and
  which often exceed the physical memory limits of the device. This is achieved
  through paging, handled by the MMU.

  ## The Memory Management Unit (MMU)

  Without an MMU, when the CPU accesses RAM, the actual RAM locations never
  change. The memory address is always the same physical location within the RAM.
  The MMU is a chip that sits between the CPU and RAM recalculating the actual
  memory address from the virtual memory location requested by the kernel.

  ## Pages

  We use the term **pages** to denote blocks of virtual memory and to distinguish
  them from **addresses** as physical blocks. The MMU possesses a **page table**
  which is registry logging which pages correspond to which physical blocks.

  ## Shared pages

  Virtual memory allows the sharing of files and memory by multiple processes.
  Crucially the shared data doesn't have to be within the address of each process,
  instead there is a reference in the page table that each process has access to
  the shared data.

  ## Page faults

  There are two kinds of error that can occur with relation to paged memory:

  - minor page faults
    - The desired page is in main memory but the MMU doesn't currently know where
      it is
  - major page faults
    - The desired page is not in main memory at all. Therefore the kernel must
      fetch it from disk

  Minor page faults are very common and are to be expected; they resolve quickly.
  On the other hand too many major page faults can slow the system down both
  because of the time-costly process of fetching data from disk and because it
  demands more kernel resources to locate the missing page, which puts other
  processes on hold.

  ## Resources

  [Virtual memory](9_VirtualMemory.html#:~:text=Virtual%20memory%20also%20allows%20the,to%20more%20than%20one%20process)

raw_content:
  ---
  tags:
    - memory
    - Linux
  ---

  # Virtual memory and the Memory Management Unit

  ## What is virtual memory?

  Virtual memory is implemented at the level of the operating system and is an
  abstraction on top of 'real', physical memory (i.e the charges stored within the
  actual DRAM component.).

  When virtual memory is used, the CPU handles physical memory allocation and
  presents this to the kernel as an idealised representation. This means that the
  kernel and, by extension, programs and processes do not need to think about
  accessing the real memory blocks. This reduces complexity because often memory
  will be allocated in places that are non-contiguous with similar running
  processes or be located in the cache or swap memory on the disk.

  ![](/img/virtual-memory-diagram.jpg)

  It would require considerable processing work for the kernel to be tracing these
  disparate memory sources at every instance. By working on an idealised
  (contiguous, unlimited) memory set the kernel can focus on task management and
  CPU sequencing as its primary task.

  The memory is idealised in that all locations are represented virtually as being
  contiguous (even when this is not physically the case). Secondly, quantities of
  available memory can be presented as much larger than is actually the case and
  which often exceed the physical memory limits of the device. This is achieved
  through paging, handled by the MMU.

  ## The Memory Management Unit (MMU)

  Without an MMU, when the CPU accesses RAM, the actual RAM locations never
  change. The memory address is always the same physical location within the RAM.
  The MMU is a chip that sits between the CPU and RAM recalculating the actual
  memory address from the virtual memory location requested by the kernel.

  ## Pages

  We use the term **pages** to denote blocks of virtual memory and to distinguish
  them from **addresses** as physical blocks. The MMU possesses a **page table**
  which is registry logging which pages correspond to which physical blocks.

  ## Shared pages

  Virtual memory allows the sharing of files and memory by multiple processes.
  Crucially the shared data doesn't have to be within the address of each process,
  instead there is a reference in the page table that each process has access to
  the shared data.

  ## Page faults

  There are two kinds of error that can occur with relation to paged memory:

  - minor page faults
    - The desired page is in main memory but the MMU doesn't currently know where
      it is
  - major page faults
    - The desired page is not in main memory at all. Therefore the kernel must
      fetch it from disk

  Minor page faults are very common and are to be expected; they resolve quickly.
  On the other hand too many major page faults can slow the system down both
  because of the time-costly process of fetching data from disk and because it
  demands more kernel resources to locate the missing page, which puts other
  processes on hold.

  ## Resources

  [Virtual memory](9_VirtualMemory.html#:~:text=Virtual%20memory%20also%20allows%20the,to%20more%20than%20one%20process)


path: zk/Virtual_private_cloud.md
sortable_path: zkVirtual_private_cloud.md
title: Virtual Private Cloud
lead: # Virtual Private Cloud
checksum: 15665690b24aff7e50083932162a8fb8e22aa4065f512ff3495b497587d4bca4
created: 2024-06-16 17:37:32.272794495+00:00
modified: 2024-03-27 10:45:52.510192133+00:00
body:
  # Virtual Private Cloud

  AWS VPC is used to create a virtual network. This is typically used in concert
  with [[zk/Elastic_Compute_Cloud]] to manage connections to a virtual server both
  privately and accross the internet.

  You define a network address range and then create subnets for managing
  different connections and functionality. You use a public subnet for resources
  that must be connected to the internet and a private subnet for resources that
  are to remain isolated from the internet.

  The diagram below details a basic VPC configuration:

  ![](../img/aws-vpc-example.png)

  - Within a given AWS region we have created a VPC network.
  - This comprises public and private subnets
  - Both subnets host an EC2 instance
  - The public subnet has a bridge to the internet through the Internet Gateway
  - Both subnets have a routing table to manage requests and access

raw_content:
  ---
  id: mdw5fe5a
  title: Virtual Private Cloud
  tags: [AWS, networks]
  created: Tuesday, February 20, 2024 | 08:31
  ---

  # Virtual Private Cloud

  AWS VPC is used to create a virtual network. This is typically used in concert
  with [[zk/Elastic_Compute_Cloud]] to manage connections to a virtual server both
  privately and accross the internet.

  You define a network address range and then create subnets for managing
  different connections and functionality. You use a public subnet for resources
  that must be connected to the internet and a private subnet for resources that
  are to remain isolated from the internet.

  The diagram below details a basic VPC configuration:

  ![](../img/aws-vpc-example.png)

  - Within a given AWS region we have created a VPC network.
  - This comprises public and private subnets
  - Both subnets host an EC2 instance
  - The public subnet has a bridge to the internet through the Internet Gateway
  - Both subnets have a routing table to manage requests and access

metadata:
  {"created":"Tuesday, February 20, 2024 | 08:31","id":"mdw5fe5a","tags":["AWS","networks"],"title":"Virtual Private Cloud"}


path: zk/http_in_Node.md
sortable_path: zkhttp_in_Node.md
title: http module
checksum: d74610fc301d67759fe76291d7e99eda1b918720fe38a694e5d28775c0b7ee25
created: 2024-06-16 17:37:32.313365813+00:00
modified: 2024-06-15 09:50:58.8172+00:00
metadata: {"tags":["node-js"]}
lead:
  The HTTP Module allows us to create a web server that listens for HTTP requests
  on a given port. It is therefore perfect for creating backends for client-side
  JavaScript.

body:
  The HTTP Module allows us to create a web server that listens for HTTP requests
  on a given port. It is therefore perfect for creating backends for client-side
  JavaScript.

  ## Creating a server

  An HTTP server is another instance of an
  [event emitter](events.md)). It
  therefore has all the same methods as the `EventEmitter` class: `on`, `emit`,
  `addListener` etc. This demonstrates again how much of Node's core functionality
  is based on event emitters.

  _Creating a server_

  ```js
  const http = require("http");

  const server = http.createServer(); // Create server as emitter

  // Register functions to run when listener is triggered
  server.on("connection", (socket) => {
    console.log("new connection...");
  });

  server.listen(3000);
  console.log("Listening on port 3000");
  ```

  This server is functionally equivalent to a generic event emitter:

  ```js
  // Raise an event
  const emitter = new EventEmitter("messageLogged");

  // Register a listener
  emitter.on("messagedLogged", function () {
    console.log("The listener was called.");
  });
  ```

  Whenever a request is made to this server, it raises an event. We can therefore
  target it with the `on` method and make it execute a function when requests are
  made.

  If we were to start the server by running the file and we then used a browser to
  navigate to the port, we would see `new connection` logged every time we refresh
  the page.

  ### Sockets and `req, res`

  A socket is a generic protocol for client-server communication. Crucially it
  **allows simultaneous communication both ways**. The client can contact the
  server but the server can also contact the client. Our listener function above
  uses a socket as the callback function but in most cases this is quite
  low-level, not distinguishing responses from requests. It is more likely that
  you would initiate a `request, resource` architecture in place of a socket:

  ```js
  const server = http.createServer((req, res) => {
    if (req.url === "/") {
      res.write("hello");
      res.end();
    }
  });
  ```

  #### Return JSON

  Below is an example of using this architecture to return JSON to the client:

  ```js
  const server = http.createServer((req, res) => {
    if (req.url === "/products") {
      res.write(JSON.stringify(["shoes", "lipstick", "cups"]));
      res.end();
    }
  });
  ```

  ### Express

  In reality you would rarely use the `http` module directly to create a server.
  This is because it is quite low level and each response must be written in a
  linear fashion as with the two URLs in the previous example. Instead we use
  Express which is a framework for creating servers and routing that is an
  abstraction on top of the core HTTP module.

raw_content:
  ---
  tags:
    - node-js
  ---

  # `http` module

  The HTTP Module allows us to create a web server that listens for HTTP requests
  on a given port. It is therefore perfect for creating backends for client-side
  JavaScript.

  ## Creating a server

  An HTTP server is another instance of an
  [event emitter](events.md)). It
  therefore has all the same methods as the `EventEmitter` class: `on`, `emit`,
  `addListener` etc. This demonstrates again how much of Node's core functionality
  is based on event emitters.

  _Creating a server_

  ```js
  const http = require("http");

  const server = http.createServer(); // Create server as emitter

  // Register functions to run when listener is triggered
  server.on("connection", (socket) => {
    console.log("new connection...");
  });

  server.listen(3000);
  console.log("Listening on port 3000");
  ```

  This server is functionally equivalent to a generic event emitter:

  ```js
  // Raise an event
  const emitter = new EventEmitter("messageLogged");

  // Register a listener
  emitter.on("messagedLogged", function () {
    console.log("The listener was called.");
  });
  ```

  Whenever a request is made to this server, it raises an event. We can therefore
  target it with the `on` method and make it execute a function when requests are
  made.

  If we were to start the server by running the file and we then used a browser to
  navigate to the port, we would see `new connection` logged every time we refresh
  the page.

  ### Sockets and `req, res`

  A socket is a generic protocol for client-server communication. Crucially it
  **allows simultaneous communication both ways**. The client can contact the
  server but the server can also contact the client. Our listener function above
  uses a socket as the callback function but in most cases this is quite
  low-level, not distinguishing responses from requests. It is more likely that
  you would initiate a `request, resource` architecture in place of a socket:

  ```js
  const server = http.createServer((req, res) => {
    if (req.url === "/") {
      res.write("hello");
      res.end();
    }
  });
  ```

  #### Return JSON

  Below is an example of using this architecture to return JSON to the client:

  ```js
  const server = http.createServer((req, res) => {
    if (req.url === "/products") {
      res.write(JSON.stringify(["shoes", "lipstick", "cups"]));
      res.end();
    }
  });
  ```

  ### Express

  In reality you would rarely use the `http` module directly to create a server.
  This is because it is quite low level and each response must be written in a
  linear fashion as with the two URLs in the previous example. Instead we use
  Express which is a framework for creating servers and routing that is an
  abstraction on top of the core HTTP module.


path: zk/Network_debugging.md
sortable_path: zkNetwork_debugging.md
title: Network debugging
lead: # Network debugging
body:
  # Network debugging

  ## Related notes

  ![Network scanning](Network_scanning.md)

checksum: c9c358edc6e51a8d38781b824600abdf15dcc85e98385bfaf50fd1264927c2b1
created: 2024-06-17 19:00:36.317063339+00:00
modified: 2024-06-17 18:57:53.073398693+00:00
raw_content:
  ---
  id: x44w
  title: Network debugging
  tags: [procedural, Linux, networks]
  created: Monday, June 17, 2024
  ---

  # Network debugging

  ## Related notes

  ![Network scanning](Network_scanning.md)

metadata:
  {"created":"Monday, June 17, 2024","id":"x44w","tags":["procedural","Linux","networks"],"title":"Network debugging"}


path: zk/Network debugging.md
sortable_path: zkNetwork debugging.md
title: Network debugging
lead: # Network debugging
checksum: a8dee7b683041f9119953bb6a3356cf170d05e27e4e02b58e8a1cb3a7e8f9726
created: 2024-06-18 06:43:30.382978733+00:00
modified: 2024-06-17 19:33:19.773645673+00:00
body:
  # Network debugging

  ### For DNS resolution problems

  ```sh
  sudo systemctl restart resolvd

  ```

  ## Related notes

  ![Network scanning](Network_scanning.md)

raw_content:
  ---
  id: x44w
  title: Network debugging
  tags: [procedural, Linux, networks]
  created: Monday, June 17, 2024
  ---

  # Network debugging

  ### For DNS resolution problems

  ```sh
  sudo systemctl restart resolvd

  ```

  ## Related notes

  ![Network scanning](Network_scanning.md)

metadata:
  {"created":"Monday, June 17, 2024","id":"x44w","tags":["procedural","Linux","networks"],"title":"Network debugging"}


path: zk/Passing_arguments_to_Python_scripts.md
sortable_path: zkPassing_arguments_to_Python_scripts.md
title: Passing arguments to Python scripts
lead: # Passing arguments to Python scripts
checksum: 5e1ef301b1aa124717c0ce90a1868111cc2b7e21fab8d21ef063d144db35393b
created: 2024-06-19 16:57:35.57855372+00:00
modified: 2024-06-19 06:39:17.552249291+00:00
body:
  # Passing arguments to Python scripts

  `sys.argv` is a list that contains the command-line arguments passed to a Python
  scripts.

  - `sys.argv[0]` = the name of script
  - `sys.argv[1]` = the first argument
  - `sys.argv[2]` = the second argument, and so on

  Example invocation:

  ```sh
  python3 ./my_script.py argument_one argument_two

  ```

  ```python
  import sys

  print(sys.argv[0])
  print(sys.arg)
  print(sys.argv[1])

  # my_script.py
  # ['my_script.py', 'argyment_one', 'argument_two']
  # argument_one

  ```

raw_content:
  ---
  id: 44li
  title: Passing arguments to Python scripts
  tags: [python]
  created: Wednesday, June 19, 2024
  ---

  # Passing arguments to Python scripts

  `sys.argv` is a list that contains the command-line arguments passed to a Python
  scripts.

  - `sys.argv[0]` = the name of script
  - `sys.argv[1]` = the first argument
  - `sys.argv[2]` = the second argument, and so on

  Example invocation:

  ```sh
  python3 ./my_script.py argument_one argument_two

  ```

  ```python
  import sys

  print(sys.argv[0])
  print(sys.arg)
  print(sys.argv[1])

  # my_script.py
  # ['my_script.py', 'argyment_one', 'argument_two']
  # argument_one

  ```

metadata:
  {"created":"Wednesday, June 19, 2024","id":"44li","tags":["python"],"title":"Passing arguments to Python scripts"}


path: zk/Basic_model_of_the_operating_system.md
sortable_path: zkBasic_model_of_the_operating_system.md
title: Basic model of a \*nix operating system
lead:
  We can abstract the Linux OS into three operational levels or tiers, from the
  bottom up:

checksum: dfb38c057bcf8539f456c07f4dd14520aefe0b7b784f83b6ce6f447360fe0485
created: 2024-06-21 05:06:21.717225019+00:00
modified: 2024-06-15 10:20:39.952342362+00:00
metadata: {"tags":["operating-systems","Linux"]}
body:
  We can abstract the Linux OS into three operational levels or tiers, from the
  bottom up:

  <dl>
  <dt>User processes: user space</dt>
  <dd>The running programs that the kernel manages. Also known as the user space which is the memory that the kernal assigns for user processes. Comprising:
  <ul>
      <li>Graphical user interface</li>
      <li>Servers</li> 
      <li>Shell</li>    
    </ul>
  <dt>Kernel: kernel space</dt>
  </dd>
  <dd>The core of the operating system. Software residing in memory that tells the CPU where to look for its next task. Acts as a mediator and primary interface between the hardware and the user processes. Known as kernel space: the memory that the kernel allocates for itself. Comprising:
    <ul>
      <li>System calls</li>
      <li>Process management</li> 
      <li>Memory management</li>    
      <li>Device drivers</li>    
    </ul>
  </dd>
  <dt>Hardware</dt>
  <dd>The base: one or more CPUs and RAM memory performing computations and writing to memory. Comprising:
    <ul>
      <li>Processor (CPU)</li>
      <li>Main memory (RAM)</li> 
      <li>Disks</li>    
      <li>Network ports</li>    
    </ul>
  </dl>

  !! Add info on kernel mode and user mode
  https://www.geeksforgeeks.org/user-mode-and-kernel-mode-switching/

raw_content:
  ---
  tags:
    - operating-systems
    - Linux
  ---

  # Basic model of a \*nix operating system

  We can abstract the Linux OS into three operational levels or tiers, from the
  bottom up:

  <dl>
  <dt>User processes: user space</dt>
  <dd>The running programs that the kernel manages. Also known as the user space which is the memory that the kernal assigns for user processes. Comprising:
  <ul>
      <li>Graphical user interface</li>
      <li>Servers</li> 
      <li>Shell</li>    
    </ul>
  <dt>Kernel: kernel space</dt>
  </dd>
  <dd>The core of the operating system. Software residing in memory that tells the CPU where to look for its next task. Acts as a mediator and primary interface between the hardware and the user processes. Known as kernel space: the memory that the kernel allocates for itself. Comprising:
    <ul>
      <li>System calls</li>
      <li>Process management</li> 
      <li>Memory management</li>    
      <li>Device drivers</li>    
    </ul>
  </dd>
  <dt>Hardware</dt>
  <dd>The base: one or more CPUs and RAM memory performing computations and writing to memory. Comprising:
    <ul>
      <li>Processor (CPU)</li>
      <li>Main memory (RAM)</li> 
      <li>Disks</li>    
      <li>Network ports</li>    
    </ul>
  </dl>

  !! Add info on kernel mode and user mode
  https://www.geeksforgeeks.org/user-mode-and-kernel-mode-switching/


path: zk/ps.md
sortable_path: zkps.md
title: Processes (ps)
lead:
  `ps` allows us to control [user processes](The_kernel.md)
  from the shell.

checksum: db2045cff446875dd957c96c1b0b2dcaf4c16fed9ceb7c1f0f91146ea1f07297
created: 2024-06-21 05:23:32.570424822+00:00
modified: 2024-06-16 17:26:03.906136212+00:00
metadata: {"tags":["shell","Linux"]}
body:
  `ps` allows us to control [user processes](The_kernel.md)
  from the shell.

  The command in its most minimal application returns the following

  ```
    PID TTY       TIME     CMD
    2437 pts/2    00:00:01 zsh
    7112 pts/2    00:00:00 ps
  ```

  With the `-e` modifier we can list more processes:

  ```
   PID TTY          TIME CMD
        1 ?        00:00:05 systemd
        2 ?        00:00:00 kthreadd
        3 ?        00:00:00 rcu_gp
        4 ?        00:00:00 rcu_par_gp
        5 ?        00:00:00 netns
        7 ?        00:00:00 kworker/0:0H-events_highpri
        9 ?        00:00:00 mm_percpu_wq
       11 ?        00:00:00 rcu_tasks_kthread
       12 ?        00:00:00 rcu_tasks_rude_kthread
       13 ?        00:00:00 rcu_tasks_trace_kthread
       14 ?        00:00:08 ksoftirqd/0
       15 ?        00:03:20 rcu_preempt
       16 ?        00:00:00 rcub/0
       17 ?        00:00:00 migration/0
       18 ?        00:00:00 idle_inject/0
       20 ?        00:00:00 cpuhp/0
       21 ?        00:00:00 cpuhp/1
       22 ?        00:00:00 idle_inject/1
       23 ?        00:00:00 migration/1
  ```

  <dl>
  <dt>pid</dt>
  <dd>Process ID: every currently running process has a unique ID<dd>
  <dt>tty</dt>
  <dd>The terminal device where the process is running<dd>
  <dt>Time</dt>
  <dd>The amount of CPU time in minutes and seconds that the process has used so far. The total amount of time that the process has spent running instructions on the processor.<dd>
  <dt>cmd</dt>
  <dd>The command used to run the program. Note this can change during the running of the program.<dd>
  </dl>

  ## Modifiers

  <dl>
  <dt><code>ps x</code></dt>
  <dd>Show all running processes<dd>
  <dt><code>ps ax</code></dt>
  <dd>Show all processes not just the ones you, the current user, own<dd>
  <dt><code>ps u</code></dt>
  <dd>Show detailed info on processes<dd>
  <dt><code>ps w</code></dt>
  <dd>Show full command names<dd>
  </dl>

  ## Process termination

  The general schema is: `kill [pid]`. This allows for process clean-up. If this
  doesn't succeed you can force with `KILL [pid]` which will terminate the process
  immediately but is obviously more risky.

  We can also start/stop processes with modifiers on `kill`:

  - `kill -STOP pid`
  - `kill -CONT pid`

raw_content:
  ---
  tags:
    - shell
    - Linux
  ---

  # Processes (`ps`)

  `ps` allows us to control [user processes](The_kernel.md)
  from the shell.

  The command in its most minimal application returns the following

  ```
    PID TTY       TIME     CMD
    2437 pts/2    00:00:01 zsh
    7112 pts/2    00:00:00 ps
  ```

  With the `-e` modifier we can list more processes:

  ```
   PID TTY          TIME CMD
        1 ?        00:00:05 systemd
        2 ?        00:00:00 kthreadd
        3 ?        00:00:00 rcu_gp
        4 ?        00:00:00 rcu_par_gp
        5 ?        00:00:00 netns
        7 ?        00:00:00 kworker/0:0H-events_highpri
        9 ?        00:00:00 mm_percpu_wq
       11 ?        00:00:00 rcu_tasks_kthread
       12 ?        00:00:00 rcu_tasks_rude_kthread
       13 ?        00:00:00 rcu_tasks_trace_kthread
       14 ?        00:00:08 ksoftirqd/0
       15 ?        00:03:20 rcu_preempt
       16 ?        00:00:00 rcub/0
       17 ?        00:00:00 migration/0
       18 ?        00:00:00 idle_inject/0
       20 ?        00:00:00 cpuhp/0
       21 ?        00:00:00 cpuhp/1
       22 ?        00:00:00 idle_inject/1
       23 ?        00:00:00 migration/1
  ```

  <dl>
  <dt>pid</dt>
  <dd>Process ID: every currently running process has a unique ID<dd>
  <dt>tty</dt>
  <dd>The terminal device where the process is running<dd>
  <dt>Time</dt>
  <dd>The amount of CPU time in minutes and seconds that the process has used so far. The total amount of time that the process has spent running instructions on the processor.<dd>
  <dt>cmd</dt>
  <dd>The command used to run the program. Note this can change during the running of the program.<dd>
  </dl>

  ## Modifiers

  <dl>
  <dt><code>ps x</code></dt>
  <dd>Show all running processes<dd>
  <dt><code>ps ax</code></dt>
  <dd>Show all processes not just the ones you, the current user, own<dd>
  <dt><code>ps u</code></dt>
  <dd>Show detailed info on processes<dd>
  <dt><code>ps w</code></dt>
  <dd>Show full command names<dd>
  </dl>

  ## Process termination

  The general schema is: `kill [pid]`. This allows for process clean-up. If this
  doesn't succeed you can force with `KILL [pid]` which will terminate the process
  immediately but is obviously more risky.

  We can also start/stop processes with modifiers on `kill`:

  - `kill -STOP pid`
  - `kill -CONT pid`


path: zk/Processes.md
sortable_path: zkProcesses.md
title: Processes
lead: # Processes and threads
checksum: 3097915bed806668396a5033b0062dbdc7822902d2e0343b2e6fc07cef6ea078
created: 2024-06-21 05:23:32.592788276+00:00
modified: 2024-06-21 06:13:35.323959189+00:00
metadata: {"created":"Friday, June 21, 2024","id":"t70u","tags":["operating-systems"],"title":"Processes"}
body:
  # Processes and threads

  Programs are sequences of machine instructions stored in a file. However they do
  not work by themselves. Something needs to load the file's intructions into
  memory and direct the CPU to run the program. The OS does this via processes.

  A process **is a running instance of a given program**. It can be thought of as
  a container in which a program runs. This container includes:

  - a copy of the program code loaded into memory
  - a memory address
  - other information about the state of the process

  Other than the `init` process started by the kernel (PID1), every process has a
  parent process that started it. This parent-child relationship creates a tree of
  processes.

  It is possible that a parent process will terminate before one of its child
  processes. In this instance the child becomes an orphan. When this occurs in
  #Linux, the orphan process is adopted by `init`.

  Below, I have used the `pstree` utility to list all the running processes on my
  machine hierarchically.

  ![diagram of `pstree` output](../img/ps-tree.png)

  Children are represented vertically and horizontally.

  ```
  ├─terminator─┬─zsh───tmux: client
  │            ├─zsh───pstree
  │            └─6*[{terminator}]

  ```

  For instance here, `terminator` is a child of `init`, as are `zsh` and `tmux`
  but they are also children of `terminator`.`pstree` is a child of `zsh` and
  therefore also a child (grandchild) of `terminator`.

  ## Related notes

  ![systemd](./systemd.md)

  ![ps](./ps.md)

raw_content:
  ---
  id: t70u
  title: Processes
  tags: [operating-systems]
  created: Friday, June 21, 2024
  ---

  # Processes and threads

  Programs are sequences of machine instructions stored in a file. However they do
  not work by themselves. Something needs to load the file's intructions into
  memory and direct the CPU to run the program. The OS does this via processes.

  A process **is a running instance of a given program**. It can be thought of as
  a container in which a program runs. This container includes:

  - a copy of the program code loaded into memory
  - a memory address
  - other information about the state of the process

  Other than the `init` process started by the kernel (PID1), every process has a
  parent process that started it. This parent-child relationship creates a tree of
  processes.

  It is possible that a parent process will terminate before one of its child
  processes. In this instance the child becomes an orphan. When this occurs in
  #Linux, the orphan process is adopted by `init`.

  Below, I have used the `pstree` utility to list all the running processes on my
  machine hierarchically.

  ![diagram of `pstree` output](../img/ps-tree.png)

  Children are represented vertically and horizontally.

  ```
  ├─terminator─┬─zsh───tmux: client
  │            ├─zsh───pstree
  │            └─6*[{terminator}]

  ```

  For instance here, `terminator` is a child of `init`, as are `zsh` and `tmux`
  but they are also children of `terminator`.`pstree` is a child of `zsh` and
  therefore also a child (grandchild) of `terminator`.

  ## Related notes

  ![systemd](./systemd.md)

  ![ps](./ps.md)


path: zk/DynamoDB_data_structure.md
sortable_path: zkDynamoDB_data_structure.md
title: DynamoDB
lead: # DynamoDB
checksum: b845f451ebb9f0ddb43aa8046e9bfd71b87046576647b64f257d216ae09b4c75
created: 2024-06-22 09:38:00.123616477+00:00
modified: 2024-06-21 06:28:08.053871627+00:00
body:
  # DynamoDB

  ## Data structure

  ### Non-relational tables

  DynamoDB is "NoSQL" because it does not support #SQL queries and is
  non-relational meaning there cannot be JOIN operations via
  [foreign_keys](Foreign_keys_in_SQL.md)

  ![](../img/dynamodb.png)

  ### Primary key

  Although the data is stored as a table, one of the attributes is a primary key
  and the rest of the attributes are effectively the "value" associated with it.

  Because DynamoDB is schemaless, other than the primary key, neither the
  attributes or their data types need to be defined beforehand and each item can
  have its own distinct attributes.

  Each item in the table is uniquely identifiable by its primary key.

  There are two types of primary key available:

  - partition key: a simple primary key composed of one attribute only. Because
    the primary key is hash-mapped items can be retrieved very rapidly using the
    primary key. This would be the `personId` alone.

  - composite key: this comprises a partition key and a _sort key_ both of which
    are attributes. In a table that has a partition key and a sort key, it's
    possible for multiple items to have the same partition key value. However,
    those items must have different sort key values. You could then query by
    either key or both. For instance using the `PersonId` along with `LastName`

  ### Secondary index

  As well as the index provided by the primary key, you can set one or more
  **secondary indices**. A secondary index lets you query the data in the table
  using an alternate key.

  A **global secondary index** is useful for querying data that needs to be
  accessed using non-primary key attributes. For example, if you have a Users
  table with `UserID` as the primary key but often need to fetch users by their
  `Email`, a GSI on `Email` would be appropriate.

  There are also **local secondary indices** but I don't understand the
  difference.

  ## Real example

  Below is a specification of the DynamoDB table I am using for my time-entries
  project:

  ```json
  {
    "TableName": "TimeEntries",
    "KeyAttributes": {
      "PartitionKey": {
        "AttributeName": "activity_start_end",
        "AttributeType": "S"
      }
    },
    "NonKeyAttributes": [
      {
        "AttributeName": "activity_type",
        "AttributeType": "S"
      },
      {
        "AttributeName": "start",
        "AttributeType": "S"
      },
      {
        "AttributeName": "end",
        "AttributeType": "S"
      },
      {
        "AttributeName": "duration",
        "AttributeType": "N"
      },
      {
        "AttributeName": "description",
        "AttributeType": "S"
      },
      {
        "AttributeName": "year",
        "AttributeType": "S"
      }
    ],
    "GlobalSecondaryIndexes": [
      {
        "IndexName": "YearIndex",
        "KeyAttributes": {
          "PartitionKey": {
            "AttributeName": "year",
            "AttributeType": "S"
          },
          "SortKey": {
            "AttributeName": "start",
            "AttributeType": "S"
          }
        },
        "Projection": {
          "ProjectionType": "ALL"
        }
      }
    ]
  }
  ```

  This defines the attribute `activity_start_end` as the primary key. This string
  (`S`) value is a concatenation of three attributes, which is a way of ensuring
  each entry for the attribute will be unique.

  The `NonKeyAttributes` are all the other attributes in addition to the primary
  key. As mentioned these do not actually need to be defined when setting up the
  table but they are listed here for clarity.

  I have also defined a GSI. This is derived from the `Year` attribute. This will
  group all the items by their `Year`, allowing me to query directly by year but
  also helping to chunk the entries which will make look-ups quicker and less
  expensive.

  ## Related notes

raw_content:
  ---
  id: xowl
  title: DynamoDB
  tags:
    - AWS
    - databases
    - dynamodb
  created: Sunday, June 09, 2024
  ---

  # DynamoDB

  ## Data structure

  ### Non-relational tables

  DynamoDB is "NoSQL" because it does not support #SQL queries and is
  non-relational meaning there cannot be JOIN operations via
  [foreign_keys](Foreign_keys_in_SQL.md)

  ![](../img/dynamodb.png)

  ### Primary key

  Although the data is stored as a table, one of the attributes is a primary key
  and the rest of the attributes are effectively the "value" associated with it.

  Because DynamoDB is schemaless, other than the primary key, neither the
  attributes or their data types need to be defined beforehand and each item can
  have its own distinct attributes.

  Each item in the table is uniquely identifiable by its primary key.

  There are two types of primary key available:

  - partition key: a simple primary key composed of one attribute only. Because
    the primary key is hash-mapped items can be retrieved very rapidly using the
    primary key. This would be the `personId` alone.

  - composite key: this comprises a partition key and a _sort key_ both of which
    are attributes. In a table that has a partition key and a sort key, it's
    possible for multiple items to have the same partition key value. However,
    those items must have different sort key values. You could then query by
    either key or both. For instance using the `PersonId` along with `LastName`

  ### Secondary index

  As well as the index provided by the primary key, you can set one or more
  **secondary indices**. A secondary index lets you query the data in the table
  using an alternate key.

  A **global secondary index** is useful for querying data that needs to be
  accessed using non-primary key attributes. For example, if you have a Users
  table with `UserID` as the primary key but often need to fetch users by their
  `Email`, a GSI on `Email` would be appropriate.

  There are also **local secondary indices** but I don't understand the
  difference.

  ## Real example

  Below is a specification of the DynamoDB table I am using for my time-entries
  project:

  ```json
  {
    "TableName": "TimeEntries",
    "KeyAttributes": {
      "PartitionKey": {
        "AttributeName": "activity_start_end",
        "AttributeType": "S"
      }
    },
    "NonKeyAttributes": [
      {
        "AttributeName": "activity_type",
        "AttributeType": "S"
      },
      {
        "AttributeName": "start",
        "AttributeType": "S"
      },
      {
        "AttributeName": "end",
        "AttributeType": "S"
      },
      {
        "AttributeName": "duration",
        "AttributeType": "N"
      },
      {
        "AttributeName": "description",
        "AttributeType": "S"
      },
      {
        "AttributeName": "year",
        "AttributeType": "S"
      }
    ],
    "GlobalSecondaryIndexes": [
      {
        "IndexName": "YearIndex",
        "KeyAttributes": {
          "PartitionKey": {
            "AttributeName": "year",
            "AttributeType": "S"
          },
          "SortKey": {
            "AttributeName": "start",
            "AttributeType": "S"
          }
        },
        "Projection": {
          "ProjectionType": "ALL"
        }
      }
    ]
  }
  ```

  This defines the attribute `activity_start_end` as the primary key. This string
  (`S`) value is a concatenation of three attributes, which is a way of ensuring
  each entry for the attribute will be unique.

  The `NonKeyAttributes` are all the other attributes in addition to the primary
  key. As mentioned these do not actually need to be defined when setting up the
  table but they are listed here for clarity.

  I have also defined a GSI. This is derived from the `Year` attribute. This will
  group all the items by their `Year`, allowing me to query directly by year but
  also helping to chunk the entries which will make look-ups quicker and less
  expensive.

  ## Related notes

metadata:
  {"created":"Sunday, June 09, 2024","id":"xowl","tags":["AWS","databases","dynamodb"],"title":"DynamoDB"}


path: zk/DynamoDB_CLI_commands.md
sortable_path: zkDynamoDB_CLI_commands.md
title: DynamoDB CLI commands
lead: # DynamoDB CLI commands
checksum: 1a00b260b0e3389d043fd16674eb547ec691c4d7f33d0b966b93c86b632bda4b
created: 2024-06-23 18:20:42.429528536+00:00
modified: 2024-06-23 18:02:16.326234491+00:00
body:
  # DynamoDB CLI commands

  ## Connecting to a local (Docker)/prod (AWS) DynamoDB instance

  In order to distinguish between local and production accounts you should keep
  seperate profiles for each (via `.aws/config` and `.aws/credentials`).

  When connecting to a local DB use the local profile and the local URL. Without
  the `--profile` flag, AWS will default to the `default` profile which will
  typically be your credentials for accessing AWS on the remote.

  It also sometimes required to add the endpoint-url when working locally:

  ```
  --endpoint-url http://localhost:800

  > When using the commans below locally, assume `--endpoint-url` and `--profile`
  > have been appended

  ```

  For example:

  ```sh
  aws dynamodb list-tables \
  --profile timetracking_dev \
  --endpoint-url http://localhost:800
  ```

  ## Delete a table

  ```sh
  aws dynamodb delete-table \
  --table-name TableName
  ```

  ## Create table from JSON schema

  ```sh
  aws dynamodb create-table \
  --cli-input-json file://create-timeentries-table.json \

  ```

  ## Describe the table

  View the table schema:

  ```sh

  aws dynamodb describe-table \
  --table-name TimeEntries
  ```

  ## Scan the table

  ```sh
  aws dynamodb scan \
  --table-name TimeEntries \
  --output table
  ```

  ## Related notes

raw_content:
  ---
  id: l045
  title: DynamoDB CLI commands
  tags: [AWS, databases, dynamodb]
  created: Saturday, June 22, 2024
  ---

  # DynamoDB CLI commands

  ## Connecting to a local (Docker)/prod (AWS) DynamoDB instance

  In order to distinguish between local and production accounts you should keep
  seperate profiles for each (via `.aws/config` and `.aws/credentials`).

  When connecting to a local DB use the local profile and the local URL. Without
  the `--profile` flag, AWS will default to the `default` profile which will
  typically be your credentials for accessing AWS on the remote.

  It also sometimes required to add the endpoint-url when working locally:

  ```
  --endpoint-url http://localhost:800

  > When using the commans below locally, assume `--endpoint-url` and `--profile`
  > have been appended

  ```

  For example:

  ```sh
  aws dynamodb list-tables \
  --profile timetracking_dev \
  --endpoint-url http://localhost:800
  ```

  ## Delete a table

  ```sh
  aws dynamodb delete-table \
  --table-name TableName
  ```

  ## Create table from JSON schema

  ```sh
  aws dynamodb create-table \
  --cli-input-json file://create-timeentries-table.json \

  ```

  ## Describe the table

  View the table schema:

  ```sh

  aws dynamodb describe-table \
  --table-name TimeEntries
  ```

  ## Scan the table

  ```sh
  aws dynamodb scan \
  --table-name TimeEntries \
  --output table
  ```

  ## Related notes

metadata:
  {"created":"Saturday, June 22, 2024","id":"l045","tags":["AWS","databases","dynamodb"],"title":"DynamoDB CLI commands"}


path: zk/DynamoDB_SDK_commands.md
sortable_path: zkDynamoDB_SDK_commands.md
title: DynamoDB SDK commands
lead: # DynamoDB SDK commands
checksum: 2e375094fdb1f167a15e1dbcfc55f5e2653f990ea82816debc3ad47839ed09fe
created: 2024-06-23 18:20:42.435974932+00:00
modified: 2024-06-23 18:09:03.599881207+00:00
body:
  # DynamoDB SDK commands

  The following commands are for using `@aws-sdk/client-dynamodb` (the JS SDK).

  ## Create client

  ```js
  import DynamoDBClient from "@aws-sdk/client-dynamodb";

  const client = new DynamoDBClient({
    region: "eu-west-2",
    accessKeyId: process.env.ACCESS_KEY_ID,
    secretAccessKey: process.env.ACCESS_KEY_ID,
  });
  ```

  ### DynamoDB Document Client

  The Document Client returns the data as a standard JSON document in the manner
  of a document-based NoSQL database. Without it, DynamoDB will return the data
  with type data which is unwieldy and hard to parse.

  To transform into a document structure:

  ```js
  import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
  import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";

  const client = new DynamoDBClient({
    region: "eu-west-2",
    accessKeyId: process.env.ACCESS_KEY_ID,
    secretAccessKey: process.env.ACCESS_KEY_ID,
  });

  const dynamoDbDocumentClient = DynamoDBDocumentClient.from(client);
  ```

  ## Query a table

  Querying is the most performant and cost-effective method since it is an O(1)
  lookup against a partition key or secondary index.

  ```js
  import { DynamoDBDocumentClient, QueryCommand } from "@aws-sdk/lib-dynamodb";

  const params = {
    TableName: "YourTableName",
    KeyConditionExpression: "#pk = :pk",
    ExpressionAttributeNames: { "#pk": "PrimaryKeyAttributeName" },
    ExpressionAttributeValues: { ":pk": "PrimaryKeyValue" },
  };

  const dynamoDbDocumentClient = DynamoDBDocumentClient.from(client);
  const data = await dynamoDbDocumentClient.send(new QueryCommand(params));
  console.log(data);
  ```

  ## Scan a table

  Scanning is less performant (O(n)) and most expensive since it requires checking
  every item in the database.

  ```js
  import { DynamoDBDocumentClient, ScanCommand } from "@aws-sdk/lib-dynamodb";

  const params = {
    TableName: "YourTableName",
  };

  const dynamoDbDocumentClient = DynamoDBDocumentClient.from(client);
  const data = await dynamoDbDocumentClient.send(new ScanCommand(params));
  ```

  ## Related notes

raw_content:
  ---
  id: 8b6h
  title: DynamoDB SDK commands
  tags: [AWS, databases, dynamodb]
  created: Sunday, June 23, 2024
  ---

  # DynamoDB SDK commands

  The following commands are for using `@aws-sdk/client-dynamodb` (the JS SDK).

  ## Create client

  ```js
  import DynamoDBClient from "@aws-sdk/client-dynamodb";

  const client = new DynamoDBClient({
    region: "eu-west-2",
    accessKeyId: process.env.ACCESS_KEY_ID,
    secretAccessKey: process.env.ACCESS_KEY_ID,
  });
  ```

  ### DynamoDB Document Client

  The Document Client returns the data as a standard JSON document in the manner
  of a document-based NoSQL database. Without it, DynamoDB will return the data
  with type data which is unwieldy and hard to parse.

  To transform into a document structure:

  ```js
  import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
  import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";

  const client = new DynamoDBClient({
    region: "eu-west-2",
    accessKeyId: process.env.ACCESS_KEY_ID,
    secretAccessKey: process.env.ACCESS_KEY_ID,
  });

  const dynamoDbDocumentClient = DynamoDBDocumentClient.from(client);
  ```

  ## Query a table

  Querying is the most performant and cost-effective method since it is an O(1)
  lookup against a partition key or secondary index.

  ```js
  import { DynamoDBDocumentClient, QueryCommand } from "@aws-sdk/lib-dynamodb";

  const params = {
    TableName: "YourTableName",
    KeyConditionExpression: "#pk = :pk",
    ExpressionAttributeNames: { "#pk": "PrimaryKeyAttributeName" },
    ExpressionAttributeValues: { ":pk": "PrimaryKeyValue" },
  };

  const dynamoDbDocumentClient = DynamoDBDocumentClient.from(client);
  const data = await dynamoDbDocumentClient.send(new QueryCommand(params));
  console.log(data);
  ```

  ## Scan a table

  Scanning is less performant (O(n)) and most expensive since it requires checking
  every item in the database.

  ```js
  import { DynamoDBDocumentClient, ScanCommand } from "@aws-sdk/lib-dynamodb";

  const params = {
    TableName: "YourTableName",
  };

  const dynamoDbDocumentClient = DynamoDBDocumentClient.from(client);
  const data = await dynamoDbDocumentClient.send(new ScanCommand(params));
  ```

  ## Related notes

metadata:
  {"created":"Sunday, June 23, 2024","id":"8b6h","tags":["AWS","databases","dynamodb"],"title":"DynamoDB SDK commands"}


path: zk/Breadboards.md
sortable_path: zkBreadboards.md
title: Breadboards
lead: # Breadboards
checksum: 142319a38c2ea868a8601e38f2b42f277f0c6aaa36b9070b4e500f63be30fb12
created: 2024-06-23 18:20:42.444058773+00:00
modified: 2024-06-24 05:23:27.988532764+00:00
metadata: {"created":"Sunday, June 23, 2024","id":"jbf1","tags":["electronics"],"title":"Breadboards"}
body:
  # Breadboards

  ![](../img/breadboard-diagram.jpg)

  ## Contact holes

  Beneath the plastic casing, the contact holes are connected to one another
  making a continuous circuit connection

  ## Terminal strips

  The contact holes in the middle section, arranged in groups of five and
  designated by letters

  The terminal strips are not connected accross the ditch thus each of the two
  strips are electrically separate regions (A-E and F-J).

  ## Bus strips

  The contact holes on the outer edges of the breadboard, designated by numbers
  (1-30). The chief role of the bus strips is to manage the power to the circuit.
  You will typically use the positive bus strip on one side for the voltage source
  and the negative bus strip on the other side for the ground outlet.

  ## Related notes

raw_content:
  ---
  id: jbf1
  title: Breadboards
  tags: [electronics]
  created: Sunday, June 23, 2024
  ---

  # Breadboards

  ![](../img/breadboard-diagram.jpg)

  ## Contact holes

  Beneath the plastic casing, the contact holes are connected to one another
  making a continuous circuit connection

  ## Terminal strips

  The contact holes in the middle section, arranged in groups of five and
  designated by letters

  The terminal strips are not connected accross the ditch thus each of the two
  strips are electrically separate regions (A-E and F-J).

  ## Bus strips

  The contact holes on the outer edges of the breadboard, designated by numbers
  (1-30). The chief role of the bus strips is to manage the power to the circuit.
  You will typically use the positive bus strip on one side for the voltage source
  and the negative bus strip on the other side for the ground outlet.

  ## Related notes


path: zk/ROM versus disk loading.md
sortable_path: zkROM versus disk loading.md
title: ROM versus disk loading
lead: # ROM versus disk loading
checksum: 477d6de8d99f3fb26277cc5fe6d64cc8b3071b4eb7e53c51f593ba53d9887a0e
created: 2024-06-24 16:30:55.619239265+00:00
modified: 2024-06-24 16:42:46.898181187+00:00
body:
  # ROM versus disk loading

  I will explore the concept via the practical examples of cartridge-based and
  disk-based video games console.

  When you insert a disk into an XBox, the game data is transferred from the disk
  into the console's memory by the OS. When you insert a cartridge into a SNES,
  there is no transferral of data. The game data is stored on a chip and this chip
  is attached to the motherboard. From the point of view of the OS, it is just
  another chip along with the others that comprise the motherboard.

  The chief advantage with a ROM game is that the latency is greatly reduced. The
  game data can be accessed as rapidly as any other data travelling along the
  busses of the motherboard. With a disk, the bytes have to be transferred in a
  buffer from the disk into a memory address and from there, accessed by the CPU.

  With a ROM, the console CPU still uses its own memory to run the game (as with
  disk-based consoles), it is just that the game data on the ROM can be loaded
  into memory quicker because it is attached to the motherboard.

  becomes part of the motherboard just like the other chips that comprise the
  motherboard.

  ## Related notes

raw_content:
  ---
  id: rmvm
  title: ROM versus disk loading
  tags: [computer-architecture, memory]
  created: Monday, June 24, 2024
  ---

  # ROM versus disk loading

  I will explore the concept via the practical examples of cartridge-based and
  disk-based video games console.

  When you insert a disk into an XBox, the game data is transferred from the disk
  into the console's memory by the OS. When you insert a cartridge into a SNES,
  there is no transferral of data. The game data is stored on a chip and this chip
  is attached to the motherboard. From the point of view of the OS, it is just
  another chip along with the others that comprise the motherboard.

  The chief advantage with a ROM game is that the latency is greatly reduced. The
  game data can be accessed as rapidly as any other data travelling along the
  busses of the motherboard. With a disk, the bytes have to be transferred in a
  buffer from the disk into a memory address and from there, accessed by the CPU.

  With a ROM, the console CPU still uses its own memory to run the game (as with
  disk-based consoles), it is just that the game data on the ROM can be loaded
  into memory quicker because it is attached to the motherboard.

  becomes part of the motherboard just like the other chips that comprise the
  motherboard.

  ## Related notes

metadata:
  {"created":"Monday, June 24, 2024","id":"rmvm","tags":["computer-architecture","memory"],"title":"ROM versus disk loading"}


# links

title: using API Gateway as Lambda trigger
href: zk/Practical_walkthrough_Lambda_creation_within_AWS.md
type: markdown
snippet:
  See
  [using API Gateway as Lambda trigger](Practical_walkthrough_Lambda_creation_within_AWS.md)
  for a basic example of usage.


title: Fetch from Secrets Manager
href: zk/Fetch_from_Secrets_Manager.md
type: markdown
snippet:
  See
  [Fetch from Secrets Manager](Fetch_from_Secrets_Manager.md)
  for a code example of retrieving a value from Secrets Manager.


title: factors and divisors
href: zk/Factors_and_divisors.md
type: markdown
snippet:
  Given the symmetry between
  [factors and divisors](Factors_and_divisors.md) these
  properties are related. Note however that the LCM is more generic: it applies to
  any set of numbers not just fractions. Whereas the LCD is explicitly to do with
  fractions (hence 'denominator').


title: increase the complexity
href: zk/Why_computers_use_binary.md#from-circuits-to-programs
type: markdown
snippet:
  Although a digital system could use more than two symbols, adding more would
  [increase the complexity](Why_computers_use_binary.md#from-circuits-to-programs)
  and cost of the system. A set of only two symbols allows for simplified hardware
  and improved reliability.


title: schema
href: zk/Apollo_Server.md#example-schema
type: markdown
snippet:
  We will be working with the
  > [schema](Apollo_Server.md#example-schema) we defined
  > when working on the server


title: resolver
href: zk/Apollo_Server.md#implementing-resolvers
type: markdown
snippet:
  Therefore, for each query in the schema we must write a frontend implementation.
  We do this with **query constants**. The frontend implementation has a backend
  analogue: the
  [resolver](Apollo_Server.md#implementing-resolvers)
  that is invoked when the frontend issues a query. The schema standardises this
  relationship so that every query on the client must have a corresponding
  resolver on the backend.


title: Routing
href: zk/Routing.md
type: markdown
snippet:
  If you are using React Router `App` becomes the index for the different page
    components. See [Routing](Routing.md) for more detail.


title: logic gates
href: zk/Logic_gates.md
type: markdown
snippet:
  The ALU comprises
  [logic gates](Logic_gates.md) that
  execute the instructions passed from memory and where the data stored by the
  registers is acted upon. A processor's ALU is just a complex combinatorial logic
  circuit.


title: full-adders and half adders
href: zk/Half_adder_and_full_adder.md
type: markdown
snippet:
  It executes arithmetic and logical operations on binary numbers and where you
  will find operations conducted by
  [full-adders and half adders](Half_adder_and_full_adder.md)
  etc.


title: fetch, decode, execute cycle
href: zk/Fetch_decode_execute.md
type: markdown
snippet:
  More specifically, the ALU is responsible for the _execute_ phase of the
  [fetch, decode, execute cycle](Fetch_decode_execute.md).


title: Basic properties of sets
href: zk/Basic properties of sets.md
type: markdown
snippet:
  The basic notions of set theory are defined in
  [Basic properties of sets](Basic%20properties%20of%20sets.md). There we
  introduced a formal syntax that will be utilised to define the axioms. For easy
  reference:


title: hexadecimal
href: zk/Hexadecimal_number_system.md
type: markdown
snippet:
  To distinguish numbers in binary from decimal or
  [hexadecimal](Hexadecimal_number_system.md)
  numbers, it is common to use the prefix `0b`. Thus, e.g, `0b110` for decimal
  `6`.


title: binary number system
href: zk/Binary_number_system.md
type: markdown
snippet:
  The equivalent entity in the
  [binary number system](Binary_number_system.md)
  is the **bit**. For example the binary number 110 has three bits. A bit can only
  have one of two values in contrast to a digit which can have one of ten values.
  These values are 0 and 1.


title: standard metric prefixes
href: zk/Prefixes_for_units_of_electrical_measurement.md
type: markdown
snippet:
  Having established that the core quantity of information is the byte, the
  convention is to apply the
  [standard metric prefixes](Prefixes_for_units_of_electrical_measurement.md)
  to the byte to establish units:


title: electrical field
href: zk/Voltage.md#distinguishing-voltage-from-electric-field
type: markdown
snippet:
  In this configuration the same current flows through all the cells; it is not
  cumulative. We represent this as follow> However the voltage is cumulative: it
  is the _sum_ of the individual cell voltages, represented below as
  [electrical field](Voltage.md#distinguishing-voltage-from-electric-field):


title: remote tracking branch
href: zk/Remote_tracking_branches.md
type: markdown
snippet:
  You don't have to just cherry-pick locally, you can also cherry-pick from a
    [remote tracking branch](Remote_tracking_branches.md).


title: copying functions
href: zk/Functions_in_Python.md
type: markdown
snippet:
  The same principle that applies to
  [copying functions](Functions_in_Python.md)
  applies to copying objects created through classes: redeclaration results in a
  duplicate entity. Thus changes to the duplicate will affect the original.


title: reciprocol
href: zk/Reciprocals.md
type: markdown
snippet:
  We combine the foregoing (that it is easier to divide by fractional amounts
  using multiplication) with the concept of a [reciprocol](Reciprocals.md) to
  arrive at a definitive method for dividing two fractions. It boils down to:
  _invert and multiply_:


title: REST API
href: zk/RESTful_APIs.md
type: markdown
snippet:
  The Docker Client is a thin API for making
    [REST API](RESTful_APIs.md) to the Docker Server. Any CLI
    command beginning `docker...` is an API request to the server.


title: electric current
href: zk/Current.md
type: markdown
snippet:
  Magnetism is a physical property produced by the _motion_ of electric charge,
  > which of course, is the same thing as
  > [electric current](Current.md)


title: shell session
href: zk/Shell-sessions-e6dd743dec1d4fe3b1ee672c8f9731f6
type: markdown
snippet:
  Every time a
    [shell session](Shell-sessions-e6dd743dec1d4fe3b1ee672c8f9731f6)
    spawns, a process takes place to gather and compile information that should be
    available to the shell process and its child processes. It obtains the data
    for these settings from a variety of different files and settings on the
    system.


title: shell session
href: zk/Shell-sessions-e6dd743dec1d4fe3b1ee672c8f9731f6
type: markdown
snippet:
  You can also add variables to config files that run on login such as your user
  `.bashrc` / `.zshrc` . This is obviously best for when you want the variables to
  persist and be accessible within every
  [shell session](Shell-sessions-e6dd743dec1d4fe3b1ee672c8f9731f6).


title: solution
href: zk/Algebra key terms.md#678811
type: markdown
snippet:
  Two equations are equivalent if they have the same
  > [solution](Algebra%20key%20terms.md#678811) set.


title: solution
href: zk/Algebra key terms.md#678811
type: markdown
snippet:
  $$ x - 4 = 3
  $$
  The [solution](Algebra%20key%20terms.md#678811) to this equation is $7$
  $$ x -
  4 (+4) = 3 (+ 4) $$


title: solution
href: zk/Algebra key terms.md#678811
type: markdown
snippet:
  $$ x + 4 = 9
  $$
  The [solution](Algebra%20key%20terms.md#678811) to this equation is $5$.
  $$ x +
  4 (-4) = 9(-4) $$


title: solution
href: zk/Algebra key terms.md#678811
type: markdown
snippet:
  $$x \cdot 2 = 10  $$
  The [solution](Algebra%20key%20terms.md#678811) to this equation is $5$.
  $$
  (x \cdot 2) \cdot 3 = 10 \cdot 3 $$ Here we have multiplied each side of the
  equation by $3$. If $x =5$ then


title: solution
href: zk/Algebra key terms.md#678811
type: markdown
snippet:
  $$x \cdot 3 = 18  $$
  The [solution](Algebra%20key%20terms.md#678811) to this equation is $6$.
  $$\frac{x
  \cdot 3}{3} = \frac{18}{3}
  $$
  Here we have divided each side of the equation by $3$. If $x$ is 6, then
  $$\frac{6
  \cdot 3}{3} = 6$$
  $$\frac{18}{3} = 6 $$


title: equivalent
href: zk/Equivalent fractions.md
type: markdown
snippet:
  When we divide by the common divisor is acts as a divisor. When we multiply by
  the common divisor it acts as a factor. The fact that the fractions are
  [equivalent](Equivalent%20fractions.md) in both cases indicates that the
  properties are equivalent.


title: CPU Architecture
href: zk/CPU_architecture.md#arithmetic-logic-unit
type: markdown
snippet:
  Now the command will be executed. The operand is copied to the Memory Address
  Register and then passed to the Memory Data Register and the command is carried
  out by the ALU. The activities of ALU are covered in
  [CPU Architecture](CPU_architecture.md#arithmetic-logic-unit)
  and the notes on
  [Logic Gates](Logic_gates.md).


title: registers
href: zk/CPU_architecture.md#registers
type: markdown
snippet:
  If the instruction is iterative (e.g. adding two numbers and then multiplying
    by another number), the instruction will tell the CPU to store the interim
    first value in the CPU's
    [registers](CPU_architecture.md#registers). As
    these are part of the CPU, the data can be retrieved more readily. If the
    value is not expected to be used again immediately, it goes to the DRAM or
    harddisk.


title: passing arguments to scripts
href: zk/Passing_arguments_to_Bash_scripts.md
type: markdown
snippet:
  We can access all the arguments passed to a function using the `$@` syntax we
  encountered before when
  [passing arguments to scripts](Passing_arguments_to_Bash_scripts.md).
  (Here a function is a kind of script in miniature so the process is the same.)


title: equivalent
href: zk/Equivalent fractions.md
type: markdown
snippet:
  Let $a,b$ be any integers. The following three fractions are
  > [equivalent](Equivalent%20fractions.md):
  > $$\frac{-5}{15}, \frac{5}{-15}, - \frac{5}{15}$$


title: hardware simulator
href: zk/Hardware_simulation.md
type: markdown
snippet:
  The hardware designer specifies a chip's logic by writing an HDL program which
  is then rigorously tested. At this stage, a
  [hardware simulator](Hardware_simulation.md) takes the
  HDL program as input and creates a software representation of the chip logic.
  The designer can instruct the simulator to test the virtual chip on various sets
  of inputs. This is done to check the chip's functionality but also to benchmark
  a variety of other parameters such as speed of computation and energy
  consumption.


title: input and output pins
href: zk/Integrated_circuits.md
type: markdown
snippet:
  In an HDL program we distinguish internal pins along with the standard
  [input and output pins](Integrated_circuits.md).
  At the level of the interface, we are concerned only with input and output pins
  (in the example program these are `a`, `b` and `out`). It is at the level of the
  implementation that internal pins are encountered. In the example these are the
  connections between, e.g. the AND and NOT gates such as
  `And (a=a, b-notb, out=w1)`. This means the AND gate is receiving through its
  `a` pin the input `a` value and through its `b` pin the value of `b` inverted by
  a NOT. `out` is the value that is computed based on the input pins of `a` and
  `b`.


title: Boolean function
href: zk/Boolean_functions.md
type: markdown
snippet:
  Along with the HDL file we also create a test file. This runs the chip against
  the inputs we supply, these will typically be equivalent to the (left-hand)
  truth-values column in a truth table which is the same as the parameters passed
  to a [Boolean function](Boolean_functions.md), for
  example:


title: equivalent
href: zk/Equivalent fractions.md
type: markdown
snippet:
  Whenever we increase a fraction, the resultant fraction will always be
  > [equivalent](Equivalent%20fractions.md) to the fraction we started with.


title: NOR
href: zk/Logic_gates.md#nor-gate
type: markdown
snippet:
  The circuit diagram latch symbol obviously encapsulates more complex
  functionality that occurs at the sub-circuit level. We will demonstrate how this
  functionality can be achieved with two
  [NOR](Logic_gates.md#nor-gate) gates.


title: pins
href: zk/Integrated_circuits.md
type: markdown
snippet:
  Logic gates are the basic building blocks of digital computing. **A logic gate
  is an electrical circuit that has one or more than one input and only one
  output.** The input and output points of the gate are
  [pins](Integrated_circuits.md) The
  input controls the output and the logic determining which types of input
  (on/off) lead to specific outputs (on/off) is isomorphic with the
  truth-conditions of the
  [Boolean connectives](Truth-functional_connectives.md) specifiable in
  terms of [truth tables](Truth-tables.md).


title: transistor
href: zk/Transistors.md
type: markdown
snippet:
  Physically, what 'travels through' the gates is electrical current and what
  constitutes the 'gate' is a
  [transistor](Transistors.md)
  responding to the current. Going up a level of abstraction, the current/ charge
  is identified with a
  [bit](Binary_units_of_measurement.md#binary-units-of-measurement).
  It is bits that go into the gate and bits which come out: binary information
  that may be either 1 or 0.


title: Adders
href: zk/Half_adder_and_full_adder.md
type: markdown
snippet:
  An example of a composite gate would be a three-way AND. An AND with three
  inputs rather than the standard two that furnish the elementary AND gate. This
  gate would output 1 when all three gates have the value 1 and 0 otherwise.
  [Adders](Half_adder_and_full_adder.md)
  and [latche>s](Latches.md) whilst
  being
  [integrated circuits](Integrated_circuits.md)
  are also, technically speaking, composite gates.


title: hardware abstraction
href: zk/Hardware_abstraction_and_modularity.md
type: markdown
snippet:
  Importantly, a single interface may be implemented in a variety of ways. There
  > is a one-to-many relationship at work here. From the point of view of the user
  > interface these differences should not be detectable. This is another example
  > of
  > [hardware abstraction](Hardware_abstraction_and_modularity.md)


title: queue
href: zk/Queue.md
type: markdown
snippet:
  As the name indicates, its operating mode is that of a
  [queue](Queue.md) data structure offering first-in, first-out
  and other queue implementations.


title: add fractions with a common denominator
href: zk/Add_Subtract_Fractions.md#adding-subracting-fractions-with-common-denominators
type: markdown
snippet:
  But we know that when we
  [add fractions with a common denominator](Add_Subtract_Fractions.md#adding-subracting-fractions-with-common-denominators),
  we only add the numerators, not the denominators. Thus the calculation would
  actually be:


title: using factorization
href: zk/Multiplying_fractions.md#prime-factorisation-in-place
type: markdown
snippet:
  Then carry out the multiplication
     [using factorization](Multiplying_fractions.md#prime-factorisation-in-place):


title: invert and multiply
href: zk/Dividing_fractions.md#formal-specification-of-how-to-divide-fractions'
type: markdown
snippet:
  Again we convert the mixed fraction into an improper fraction and then follow
  the requisite rule, in the case of division this is to
  [invert and multiply](Dividing_fractions.md#formal-specification-of-how-to-divide-fractions').


title: reducing fractions
href: zk/Reducing_fractions.md
type: markdown
snippet:
  It would be laborious to reduce such a large product using factor trees or the
  repeated application of divisors, as defined in
  [reducing fractions](Reducing_fractions.md). We can use a more efficient
  method. This method can be applied at the point at which we conduct the
  multiplication rather than afterwards once we have the product. We express the
  the initial multiplicands as prime factors:


title: $PATH
href: zk/The_PATH.md
type: markdown
snippet:
  When we run a program like `cd` or `npm` we don’t have to type `./cd.sh` or
  `./npm.sh`. This is because a reference to the program file is already in our
  [`$PATH`](The_PATH.md).


title: AWS API Gateway
href: zk/AWS_API_Gateway.md
type: markdown
snippet:
  We will do this using [AWS API Gateway](AWS_API_Gateway.md). We
  select "Add trigger" from the dashboard view and input basic settings:


title: factors
href: zk/Factors and divisors.md
type: markdown
snippet:
  For any whole number $n$ where $n \neq 1$, $n$ is prime if and only if its
  > sole [factors](Factors%20and%20divisors.md) are $1$ and $n$


title: 8-bits long
href: zk/Binary_units_of_measurement.md
type: markdown
snippet:
  When Python runs in this implementation, code written in C converts it to
  bytecode (so-called because each instruction is
  [8-bits long](Binary_units_of_measurement.md)). This is a
  lower-level transliteration of Python is not meant to be understood by the CPU
  (since it is not binary) but rather to be run in the Python virtual machine
  which is equipped to understand bytecode. The Python Virtual Machine is
  therefore also known as "bytecode interpreter" or the CPython VM. The VM then
  converts bytecode into machine-executable code.


title: HTTP request types
href: zk/HTTP_request_types.md
type: markdown
snippet:
  A basic example of a REST API would be a series of methods corresponding to the
  main [HTTP request types](HTTP_request_types.md).


title: file descriptors
href: zk/File_descriptors_and_redirection.md
type: markdown
snippet:
  The `2>&1` argument is the content: any errors that the program may generate and
  try to show in stout. Notice we are using the
  [file descriptors](File_descriptors_and_redirection.md)
  `1` and `2`.


title: greatest common divisor
href: zk/Factors and divisors.md#greatest-common-divisor
type: markdown
snippet:
  A fraction is said to be _reduced to its lowest terms_ if the
  > [greatest common divisor](Factors%20and%20divisors.md#greatest-common-divisor)
  > of the numerator and the denominator is $1$.


title: equivalent
href: zk/Equivalent fractions.md
type: markdown
snippet:
  Whenever we reduce a fraction, the resultant fraction will always be
  > [equivalent](Equivalent%20fractions.md) to the fraction we started with.


title: highest common divisor
href: zk/Factors and divisors.md#greatest-common-divisor
type: markdown
snippet:
  In the previous example the reduction took two steps: first we divided by two
  and then we divided by three. There is a more efficient way: find the
  [highest common divisor](Factors%20and%20divisors.md#greatest-common-divisor) of
  the numerator and denominator and then use this as the basis for the reduction.
  With this method, the reduction can be completed in a single step.


title: factors
href: zk/Factors and divisors.md#factors
type: markdown
snippet:
  Note how our earlier two divisors 2 and 3 are
  [factors](Factors%20and%20divisors.md#factors) of 6, showing the consistency
  between the two methods.


title: interchangeability of factors and divisors
href: zk/Factors and divisors.md
type: markdown
snippet:
  The two methods above are not very systematic and are quite heuristic. The third
  approach is more systematic and relies on the
  [interchangeability of factors and divisors](Factors%20and%20divisors.md).


title: factor
href: zk/Factors and divisors.md#factors
type: markdown
snippet:
  Instead of thinking asking what is the greatest common divisor of 18 and 24 we
  could ask: which single number can we multiply by to get 18 and 24? Obviously
  both numbers are in the six times table. This is therefore to say that 6 is a
  [factor](Factors%20and%20divisors.md#factors) of both: we can multiply some
  number by 6 to arrive at both 18 and 24. The numbers are 3 and 4 respectively:


title: prime factorization
href: zk/Prime factorization.md
type: markdown
snippet:
  A better method is to utilise [prime factorization](Prime%20factorization.md)
  combined with the canceling technique.


title: fraction with unlike terms
href: zk/Handling negative fractions.md#fractions-with-unlike-terms
type: markdown
snippet:
  This fraction is an instance of a
    [fraction with unlike terms](Handling%20negative%20fractions.md#fractions-with-unlike-terms).


title: fraction with like terms
href: zk/Handling negative fractions.md#fractions-with-like-terms
type: markdown
snippet:
  This fraction is an instance of a
    [fraction with like terms](Handling%20negative%20fractions.md#fractions-with-like-terms).


title: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html
href: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html
type: markdown
snippet:
  See
  [https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html)


title: IAM user
href: zk/zk/AWS_User_management_and_roles.md#iam
type: markdown
snippet:
  You require an access key for the given
  [IAM user](zk/AWS_User_management_and_roles.md#iam). You should create an IAM
  account specific to the project with bounded permissions.


title: IAM
href: zk/zk/AWS_User_management_and_roles.md#iam
type: markdown
snippet:
  This information can be found in the Security Credentials section of the given
  [IAM](zk/AWS_User_management_and_roles.md#iam) user:


title: handler function
href: zk/Lambda_handler_function.md
type: markdown
snippet:
  This details the location of the [handler function](/Lambda_handler_function.md)
  which is contained at the path `hello-world/app.js`:


title: S3
href: zk/zk/AWS_S3.md
type: markdown
snippet:
  The packaging proces will first archive all of the project artefacts into a zip
  file and then upload that to [S3](zk/AWS_S3.md). A reference to this S3 entity
  is then provided to CloudFormation.


title: environmental and shell variables
href: zk/Environmental-and-shell-variables-04d5ec7e8e2b486a93f002bf686e4bbb
type: markdown
snippet:
  The type of shell session that you are currently in affects the
  [environmental and shell variables](Environmental-and-shell-variables-04d5ec7e8e2b486a93f002bf686e4bbb)
  that you can access. This is because the order in which configuration files are
  read on initialisation differs depending on the type of shell.


title: Lambda
href: zk/Lambda_programming_model.md
type: markdown
snippet:
  At the beginning you define a `StartAt` state which is the entrypoint of the
  state machine. This can be manually triggered, or more likely, triggered by
  another AWS service such as a
  [Lambda](Lambda_programming_model.md), an
  [API Gateway](AWS_API_Gateway.md) request or a messaging/queue
  event.


title: list
href: zk/Lists_in_Python.md
type: markdown
snippet:
  The `split()` function in Python is used to divide a string into multiple parts
  at the occurrence of a given separator. This function returns a
  [list](Lists_in_Python.md) of substrings.


title: pip
href: zk/Python_package_management.md
type: markdown
snippet:
  Pytest is the most popular testing library for Python. It is not included with
  the Python standard library so it must be installed with
  [pip](Python_package_management.md).
  While it does not include a declaration library, it is robust enough to handle
  most scenarios having a rich and expressive set of constructs and decorators
  that let you declare what your tests should do, under what conditions they
  should run, and how they should interact with the rest of your system.


title: original schema
href: zk/Apollo_Server.md#example-schema
type: markdown
snippet:
  In order to demonstrate arguments we need to expand the
  [original schema](Apollo_Server.md#example-schema).


title: server-side process
href: zk/Apollo_Server.md
type: markdown
snippet:
  Now we have to create a resolver for our new `track` query. We will quickly run
  through the [server-side process](Apollo_Server.md).


title: useQuery hook
href: zk/Apollo_Client.md#usequery-hook
type: markdown
snippet:
  We can now write a proper query using the
  [useQuery hook](Apollo_Client.md#usequery-hook) from
  Apollo Client, with variables.


title: simple example
href: zk/Apollo_Client.md#query-constants
type: markdown
snippet:
  Note that in contrast to the
  [simple example](Apollo_Client.md#query-constants)
  because we are using variables, we have to pass-in an additional options object
  with the query constant that specifies our variables.


title: multiplicands
href: zk/Symbols-and-formal-conventions-80aeaf1872f94a0d97a2e8d07e3855bd
type: markdown
snippet:
  When **multiplying** whole numbers the placement of the
  [multiplicands](Symbols-and-formal-conventions-80aeaf1872f94a0d97a2e8d07e3855bd)
  does not affect the
  [product](Symbols-and-formal-conventions-80aeaf1872f94a0d97a2e8d07e3855bd).


title: expansion
href: zk/Expansions_and_substitutions.md
type: markdown
snippet:
  Note: we do not use a dollar-sign when referring to variables within
  > arithmetic evaluation, there is no need. If we do, we get an error. This is
  > because we are using an
  > [expansion](Expansions_and_substitutions.md),
  > therefore the variables are already being interpreted as variables.


title: Arithmetic_Logic_Unit
href: Arithmetic_Logic_Unit
type: wiki-link
snippet:
  A family of CPUs that implement the core instructions of the
    [[Arithmetic_Logic_Unit]] in the same way share an ISA. Any software built for
    that ISA will work on any CPU that implements the ISA


title: word-size
href: zk/Signed_and_unsigned_numbers.md
type: markdown
snippet:
  There have been different, successive generations of x86 corresponding to
    their [word-size](Signed_and_unsigned_numbers.md): 16-bit, 32-bit, 64-bit.
    Word size here just means how many bits the processor can work with at a time.
    A 34-bit processor can operate on values that are 32 bits in length. This
    means it has 32bit [[CPU_architecture#registers|registers]], a 32-bit data
    [[Bus|bus]], a 32-bit address bus and so on.


title: logic gates
href: zk/Logic_gates.md
type: markdown
snippet:
  The half adder and full adder are components of digital circuits that enable us
  to carry out binary addition. Using adders and half adders we can add two binary
  numbers together. Adders are a type of [integrated circuit]() comprising certain
  [logic gates](Logic_gates.md) where the arrangement allows for the
  representation of the addition of bits.


title: XOR
href: zk/Logic_gates.md#xor-gate
type: markdown
snippet:
  We can see that the sum bit column replicates the truth-conditions of
  [XOR](Logic_gates.md#xor-gate):


title: heap memory
href: Heap_memory
type: wiki-link
snippet:
  Along with [[Heap_memory|heap memory]] heap memory, programs make use of
    _stack memory_ during runtime.


title: stack data structure
href: Stacks
type: wiki-link
snippet:
  Similarly to the [[Stacks|stack data structure]], it works on the basis of LIFO:
  the last item put on the stack is the first item to be withdrawn.


title: register
href: CPU_architecture#registers
type: wiki-link
snippet:
  A **stack pointer** is used to manage the items in the stack. This value is
  stored in a [[CPU_architecture#registers|register]] and its value is the memory
  address of the item currently on the top of the stack. Note: _not_ the value
  itself, the _address_ of the value.


title: memory leaks
href: Memory_leaks
type: wiki-link
snippet:
  Local variable storage: storing the variables local to a function's scope and
     removing them once the function returns, avoiding
     [[Memory_leaks|memory leaks]]


title: Memory_leaks
href: Memory_leaks
type: wiki-link
snippet:
  Whereas stack memory with it's LIFO structure has memory management built-in
  when programs allocate memory from the heap they must manually deallocate it
  when it is no longer required. This process of "freeing memory" is known as
  _garbage collection_. In a language like C, this is the explicit concern of the
  programmer and is not abstracted away. Failure to properly manage garbage
  collection is what causes [[Memory_leaks]].


title: ways around this
href: https://thom4.net/2014/self-contained-node-scripts/
type: markdown
snippet:
  If you use any module not in the Node core, you will need to have this installed
  globally for it to work. (There are
  [ways around this](https://thom4.net/2014/self-contained-node-scripts/) for Node
  scripts you publish but for personal scripts this doesn't matter.)


title: difference of potential
href: zk/Voltage.md
type: markdown
snippet:
  When there is an excess of electrons at one terminal (i.e. negatively charged
  atoms) and a deficiency of electrons at the other terminal (i.e. positively
  charged atoms), a [_difference of potential_](Voltage.md) exists between the two
  terminals.


title: current
href: zk/Current.md
type: markdown
snippet:
  We noted in the discussion of [current](Current.md) that current flows when
  there is a difference of potential between two points with negatively charged
  atoms at one point and positively charged atoms at the other.


title: form of energy
href: zk/Voltage_sources.md
type: markdown
snippet:
  Voltage is the application of this energy. Any
  [form of energy](Voltage_sources.md) that dislodges electrons from atoms can be
  used to produce current. Thus:


title: battery
href: zk/Cells_and_batteries.md
type: markdown
snippet:
  Given that voltage is the force that generates current, it would be natural to
  think that voltage only exists when a voltage source (such as a
  [battery](Cells_and_batteries.md)) is connected to a circuit. This however is
  not the case. Even if a 9V battery isn't connected to anything it still has a
  difference of potential of 9-volts accross its terminals. Remember voltage is
  _potential energy_ not just the actualisation of that energy.


title: Ohm's Law
href: zk/Ohms_Law.md
type: markdown
snippet:
  We can work out the voltage of the remaining voltage points by inverting
  [Ohm's Law](Ohms_Law.md): $V = I \times R$:


title: amp
href: zk/Current.md#formal-expression
type: markdown
snippet:
  One ohm is the resistance of a circuit or circuit element that permits a
  > steady current flow of one [amp](Current.md#formal-expression) (one
  > coulomb/second) when one [volt](Voltage.md#voltage) is applied to the circuit.


title: batteries
href: zk/Cells_and_batteries.md
type: markdown
snippet:
  The chemical creation of current is the physics behind
  [batteries](Cells_and_batteries.md). Chemical current production produces
  currents on a smaller and less industrial scale than generators.


title: exception
href: zk/Error_handling_in_Python.md
type: markdown
snippet:
  Obviously file access can raise errors - typically when the file you want to
  access does not exist (i.e. a `FileNotFoundError`
  [exception](Error_handling_in_Python.md)). We can manage this scenario with
  [exception handlers](Error_handling_in_Python.md):


title: event emitter
href: zk/Events module.md#event-emitters
type: markdown
snippet:
  We create an [event emitter](Events%20module.md#event-emitters) and listener
  that listens for GET requests on a specified port and sends data in response to
  requests.


title: my notes
href: zk/Connect_to_Mongo_database.md
type: markdown
snippet:
  We will follow the routine for establishing a MongoDB instance as detailed in
  [my notes](Connect_to_Mongo_database.md) on Mongo:


title: Querying a collection
href: zk/Querying_a_Mongo_collection.md
type: markdown
snippet:
  Now we need to rewrite our RESTful request handlers so that the data is sourced
  from and added to the database. We will mainly be using the Mongo syntax defined
  at [Querying a collection](Querying_a_Mongo_collection.md) and
  [Adding documents to a collection](Adding_documents_to_a_Mongo_collection.md).
  We will also keep API validation within the `/model/` file.


title: query-first
href: zk/Update_a_Mongo_document.md#query-first-document-update
type: markdown
snippet:
  When updating a value in the database we are going to use the
  [query-first](Update_a_Mongo_document.md#query-first-document-update)
  approach to updating a Mongo document.


title: React_useReducer
href: zk/React_useReducer.md#refining-the-syntax
type: markdown
snippet:
  Now we need a reducer that will handle the state updates. We will just use the
  same setup as we used in the example of
  [React_useReducer](React_useReducer.md#refining-the-syntax):


title: Commutative Law
href: zk/Whole_numbers.md#the-commutative-property
type: markdown
snippet:
  Compare the
  [Commutative Law](Whole_numbers.md#the-commutative-property)
  in the context of arithmetic.


title: Associative Law
href: zk/Whole_numbers.md#the-associative-property
type: markdown
snippet:
  Compare the
  [Associative Law](Whole_numbers.md#the-associative-property)
  in the context of arithmetic.


title: Distributive Law applies in the case of algebra based on arithmetic
href: zk/Distributivity.md
type: markdown
snippet:
  Compare how the
  [Distributive Law applies in the case of algebra based on arithmetic](Distributivity.md):


title: DeMorgan's Laws
href: zk/DeMorgan's_Laws.md
type: markdown
snippet:
  In addition we have
  [DeMorgan's Laws](DeMorgan's_Laws.md) which express
  the relationship that obtains between the negations of conjunctive and
  disjunctive expressions:


title: logic gates
href: zk/Logic_gates.md
type: markdown
snippet:
  The fact that we can take a complex Boolean function and reduce it to a simpler
  formulation has great significance for the development of computer
  architectures, specifically
  [logic gates](Logic_gates.md). It
  would be rather resource intensive and inefficient to create a gate that is
  representative of the complex function. Whereas the simplified version only
  requires a single
  [OR gate](Logic_gates.md#or-gate).


title: logic circuits
href: zk/Digital_circuits.md
type: markdown
snippet:
  This is an important skill that we will use when constructing
  [logic circuits](Digital_circuits.md).
  We will go from truth conditions (i.e. what we want the circuit to do and when
  we want it to do it) to a function expression which is then reduced to its
  simplest form and implemented with
  [logic gates](Logic_gates.md).
  Specifically, NAND gates.


title: idempotence
href: zk/Boolean_algebra.md#idempotent-law
type: markdown
snippet:
  Notice that $\lnot(z)$ is repeated so we can remove the repetition through
  [idempotence](Boolean_algebra.md#idempotent-law):


title: NAND gate
href: zk/Logic_gates.md#nand-gate
type: markdown
snippet:
  Finally, we can simplify even further by doing away with AND and NOT and using a
  single
  [NAND gate](Logic_gates.md#nand-gate)
  which embodies the logic of both, being true in all instances where AND would be
  false: $\lnot (x \land  y)$.


title: trkjuth table
href: zk/Truth-tables.md
type: markdown
snippet:
  We can compute all possible outputs of the function by constructing a
  [trkjuth table](Truth-tables.md) with each possible
  variable as the truth conditions and the output of the function as the truth
  value:


title: memory
href: zk/Memory.md
type: markdown
snippet:
  | Bus type      | Description                                                                                                                                                                                                        |
  | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
  | System bus    | The primary pathway between the CPU and [memory](Memory.md). It comprises the **data bus** that transfers data from the memory to the CPU and the **address bus** which transmits requests from the CPU to memory. |
  | Internal bus  | Connects local devices for example the harddisk to the CPU.                                                                                                                                                        |
  | External bus  | Connects peripheral devices such as disks and printers to the [motherboard](Motherboard.md)                                                                                                                        |
  | Expansion bus | Allows expansion boards to access the CPU and memory.                                                                                                                                                              |
  | Frontside bus | Main computer bus that determines data transfer rate speed and is the primary data transfer path between the CPU, RAM and other [motherboard](Motherboard.md) devices.                                             |
  | Backside bus  | Transfers secondary cache (L2 cache) data at faster speeds, allowing more efficient CPU operations                                                                                                                 |


title: motherboard
href: zk/Motherboard.md
type: markdown
snippet:
  The chipset manages the data flow between the different components that comprise
  the [motherboard](Motherboard.md): processor,
  [memory](Memory.md),
  [harddisk](What_are_disks.md) and peripherals.


title: system bus
href: zk/Bus.md
type: markdown
snippet:
  Buses run in and out of the chipset into these key motherboard components. The
  main chipset is a kind of junction that sits between the memory and CPU through
  which the [system bus](Bus.md) passes.


title: duck typing
href: zk/Custom_types_in_TypeScript.md#duck-typing
type: markdown
snippet:
  You shouldn't confuse `implements` with `extends`. `implements` just checks the
  class as an interface in accordance with the principles of
  [duck typing](Custom_types_in_TypeScript.md#duck-typing):
  i.e the implementing class should have the same properties and methods. It
  doesn't affect anything internal to the methods or properties. So e.g, if you
  typed a method parameter as `string` in the base class, this would still default
  to `any` in the derived class.


title: principle of the immutability of elements
href: zk/Elements-992594b9cd2e483c85cddddffeb16f11
type: markdown
snippet:
  We change components by using state, not by mutating props. This is consistent
  with React's
  [principle of the immutability of elements](Elements-992594b9cd2e483c85cddddffeb16f11).


title: data type
href: zk/Data_types_in_MySQL.md
type: markdown
snippet:
  Below is an example of this in practice. Each field corresponds to a column. We
  specify the name of the field and its corresponding
  [data type](Data_types_in_MySQL.md). Every table must have a
  **primary key**. In the example, `employee_id` is the primary key.


title: collections and documents
href: zk/MongoDB_Introduction.md
type: markdown
snippet:
  In order start adding
  [collections and documents](MongoDB_Introduction.md) to our database,
  we use Mongoose's **schema** structure. (This is specific to Mongoose and is not
  a structure that is a part of Mongo in general.)


title: separate entry
href: zk/Validating_Mongoose_schemas.md
type: markdown
snippet:
  Note that we set our validation criteria as the second property for each
  > schema value. There is more info info on validation in a
  > [separate entry](Validating_Mongoose_schemas.md);


title: zk/Docker_architecture
href: zk/Docker_architecture
type: wiki-link
snippet:
  Cloud-based or virtual server (virtual machine), basically a hypervisor
    (compare [[zk/Docker_architecture]])


title: syntactic
href: zk/Syntax_of_sentential_logic.md
type: markdown
snippet:
  Derivation rules are
  [syntactic](Syntax_of_sentential_logic.md) rather
  than semantic. They are applied on the basis of their form rather than on the
  basis of the truth conditions of the sentences they are applied to.


title: CREATE TABLE
href: zk/Create_an_SQL_table.md
type: markdown
snippet:
  The output will be represented as a table but it is virtual, not an actual
  table. (If you wish to actually create a table or a view off the back of a join
  operation you should combine the join with the
  [`CREATE TABLE`](Create_an_SQL_table.md) command etc.)


title: contradiction
href: zk/Logical_truth_and_falsity.md#logical-falsity
type: markdown
snippet:
  A
  [contradiction](Logical_truth_and_falsity.md#logical-falsity)
  has very important consequences for reasoning because if a set of propositions
  is inconsistent, any other proposition is derivable from it.


title: negation elimination
href: zk/Negation_Elimination.md
type: markdown
snippet:
  Here we want to derive some proposition $Q$. If we can derive a contradiction
  from its negation as an assumption then, by the
  [negation elimination](Negation_Elimination.md)) rule, we can
  assert $Q$. This is why contradictions should be avoided in arguments, they
  'prove' everything which, by association, undermines any particular premise you
  are trying to assert.


title: derivation
href: zk/Formal proofs in propositional logic.md
type: markdown
snippet:
  Propositions $P$ and $Q$ are equivalent in a system of
  > [derivation](Formal%20proofs%20in%20propositional%20logic.md) for
  > propositional logic if $Q$ is derivable from $P$ and $P$ is derivable from
  > $Q$.


title: material biconditional
href: zk/Biconditional_Introduction.md
type: markdown
snippet:
  Note that the property of equivalence stated in terms of derivablity above is
  identical to the derivation rule for the
  [material biconditional](Biconditional_Introduction.md):


title: consistently
href: zk/Consistency.md
type: markdown
snippet:
  A proposition is logically indeterminate if it is neither logically true or
  logically false. This is to say: it can be both [consistently](Consistency.md)
  asserted and consistently denied.


title: logical consistency
href: zk/Logical_consistency.md
type: markdown
snippet:
  In distinguishing the properties of
  [logical consistency](Logical_consistency.md) and
  [validity](Validity_and_entailment.md) we make tacit use
  of the notion of **possibility**. This is because when we consider the validity
  of an argument we are assessing truth-conditions and this consists in asking
  ourselves what could or could not be the case: were it such that _P_, then it
  would be the case that _Q_. It is important to understand what possibility means
  in the context of logic and how it differs from what we might mean ordinarily
  when we use the term.


title: logical truth
href: zk/Logical_truth_and_falsity.md#logical-truth
type: markdown
snippet:
  A proposition is _logically necessary_ if it is true in every logically possible
  circumstance which is to say: true on every possible truth functional
  assignment. Necessity and
  [logical truth](Logical_truth_and_falsity.md#logical-truth)
  are therefore synonyms: anything that is logically true (a tautology) is true by
  necessity (could not be otherwise.)


title: consistency
href: zk/Logical_consistency.md
type: markdown
snippet:
  Neither proposition can be true because the truth of the first clause is
  contradicted by the second. By the principle of
  [consistency](Logical_consistency.md), it is not
  possible for both clauses to be true at once therefore the proposition, overall
  has the truth value of false.


title: validity
href: zk/Validity_and_entailment.md
type: markdown
snippet:
  If an argument contains premises which are logically false than this argument
    will perforce be valid. This is because one cannot consistently assert the
    premises and deny the conclusion which is the definition of
    [validity](Validity_and_entailment.md). However the
    _reason_ why one cannot consistently assert the premises and deny the
    conclusions is because one cannot consistently assert the premises - they
    conflict with each other. Furthermore as the argument contains false premises,
    it cannot be sound.


title: React_useEffect
href: zk/React_useEffect.md
type: markdown
snippet:
  Note that the syntax is similar to [React_useEffect](React_useEffect.md): there is a
  dependency array. The effect is the same: the function contained within
  `useCallback` will only re-rendered if one of these dependencies changes.
  However (see next section) the function will run in its memoized form on every
  click.


title: CPU
href: zk/CPU_architecture.md
type: markdown
snippet:
  When a [CPU](CPU_architecture.md) executes a program,
  it needs a place to store the program's **instructions** and **related data**.
  This is the role of memory.


title: transistor
href: zk/Transistors.md
type: markdown
snippet:
  In a DRAM cell, each bit of data is stored as a charge in a capacitor. The
  presence of charge represents a '1' bit and the absence of charge represents a
  '0' bit. Each of these cells is paired with a
  [transistor](Transistors.md) that
  controls the reading and writing of data.


title: charge
href: zk/Current.md
type: markdown
snippet:
  However capacitors lose
  [charge](Current.md) over time due
  to leaks. As a result DRAM is memory that needs to be refreshed (recharged)
  frequently. For this reason and because it only uses one transistor and
  capacitor per bit, DRAM is the less expensive form of volatile memory.


title: flip flops
href: zk/Flip_flops.md
type: markdown
snippet:
  SRAM uses [flip flops](Flip_flops.md)
  to store the bits. It also uses multiple transistors per bit. This makes it
  faster than DRAM but more expensive. DRAM is at least ten times slower than
  SRAM.


title: bootstrapping
href: zk/Boot_process.md
type: markdown
snippet:
  The following steps outline the way in which memory interacts with the processor
  during computational cycles, once the
  [bootstrapping](Boot_process.md) process has completed and
  the OS kernel is itself loaded into memory.


title: system bus
href: zk/Bus.md
type: markdown
snippet:
  The instruction at the first address is sent to the CPU, travelling accross
     the data bus part of the [system bus](Bus.md).


title: chipset
href: zk/Chipset_and_controllers.md
type: markdown
snippet:
  The CPU processes this instruction and then sends a request accross the
     address bus part of the system bus for the next instruction to the memory
     controller within the
     [chipset](Chipset_and_controllers.md).


title: DRAM
href: zk/Memory.md#dram
type: markdown
snippet:
  The chipset finds where this instruction is stored within the
     [DRAM](Memory.md#dram) and issues a request to
     have it read out and send to the CPU over the data bus.


title: logarithm
href: zk/Logarithms.md
type: markdown
snippet:
  We need to reverse this formula to find out how many bits we need to represent a
  given number of addresses. We can do this with a
  [logarithm](Logarithms.md).


title: hexadecimal numbers
href: zk/Hexadecimal_number_system.md
type: markdown
snippet:
  This is hard to parse so we can instead use
  [hexadecimal numbers](Hexadecimal_number_system.md)
  to represent the addresses:


title: binary encoding
href: zk/Binary_encoding.md
type: markdown
snippet:
  By itself, the the data is meaningless but we know from
  [binary encoding](Binary_encoding.md) that the
  binary data will correspond to some meaningful data, such as a character or a
  colour, depending on the encoding scheme used. The above table could correspond
  to the characters for 'A', 'B' and 'C' in the ASCII encoding scheme:


title: tables
href: zk/Relational_database_architecture.md#table
type: markdown
snippet:
  Although Mongo is not a relational database it has a structure that we can
  understand in relation to that paradigm. A **database** is obviously the overall
  structure. It comprises **collections** which are organised sets of data that
  are analagous to [tables](Relational_database_architecture.md#table)
  in RDBs. Within each collection are a series of **documents** which we can think
  of as being equivalent to [rows](Relational_database_architecture.md)
  in RDB table: units that comprise the collection.


title: CPU
href: zk/CPU_architecture.md
type: markdown
snippet:
  The motherboard is the foundation of a computer. It allocates power and allows
  communication to and between the
  [CPU](CPU_architecture.md),
  [RAM](Memory.md),
  [harddisk](What_are_disks.md) and all other hardware
  components.


title: any
href: zk/Any.md
type: markdown
snippet:
  `Object` is a valid type declaration in TS but it is not particularly helpful
  since it becomes similar to using [any](Any.md) given that most primitive
  types in JavaScripts prototypically inherit from an Object.


title: custom types
href: zk/Custom_types_in_TypeScript.md
type: markdown
snippet:
  Generally, when you use objects in TypeScript you type them as
  [custom types](Custom_types_in_TypeScript.md).


title: model
href: zk/Create_collections_and_documents_with_Mongoose.md#models
type: markdown
snippet:
  Now we will query the collection. This capability is provided via the Mongoose
  schema class we used to create the `Course`
  [model](Create_collections_and_documents_with_Mongoose.md#models).
  We have the following methods available to use from the schema:


title: React_useEffect
href: zk/React_useEffect.md#cleanup-functions
type: markdown
snippet:
  As the warning suggests, this can be resolved using the cleanup parameter within
  [React_useEffect](React_useEffect.md#cleanup-functions).


title: Application state management
href: zk/Application_state_management_with_React_hooks.md
type: markdown
snippet:
  In the examples above we have only been consuming state that is owned by the
  provider however in most scenarios you will also want to update the state from a
  consumer. This is best achieved by combining `useContext` with a reducer and is
  detailed in [Application state management](Application_state_management_with_React_hooks.md).


title: lifecyle methods
href: zk/Lifecycle_methods.md
type: markdown
snippet:
  `useEffect` enshrines but also simplifies the
  [lifecyle methods](Lifecycle_methods.md) that are used with
  class-based React components.


title: lifecycle methods
href: zk/Lifecycle_methods.md
type: markdown
snippet:
  The syntax of the `useEffect` hook also allows you to handle cleanup: something
  you want to do when the component unmounts (another example of how this hook
  recasts the traditional [lifecycle methods](Lifecycle_methods.md))
  . In addition to running on unmount, the cleanup function will run before the
  effect runs again (i.e. when it runs in response to a change in one of the
  elements of the dependency araray). This is chiefly used to prevent
  [memory leaks](Memory_leaks.md) and the
  ['update on unmounted component error'](React_errors.md#state-update-on-unmounted-component).


title: ACID principle
href: zk/ACID_principle.md
type: markdown
snippet:
  This is essential for carrying out operations across database tables and for
  creating and deleting database entires in accordance with the
  [ACID principle](ACID_principle.md). It is also a safeguard: it means
  you can always identify a record by itself and don't have to rely on generic
  queries to identify it.


title: recursive
href: zk/Recursion.md
type: markdown
snippet:
  Goal analysis is a [recursive](Recursion.md) strategy which
  proceeds by using a 'goal' proposition to guide the construction of intermediary
  derivations.


title: valid
href: zk/Validity_and_entailment.md#validity
type: markdown
snippet:
  Assume that we want to show that an argument is
  [valid](Validity_and_entailment.md#validity). Then our
  ultimate goal is to derive the conclusion from the premises we are given. We
  first ask ourselves: _which propositions if we could derive them, would allow us
  to easily derive the conclusion_? (For example, these propositions might be two
  simple propositions that when combined with
  [Conjunction Introduction](Conjunction_Introduction.md) give us
  the conclusion.) Deriving these propositions then becomes the new intermediate
  goal.


title: Conjunction Introduction
href: zk/Conditional_Introduction.md
type: markdown
snippet:
  First, we consider what is the easiest possible way of achieving the proposition
  $(L \lor A) \land D$. Clearly it is to separately derive each disjunct
  ($L \lor A$ and $D$) and then combine them with
  [Conjunction Introduction](Conditional_Introduction.md). This
  provides us with our first goal: to derive each of the separate conjuncts.


title: Conjunction Elimination
href: zk/Conjunction Elimination.md
type: markdown
snippet:
  Let's start with $D$: where does it occur in the assumptions? It occurs in the
  compound $(\lnot N \rightarrow L) \land (D \leftrightarrow \lnot N)$, but only
  in the first conjunct. We can get this simply but applying
  [Conjunction Elimination](Conjunction%20Elimination.md).


title: Biconditional Elimination
href: zk/Biconditional_Elimination.md
type: markdown
snippet:
  Now we just need to get $D$ from the proposition at line 3. This is easy since
  we already have access to the consequent of the biconditional at line 1.
  Therefore we can apply
  [Biconditional Elimination](Biconditional_Elimination.md)) at line
  3 to get $D$. We are now halfway there:


title: Conjunction Elimination
href: zk/Conjunction_Elimination.md
type: markdown
snippet:
  Next we need to turn our attention to deriving $L \lor A$. How can we obtain $L$
  ? Well it is contained within the first conjunct of the assumption on line 2.
  Again, we can get this through the application of
  [Conjunction Elimination](Conjunction_Elimination.md). Now, how do
  we get $L$ from $(\lnot N \rightarrow L)$? Well, we already have the antecedent
  $\lnot N$ as an assumption on the first line, so we can use
  [Conditional Elimination](Conditional_Elimination.md) to derive
  $L$. These two steps give us:


title: Disjunction Introduction
href: zk/Disjunction_Introduction.md
type: markdown
snippet:
  Now we need to get from $L$ to $L \lor A$. This is really straightforward
  because by using
  [Disjunction Introduction](Disjunction_Introduction.md)) we can
  get from any sentence to a disjunction. Finally, having assembled all the
  constituent parts of the conjunction that is the conclusion, we can combine them
  with [Conjunction Introduction](Conjunction_Introduction.md) as we
  had planned at the outset.


title: Conjunction Introduction
href: zk/Conjunction_Introduction.md
type: markdown
snippet:
  The requirements here could easily mislead us. We see that the target
  proposition is a conjunction so we might think that the best strategy is to seek
  to derive each conjunct and then combine them via
  [Conjunction Introduction](Conjunction_Introduction.md)).


title: Biconditional Elimination
href: zk/Biconditional_Elimination.md
type: markdown
snippet:
  Actually, if we look more closely, there is a better approach. The target
  proposition is contained in the first premise as the consequent to the
  biconditional ($\lnot L \leftrightarrow [X \land (\lnot S \lor B)]$). A better
  approach is therefore to seek to derive the antecedent ($\lnot L$) and then use
  [Biconditional Elimination](Biconditional_Elimination.md) to
  extract the target sentence which is the consequent.


title: theorems
href: zk/Theorems_and_empty_sets.md#theorems-and-empty-sets
type: markdown
snippet:
  When we are proving
  [theorems](Theorems_and_empty_sets.md#theorems-and-empty-sets)
  we do not have a set of assumptions to work from when constructing the proof. We
  must derive the target sentence from the 'empty set' which is the target
  sentence itself. It is therefore like a process of reverse engineering.


title: Disjunction Elimination
href: zk/Disjunction_Elimination.md
type: markdown
snippet:
  Our starting assumption is to a disjunction. Thus we can apply
    [Disjunction Elimination](Disjunction_Elimination.md) to show
    that our goal sentence $\lnot(A \land B)$ follows from each of the disjuncts
    ($\lnot A$ and $\lnot B$) in dedicated sub-proofs. If we can do this, we have
    the right to derive $\lnot (A \land B)$.


title: Disjunction Elimination
href: zk/Disjunction_Elimination.md
type: markdown
snippet:
  Having done this, we can discharge the
    [Disjunction Elimination](Disjunction_Elimination.md) sub-proofs
    and derive $\lnot (A \land B)$ from $\lnot A \lor \lnot B$


title: Negation Elimination
href: zk/Negation_Elimination.md
type: markdown
snippet:
  We will do this by assuming the negation of what we want to prove
    ($\lnot (\lnot A \lor \lnot B)$) and then apply
    [Negation Elimination](Negation_Elimination.md) to get
    $\lnot A \lor \lnot B$.


title: Negation Elimination
href: zk/Negation_Elimination.md
type: markdown
snippet:
  This requires us to derive a contradiction. We get this on lines 23 and 24.
    This requires as previous steps that we have two sub-proofs that use
    [Negation Elimination](Negation_Elimination.md) to release $A$
    and $B$


title: atomic and molecular propositions
href: zk/Atomic_and_molecular_propositions.md
type: markdown
snippet:
  These definitions provide a formal specification of the concepts of
  [atomic and molecular propositions](Atomic_and_molecular_propositions.md)
  introduced previously.


title: derivation
href: zk/Formal_proofs_in_propositional_logic.md#derivation-rules
type: markdown
snippet:
  We know that when we construct a
  [derivation](Formal_proofs_in_propositional_logic.md#derivation-rules)
  we start from a set of assumptions and then attempt to reach a proposition that
  is a consequence of the starting assumptions. However it does not always have to
  be the case that the starting set contains members. The set can in fact be
  empty.


title: logically determinant
href: zk/Logical_indeterminacy.md
type: markdown
snippet:
  We know that
  [logically determinant](Logical_indeterminacy.md)
  propositions express a truth value. When simple propositions are joined with a
  connective to make a compound proposition they also have a truth value. This is
  determined by the nature of the connective and the truth value of the
  constituent propositions. We therefore call connectives of this nature truth
  _functional_ connectives since the **truth value of the compound is a function
  of the truth values of its components**.


title: query
href: zk/Querying_a_Mongo_collection.md
type: markdown
snippet:
  With this approach we first execute a
  [query](Querying_a_Mongo_collection.md) to retrieve the document we
  want to edit and then make the change. We use the `findById` method to identify
  the document by its UUID and then `set` to update specified properties on the
  document. The `set` method is one of many operators that can be used to update
  values. For example there is also built-in operators for increment, renaming,
  multiplying values.


title: HTTP request types
href: zk/HTTP_request_types.md
type: markdown
snippet:
  Express provides us with methods corresponding to each of the
  [HTTP request types](HTTP_request_types.md):


title: MongoDB database
href: zk/05_ Integrating_the_database.md
type: markdown
snippet:
  Typically when you create a RESTful API you are going to be returning data
  > from a database. For simplicity we are just going simulate this with a simple
  > data array so that we can focus on the Express syntax rather than database
  > handling. Later we will integrate this with a
  > [MongoDB database](05_%20Integrating_the_database.md).


title: middleware
href: zk/Middleware_in_NodeJS.md
type: markdown
snippet:
  We first create an instance of Express within `index.js`. This will be the main
  coordinating file and we will aim to minimise the amount of business logic we
  have in this file. It should really just be for initialization and managing
  [middleware](Middleware_in_NodeJS.md).


title: Joi validator
href: zk/Validation_in_NodeJS.md
type: markdown
snippet:
  We should accept alterations to the database that are not first validated. We
  can use the
  [Joi validator](Validation_in_NodeJS.md) to vet
  the request:


title: capacitors
href: zk/Memory.md
type: markdown
snippet:
  This is the part of the CPU that stores data. The memory cells that comprise it
  do not have [capacitors](Memory.md) (unlike RAM)
  so they cannot store very much data but they work faster, which is what is
  important. Because their memory capacity is so small, we measure the size of
  registers in bits rather than bytes.


title: memory hierarchy
href: zk/Memory.md#the-memory-hierarchy
type: markdown
snippet:
  In terms of speed, registers sit at the top part of the overall
  [memory hierarchy](Memory.md#the-memory-hierarchy).


title: controller
href: zk/Chipset_and_controllers.md
type: markdown
snippet:
  The CPU's [controller](Chipset_and_controllers.md). It
  takes the instructions in binary form from RAM memory (separate from the CPU,
  but connected) and then signals to the to ALU and memory registers what it is
  supposed to do to execute the instructions. Think of it as the overseer that
  gets the ALU and registers to work together to run program instructions.


title: logic gates
href: zk/Logic_gates.md
type: markdown
snippet:
  The clock's circuitry is based on a quartz crystal system like that used in
  watches. At precisely timed intervals, the clock sends out pulses of electricity
  that cause bits to move from place to place within
  [logic gates](Logic_gates.md) or
  between logic gates and
  [registers](CPU_architecture.md#registers). This is
  covered in greater detail in the discussion of
  [clock signals in digital circuits](Clock_signals.md).


title: kernel
href: zk/The_kernel.md
type: markdown
snippet:
  Each "cycle" is the execution of a process that commences once the
  [kernel](The_kernel.md) hands control to the CPU. Each cycle
  follows a sequence of events known as
  [fetch, decode, and execute](Fetch_decode_execute.md).


title: electromagentic waves
href: zk/Electromagnetism.md
type: markdown
snippet:
  Hertz was the scientist who detected
  [electromagentic waves](Electromagnetism.md).
  We use Hertz as a measure of the frequency of electromatic wave cycles in a
  signal.


title: arguments
href: zk/Passing_arguments_and_options_to_Bash_scripts.md
type: markdown
snippet:
  Here we test that the right number of
  [arguments](Passing_arguments_and_options_to_Bash_scripts.md)
  have been passed to the script:


title: electromagnetic
href: zk/Electromagnetism.md
type: markdown
snippet:
  A single iteration of the volatage rising and falling is a **pulse**. A complete
  oscillation from low to high and back to low is a **cycle**. As with all
  [electromagnetic](Electromagnetism.md)
  signals we measure the frequency of the wave in Hertz: cylcles per second. We
  also further distinguish the rising and falling edge of a pulse. Rising
  represents the signal passing from ground to its maximum voltage and falling is
  the reverse (the electrons moving from the voltage source to ground).


title: CPU
href: zk/CPU_architecture.md#the-system-clock
type: markdown
snippet:
  The role of the clock is essential in the functioning of the
  [CPU](CPU_architecture.md#the-system-clock). It is
  the system clock that gives CPUs their performance rating: how many processes
  can execute within a given clock cycle.


title: kernal
href: zk/The_kernel.md
type: markdown
snippet:
  Containers are native to the Linux [kernal](The_kernel.md)
    and are key part of how it works. Thus when you run containers on Linux, you
    are using native capability. When you use containers on Windows or Mac you
    have to run a virtual version of Linux in order to exploit the capabilities of
    that kernel. (Docker provides this)


title: user space
href: zk/User_Space.md
type: markdown
snippet:
  In ordinary [user space](User_Space.md) applications share
  the _same_ processor, memory and file system resources. This increases the
  likelihood of resourcing challenges, dependency conflicts and security threats.
  Without modularisation and the titration of resources, you are opened up to much
  greater possibility of failure.


title: mode
href: zk/File_permissions_and_execution_in_Bash.md#what-the-output-means
type: markdown
snippet:
  The
  [mode](File_permissions_and_execution_in_Bash.md#what-the-output-means)
  is different from ordinary files. Each device file is prepended with
  `b, p, c, s` before the standard permissions. These stand for the major types of
  devices: _block, character, pipe_ and _socket_.


title: bash scripting
href: zk/Redirect_to_dev_null.md
type: markdown
snippet:
  `/dev/null` is a virtual device: it doesn't actually exist as a piece of
  hardware on the system. It can be useful when
  [bash scripting](Redirect_to_dev_null.md) as a
  place to direct output that you don't care about, for example errors or verbose
  program read-outs.


title: kernel
href: zk/The_kernel.md
type: markdown
snippet:
  A running Node application is a single running process. Like everything that
  happens within the OS, a process is managed by the
  [kernel](The_kernel.md) that dispatches operations to the CPU
  in a clock cycle. A thread is a sequence of code that resides within the process
  and utilises its memory pool (the amount of memory assigned by the kernel to the
  Node process). The Event Loop runs on CPU ticks: a tick is a single run of the
  Event Loop.


title: call stack
href: zk/Call_stack.md
type: markdown
snippet:
  The Event Loop comprises six phases. The Event Loop starts at the moment Node
  begins to execute your `index.js` file or any other application entry point.
  These six phases create one cycle, or loop, equal to one **tick**. A Node.js
  process exits when there is no more pending work in the Event Loop, or when
  `process.exit()` is called manually. A program only runs for as long as there
  are tasks queued in the Event Loop, or present on the
  [call stack](Call_stack.md).


title: call stack
href: zk/Call_stack.md
type: markdown
snippet:
  At the beginning of this phase the Event Loop updates its own time. Then it
       checks a queue, or pool, of timers. This queue consists of all timers that
       are currently set. The Event Loop takes the timer with the shortest wait
       time and compares it with the Event Loop's current time. If the wait time
       has elapsed, then the timer's callback is queued to be called once the
       [call stack](Call_stack.md) is empty.


title: https://blog.appsignal.com/2022/07/20/an-introduction-to-multithreading-in-nodejs.html
href: https://blog.appsignal.com/2022/07/20/an-introduction-to-multithreading-in-nodejs.html
type: implicit
snippet:
  https://blog.appsignal.com/2022/07/20/an-introduction-to-multithreading-in-nodejs.html
  https://school.geekwall.in/p/Bk2xFs1DV


title: variables
href: zk/Variables_and_data_types_in_Bash.md
type: markdown
snippet:
  We use most frequently for returning the value of stored
  [variables](Variables_and_data_types_in_Bash.md).
  Techically we do not have to use the braces, we can retrieve with just `$var`
  however it's better to use them to minimise interpretation fuck-ups which happen
  a lot.


title: sub-shell
href: zk/Shell_sessions.md
type: markdown
snippet:
  Command substitution (circle-brackets) allows us to put the output of one
  command inside another. Bash runs the bracketed command in a
  [sub-shell](Shell_sessions.md) and then returns it
  to the main user shell.


title: redirect
href: zk/Redirection_in_Bash.md
type: markdown
snippet:
  They are typically used when you want to
  [redirect](Redirection_in_Bash.md) the output of the
  standard/input /output/error somewhere, e.g a file or as input to another
  program. A classic case is `[some_command] > /dev/null 2>&1`


title: $0
href: zk/Passing_arguments_and_options_to_Bash_scripts.md#passing-arguments
type: markdown
snippet:
  They are all technically "files" which are open and which append themselves to
  every process that can run in the shell. For any command or program that you
  run, you will be able to access `0`, `1` and `2` for them. In this way they are
  similar to variables like
  [`$0`](Passing_arguments_and_options_to_Bash_scripts.md#passing-arguments)
  and
  [`$@`](Passing_arguments_and_options_to_Bash_scripts.md#passing-arguments).
  They have a universal meaning within the context of the shell runtime.


title: database
href: zk/Basic_database_concepts.md
type: markdown
snippet:
  A filesytem is a form of [database](Basic_database_concepts.md); it
  > supplies the structure to transform a simple block device into the
  > sophisticated hierarchy of files and subdirectories that users can understand.


title: swap
href: zk/Swap_space.md
type: markdown
snippet:
  It shows my root and home filesystems and my
  [swap](Swap_space.md) file. Note that we use the UUID
  to name the partition rather than its name in `/dev/`. The order of the
  parameters is as follows:


title: printing-values-in-c
href: zk/printing-values-in-c.md
type: markdown
snippet:
  Format specifiers define the type of data to be printed on standard output. You
  need to use format specifiers whenever you are
  [printing-values-in-c](printing-values-in-c.md).


title: cherry-picking
href: zk/Cherry_picking_a_branch.md
type: markdown
snippet:
  The main difference between the two approaches is that
  [cherry-picking](Cherry_picking_a_branch.md) is a more selective
  process, where you can pick and choose specific commits that you want to include
  in another branch. This can be useful when you only want to apply specific
  changes or fixes from one branch to another, without including all the changes
  made in the original branch.


title: sort
href: zk/Sorting_lists_in_Python.md
type: markdown
snippet:
  Assuming the sub-lists have an identical structure, you can
  [sort](Sorting_lists_in_Python.md) them by
  a common property by passing a
  [lambda function](Lambdas_in_Python.md) to
  the `key` value of `sorted()` and `.sort()`.


title: map
href: zk/Map_and_filter_in_Python.md
type: markdown
snippet:
  Below we use
  [map](Map_and_filter_in_Python.md) and a
  [lambda function](Lambdas_in_Python.md) to
  convert the first element of each iner list from a Unix timestamp to a readable
  string:


title: list comprehension
href: zk/List_comprehension_in_Python.md
type: markdown
snippet:
  We could also use
  [list comprehension](List_comprehension_in_Python.md)
  to achieve the same outcome:


title: dictionary comprehension
href: zk/List_comprehension_in_Python.md#dictionary-comprehension
type: markdown
snippet:
  Accordingly, we create a dictionary which uses the unique key in each list as
  the key of each dictionary entry via
  [dictionary comprehension](List_comprehension_in_Python.md#dictionary-comprehension)
  that loops through each value in the inner lists of the multidimensional array.
  We then parse the values of the dictionary into a list.


title: map, filter
href: zk/Map_and_filter_in_Python.md
type: markdown
snippet:
  They are most often used unnamed with the functional methods
  [map, filter](Map_and_filter_in_Python.md)
  and reduce.


title: superuser
href: zk/User_Space.md#root-user-superuser
type: markdown
snippet:
  This is the domain of the [superuser](User_Space.md#root-user-superuser). The
    part of the filesystem that you need sudo priveleges to access and where you
    manage users


title: kernel
href: zk/The_kernel.md
type: markdown
snippet:
  Most standard partition tables allow for primary, extended and logical
  partitions. The primary partition is the part of the harddisk that contains the
  operating system and is thus described as 'bootable' and may be called the 'boot
  partition'. During the bootstrapping process this is injected into memory as the
  [kernel](The_kernel.md).


title: map and filter
href: zk/Map_and_filter_in_Python.md
type: markdown
snippet:
  Since its introduction to the language, the same functionality has become
  achievable by using functional methods like
  [`map` and `filter`](Map_and_filter_in_Python.md),
  utilising [lambdas](Lambdas_in_Python.md)
  however list comprehension is often more straightforward and easier to read.


title: test
href: zk/Test_values_in_Bash.md
type: markdown
snippet:
  Here we pass all the elements of the array to a
  [test](Test_values_in_Bash.md) condition which
  tests for an empty string.


title: function
href: zk/Functions_in_Bash.md
type: markdown
snippet:
  When you pass an array as an argument to a
  [function](Functions_in_Bash.md) it will not
  immediately be understood to be an array.


title: loop through each character in a string
href: zk/Strings_in_Bash.md#loop-through-each-character-in-a-string
type: markdown
snippet:
  We are leveraging this aspect of Bash when we
  [loop through each character in a string](Strings_in_Bash.md#loop-through-each-character-in-a-string).


title: CPU
href: CPU_architecture
type: wiki-link
snippet:
  No matter how a program was originally written, it eventually needs to execute
  on a [[CPU_architecture|CPU]] as a series of machine language instructions.


title: ARM ISA
href: Instruction_set_architectures
type: wiki-link
snippet:
  The following machine instruction is an instruction that would be understood by
  an [[Instruction_set_architectures| ARM ISA]]. It moves the number `4` into the
  `r7` register:


title: Hexadecimal_number_system
href: Hexadecimal_number_system
type: wiki-link
snippet:
  Binary sequences are hard to understand, even if converted to the
  [[Hexadecimal_number_system]]. We have a better way of managing operations on
  the machine level: [assembly](Assembly.md)


title: global process object
href: zk/Process_object.md
type: markdown
snippet:
  To determine the current environment we can use the variable
  **`process.env.NODE_ENV`** from the
  [global process object](Process_object.md).
  This works universally regardless of the kind of Node app we are building.


title: environment variable
href: zk/Environmental_and_shell_variables.md
type: markdown
snippet:
  `NODE_ENV` is a bash
  [environment variable](Environmental_and_shell_variables.md)
  like any other. So we can set it in the normal way:


title: Config
href: zk/node-config
type: markdown
snippet:
  We use the third-party [Config](node-config)
  package to manage different configurations based on the environment.


title: environmental variables
href: zk/Environmental_and_shell_variables.md
type: markdown
snippet:
  We can do so securely by utilising
  [environmental variables](Environmental_and_shell_variables.md)
  alongside the config pacakage.


title: ports
href: zk/Ports_in_NodeJS.md
type: markdown
snippet:
  We can control which middleware we run via the Node envrionment variables:
  `process.env` (see for instance [ports](Ports_in_NodeJS.md)).


title: module object
href: zk/Modules_in_NodeJS.md#structure-of-a-module
type: markdown
snippet:
  Note that one of these parameters is the
  [module object](Modules_in_NodeJS.md#structure-of-a-module).


title: ps
href: zk/Processes.md
type: markdown
snippet:
  We can use [ps](Processes.md) to list the
  currently running processes but it does not provide much information about the
  resource metrics or how the process changes over time. We can use `top` to get
  more information.


title: virtual memory
href: zk/Virtual_memory_and_the_MMU_in_Linux.md
type: markdown
snippet:
  The total amount of
      [virtual memory](Virtual_memory_and_the_MMU_in_Linux.md) used by
      the process including: program code, data, shared libraries, pages that have
      been swapped, pages that have been mapped but not used.


title: buffer
href: zk/Role_of_memory_in_computation.md#relation-between-cache-and-buffers
type: markdown
snippet:
  Total kbs currently in
        [buffer](Role_of_memory_in_computation.md#relation-between-cache-and-buffers)
        and not written


title: cache
href: zk/Role_of_memory_in_computation.md#relation-between-cache-and-buffers
type: markdown
snippet:
  Total amount of virtual memory in the
        [cache](Role_of_memory_in_computation.md#relation-between-cache-and-buffers)


title: swapped
href: zk/Swap_space.md
type: markdown
snippet:
  Distinguishes amount of memory
      [swapped](Swap_space.md) in (`si`) to memory and
      swapped out (`so`) to disk


title: kernel
href: zk/The_kernel.md
type: markdown
snippet:
  A system call is when a process requests a service from the
  [kernel](The_kernel.md), for instance an I/O operation to
  memory. We can trace these system calls with `strace`.


title: MMU
href: zk/Virtual_memory_and_the_MMU_in_Linux.md
type: markdown
snippet:
  We know that processes primarily interact with virtual memory in the form of
  pages which are then translated to physical blocks by the kernel via the
  [MMU](Virtual_memory_and_the_MMU_in_Linux.md). There are several tools
  which provide windows onto this process.


title: buffers and caches
href: zk/Role_of_memory_in_computation.md#relation-between-cache-and-buffers
type: markdown
snippet:
  `free` displays the total amount of free and¬used physical and swap memory in
  the system, as well as the
  [buffers and caches](Role_of_memory_in_computation.md#relation-between-cache-and-buffers)
  used by the kernel.


title: build context
href: zk/Creating_a_Docker_image.md#creating-a-docker-image
type: markdown
snippet:
  Each of the files listed below would be saved to the same source directory which
  would then form the basis of the
  [build context](Creating_a_Docker_image.md#creating-a-docker-image).


title: process.env
href: zk/Managing_environments_in_NodeJS.md
type: markdown
snippet:
  In the example, the database connection information in the Node source is coming
  from the
  [`process.env`](Managing_environments_in_NodeJS.md)
  object, which itself is sourcing the values `MYSQL_HOST`, `MYSQL_PASSWORD` etc
  from the Docker compose file. Therefore these values are hardcoded there.


title: type-guarding
href: zk/Type_guarding_and_narrowing.md
type: markdown
snippet:
  One way to get around it is to use better
  [type-guarding](Type_guarding_and_narrowing.md) and conditionality and to
  cover cases where the value may be undefined.


title: semantic versioning
href: zk/Semantic_versioning.md
type: markdown
snippet:
  `npm update` only updates from _current_ to _wanted_. In other words it only
  updates in accordance with your caret and tilde rules applied to
  [semantic versioning](Semantic_versioning.md).


title: event listeners
href: zk/Events module.md#event-emitters
type: markdown
snippet:
  While we may not know the specific port, whatever it is, it will be accessible
  via the `PORT` environment variable. So we can use this when writing our
  [event listeners](Events%20module.md#event-emitters):


title: format specifier
href: zk/zk/format-specifiers-in-c.md
type: markdown
snippet:
  The `%d` is an example of a [format specifier](./zk/format-specifiers-in-c.md).
  It is the decimal integer format specifier.


title: event listeners
href: zk/events.md
type: markdown
snippet:
  Typically we want to write and read data that the user provides. To do this we
  need to wait on that event. So we use Node's asynchonous
  [event listeners](events.md). We wait
  on the `data` event:


title: split the contents into an array
href: zk/Split_into_array_in_Bash.md
type: markdown
snippet:
  `read` will parse line by line using a space (`\n`) as the default delimiter.
  You can use IFS to parse by other characters and/or
  [split the contents into an array](Split_into_array_in_Bash.md).


title: find
href: zk/Find_Bash_command.md
type: markdown
snippet:
  Here we use [find](Find_Bash_command.md) to collate the files in
  the current directory and then pipe them to read.


title: file descriptors
href: zk/File_descriptors.md
type: markdown
snippet:
  It is common practice to combine redirection with the
  [file descriptors](File_descriptors.md) to redirect
  the output of `stdout` and `stderr`. A common case is to
  [redirect error output to `/dev/null`](Redirect_to_dev_null.md).


title: AWS Lambda handler function
href: zk/Lambda_handler_function.md
type: markdown
snippet:
  Let's walk through the above example making reference to the general structure
  of the
  [AWS Lambda handler function](Lambda_handler_function.md):


title: kernel
href: zk/The_kernel.md
type: markdown
snippet:
  To use an existing disk partition as a swap you can run the command
  `mkswap [device]` and then `swapon [device]` to register the space with the
  [kernel](The_kernel.md).


title: fstab
href: zk/Filesystems.md#fstab
type: markdown
snippet:
  You will want the swap to be activated every time the OS boots so add the
  following line to the [fstab](Filesystems.md#fstab),
  where `/sda3` is used as the example partition:


title: array
href: zk/Lists_and_arrays_in_Bash.md
type: markdown
snippet:
  Note: this syntax can also be used to test if a given element exists in an
  > [array](Lists_and_arrays_in_Bash.md).


title: clock pulses
href: zk/Clock_signals.md
type: markdown
snippet:
  The circuit will have three memory components, each representing one bit of the
  3-bit number. When the
  [clock pulses](Clock_signals.md), the
  3-bit number increments by one. We need to synchronise the operation with a
  clock because each bit by itself is meaningless, it only gains meaning by the
  relation it sustains to the other two bits hence it must be kept in sync with
  them.


title: T flip-flop
href: zk/Flip_flops.md#t-flip-flops
type: markdown
snippet:
  This means that to construct a circuit that displays this behaviour we just have
  to use a
  [T flip-flop](Flip_flops.md#t-flip-flops)
  since the only state change we need is a single bit toggle three times that
  retains its value.


title: voltage
href: zk/Voltage.md
type: markdown
snippet:
  Thus instead of switches, modern digital circuits use transistors, a special
  electrical component that controls the flow of current in the manner of a switch
  where the 'off' and 'on' states are represented by
  [voltage](Voltage.md) values within
  set parameters.


title: AND
href: zk/Logic_gates.md#and-gate
type: markdown
snippet:
  For example to create an
  [AND](Logic_gates.md#and-gate) gate
  we would have two voltage inputs going into two transistors that are connected
  in sequence. The two transistors create a continuous line going from the
  collector of one to the emitter of the other. If either voltage input is low
  then the voltage of the combined line is low (equivalent to the circuit being
  broken) and there is no current flowing.


title: OR
href: zk/Logic_gates.md#or-gate
type: markdown
snippet:
  Below, an
  [OR](Logic_gates.md#or-gate) has been
  constructed with transistors. If a voltage is applied to the base of either
  transistor, the current reaches the V-out terminal.


title: immediate sentential components
href: zk/Syntax of sentential logic.md
type: markdown
snippet:
  The core truth-tables tell us how to determine the truth-value of a molecular
  > sentence given the truth-values of its
  > [immediate sentential components](Syntax%20of%20sentential%20logic.md). And if
  > the immediate sentential components of a molecular sentence are also
  > molecular, we can use the information in the characteristic truth-tables to
  > determine how the truth-value of each immediate component depends n the
  > truth-values of _its_ components and so on.


title: consistent
href: zk/Consistency.md
type: markdown
snippet:
  Recall that a set of propositions is logically or truth-functionally
  [consistent](Consistency.md) just if there is at least one assignment of truth
  conditions which results in all members of the set being true. To identify
  consistency for a set of three propositions via the truth table approach we
  would need to construct a truth table with $2^3$ (8) rows. Assume that this set
  is consistent on one partial assignment only. This means that 87.5% of our rows
  are redundant, they are not required to prove the consistency of the set.
  However we can only know this and we can only be sure of consistency once we
  have gone through the process of generating an assignment for each row.


title: logical falsity
href: zk/Logical truth and falsity.md#logical-falsity
type: markdown
snippet:
  When we wish to assess
  [logical falsity](Logical%20truth%20and%20falsity.md#logical-falsity) we are not
  focused on sets however, we are interested in a property of a sentence. However
  we can easily construe single sentences as unit sets: sets with a single member.
  With this in mind and the above accounts of consistency and logical falsity we
  are equipped to express logical falsity in terms of truth-trees with the
  following rule:


title: logically true
href: zk/Logical truth and falsity.md#logical-truth
type: markdown
snippet:
  For a sentence $P$ to be
  [logically true](Logical%20truth%20and%20falsity.md#logical-truth), there must
  be no possible assignment in which $P$ is false. We express this informally by
  saying _it is not possible to consistently deny $P$._ We know that in terms of
  truth trees an inconsistent set is a closed tree therefore a unit set of ${ P }$
  is logically true if ${ \sim P }$ is a closed tree. This is to say: if the
  negation of $P$ is inconsistent.


title: Indeterminacy
href: zk/Indeterminacy.md
type: markdown
snippet:
  [Indeterminacy](Indeterminacy.md) follows from the two definitions above; we do
  not require any additional apparatus. We recall that a sentence $P$ is logically
  indeterminate just if it is neither logically true or logically false. Thus the
  truth tree for an indeterminate sentence is straightforward:


title: logically equivalent
href: zk/Logical equivalence.md
type: markdown
snippet:
  Recall that $P$ and $Q$ are [logically equivalent](Logical%20equivalence.md)
  just if there is no truth assignment on which one is true and the other is
  false. We know from the
  [material biconditional shorthand](Corresponding%20material%20and%20biconditional.md#corresponding-material-biconditional)
  that this state of affairs can be expressed as $P \equiv Q$ and that if this
  compound sentence is true on every assignment then both simple sentences are
  equivalent. But ‘true on every assignment’ is another way of saying _logically
  true_ since there is no possibility of a false assignment. We already know what
  logical truth looks like as a truth tree: it is a closed tree for the negation
  of the sentence being tested. Therefore, to test the logical equivalence of two
  sentences it is necessary to construct a truth tree for the negation of the
  sentences conjoined by the biconditional (i.e. $\sim (P \equiv Q)$ )and see if
  this results in a closed tree. If it does, the two sentences are logically
  equivalent.


title: entailment
href: zk/Validity and entailment.md#entailment
type: markdown
snippet:
  Let’s remind ourselves of the meaning of truth-functional
  [entailment](Validity%20and%20entailment.md#entailment) and
  [validity](Validity%20and%20entailment.md#validity) and the relation between the
  two. $\Gamma$ $\vdash$ $P$ is true if and only if there is no truth-assignment
  in which every member of $\Gamma$ is true and $P$ is false. Entailment is
  closely related to validity; it is really just a matter of emphasis: we say that
  $\Gamma$ are the premises and $P$ is the conclusion and that this is a valid
  argument if there is no assignment in which every member of $\Gamma$ is true and
  $P$ is false.


title: binary encoding
href: Binary_encoding
type: wiki-link
snippet:
  Two's complement divides the available word length (see
  [[Binary_encoding|binary encoding]]) into two subsets: one for negative integrs
  and one for positive integers.


title: signed_and_unsigned_numbers
href: Signed_and_unsigned_numbers
type: wiki-link
snippet:
  [[Signed_and_unsigned_numbers|signed_and_unsigned_numbers]],
  [[Binary_addition|binary addition]], [[Signed_magnitude_representation]]


title: middlewear
href: zk/Middleware_in_NodeJS.md
type: markdown
snippet:
  Next we introduce GraphQL as a piece of Node.js
  [middlewear](Middleware_in_NodeJS.md), with the
  `app.use()` method.


title: Joi
href: zk/Validation_in_NodeJS.md
type: markdown
snippet:
  What is the relationship between this Mongoose validation and the
  [Joi](Validation_in_NodeJS.md) validation that we
  use when validating API requests in Node/Express? They complement each other. We
  use Joi to validate the client request to the API. If this is valid, the process
  would then move onto the next stage which would be transforming the data from a
  REST request to a database request implemented through Mongoose, where a second
  layer of validation would appy. We would also have validation on the
  client-side.


title: Virtual memory
href: zk/9_VirtualMemory.html#:~:text=Virtual memory also allows the,to more than one process
type: markdown
snippet:
  [Virtual memory](9_VirtualMemory.html#:~:text=Virtual%20memory%20also%20allows%20the,to%20more%20than%20one%20process)


title: zk/Elastic_Compute_Cloud
href: zk/Elastic_Compute_Cloud
type: wiki-link
snippet:
  AWS VPC is used to create a virtual network. This is typically used in concert
  with [[zk/Elastic_Compute_Cloud]] to manage connections to a virtual server both
  privately and accross the internet.


title: partitions
href: zk/Partitions.md
type: markdown
snippet:
  A disk is divided up into [partitions](Partitions.md)
    which are subsections of the overall disk. The kernel presents each partition
    as a [block device](Devices.md) as it would with an entire
    disk.


title: user space
href: zk/User_Space.md
type: markdown
snippet:
  The **filesystem** is a database of files and directories: this comprises the
    bulk of the partition and is what you interact with in
    [user space](User_Space.md) when reading and writing data.


title: event queue
href: zk/Event_loop.md
type: markdown
snippet:
  Every method associated with `fs` has a _blocking_ and _asynchronous_
  implementation. The former obviously blocks the
  [event queue](Event_loop.md), the
  latter does not.


title: event emitter
href: zk/events.md
type: markdown
snippet:
  An HTTP server is another instance of an
  [event emitter](events.md)). It
  therefore has all the same methods as the `EventEmitter` class: `on`, `emit`,
  `addListener` etc. This demonstrates again how much of Node's core functionality
  is based on event emitters.


title: Zettelkasten
href: https://en.wikipedia.org/wiki/Zettelkasten
type: markdown
snippet:
  It is a [Zettelkasten](https://en.wikipedia.org/wiki/Zettelkasten) work in
  progress. I've recently converted the topic-based subdirectories into a single
  flat directory structure organised by tags. I'm in the process of partitioning
  longer notes into smaller units.


title: zk
href: https://github.com/zk-org/zk
type: markdown
snippet:
  I use the [zk](https://github.com/zk-org/zk) CLI package to help with indexing
  and task automation alongside its [zk-nvim](https://github.com/zk-org/zk-nvim)
  Neovim wrapper. I occassionally utilise [Obsidian](https://obsidian.md/)
  alongside Neovim for when I want to view my notes as a knowledge graph or read
  them alongside their rich content (images, videos etc).


title: scripts
href: scripts
type: markdown
snippet:
  The [scripts](/scripts) directory contains several Bash and Python scripts I use
  for general housekeeping, such as formatting image URLs, removing unused assets,
  and autosaving.


title: filesystem
href: zk/Filesystems.md
type: markdown
snippet:
  You see the GRUB default menu when you first start a Linux machine. It will
  offer you various options for loading your installed OS or other OSs. GRUB is a
  [filesystem](./Filesystems.md) like the main disk. If you press `e` in this
  screen you can view and edit specific boot parameters. Pressing `c` gives you
  access to the GRUB command line interface. This allows you to interact with GRUB
  in the same way as you would with any other filesystem, allowing for advanced
  configuration.


title: process id
href: zk/Processes.md#processes-ps
type: markdown
snippet:
  The kernel starts a program called **init**. It has a
     [process id](Processes.md#processes-ps) of 1. This is the point at which
     [user space](User_Space.md) starts.


title: journal
href: zk/journald.md
type: markdown
snippet:
  Linux keeps a log of the boot process as part of the [journal](./journald.md)
  log of everything that happens on disk. We can use the command `journalct -k` to
  view the diagnostics generated during the boot. Here is a selection:


title: https://www.geeksforgeeks.org/user-mode-and-kernel-mode-switching/
href: https://www.geeksforgeeks.org/user-mode-and-kernel-mode-switching/
type: implicit
snippet:
  !! Add info on kernel mode and user mode
  https://www.geeksforgeeks.org/user-mode-and-kernel-mode-switching/


title: memory management unit
href: zk/Virtual_memory_and_the_MMU_in_Linux.md#the-memory-management-unit-mmu
type: markdown
snippet:
  Modern CPUs include a
  > [memory management unit](Virtual_memory_and_the_MMU_in_Linux.md#the-memory-management-unit-mmu)
  > which provides the kernel with **virtual** memory. In this scenario, memory
  > isn't directly accessed by the process instead it works on the assumption that
  > is has access to the entire memory of the machine and this is then translated
  > into a map that is applied to the real memory and managed by the kernel.


title: foreign_keys
href: zk/Foreign_keys_in_SQL.md
type: markdown
snippet:
  DynamoDB is "NoSQL" because it does not support #SQL queries and is
  non-relational meaning there cannot be JOIN operations via
  [foreign_keys](Foreign_keys_in_SQL.md)


title: resistor
href: zk/Resistance.md#resistors
type: markdown
snippet:
  An LED diode lights up when the right amount of current flows through it. A
  standard LED has a maximum current of 20mA. An appropriate
  [resistor](Resistance.md#resistors)
  must therefore be added to the circuit to ensure the current doesn't exceed this
  amount.


title: listener
href: zk/Node_JS_events_module.md#extending-the-eventemitter-class
type: markdown
snippet:
  We instantiate an `ApolloServer` instance and pass our schema to it. We then
  subscribe to it with a
  [listener](Node_JS_events_module.md#extending-the-eventemitter-class).


title: function
href: zk/Creating_a_GraphQL_server.md#resolvers
type: markdown
snippet:
  A resolver is a [function](Creating_a_GraphQL_server.md#resolvers) that
  populates data for a given query. It should have **the same name as the field
  for the query**. So far we have one query in our schema: `tracksForHome` which
  returns the tracks to be listed on the home page. We must therefore also name
  our resolver for this query `tracksForHome`.


title: generic example
href: zk/Creating_a_GraphQL_server.md#resolvers
type: markdown
snippet:
  As per the [generic example](Creating_a_GraphQL_server.md#resolvers), you
  write write your resolvers as keys on a `resolvers` object, e.g:


title: resolver chains
href: zk/Using_arguments_with_Apollo_Client.md#resolver-chains
type: markdown
snippet:
  Used with
      [resolver chains](Using_arguments_with_Apollo_Client.md#resolver-chains)
      ---add example


title: argument
href: zk/Using_arguments_with_Apollo_Client.md
type: markdown
snippet:
  This time we utilise the `args` parameter in the resolver since an `id` will
    be provided as a client-side
    [argument](Using_arguments_with_Apollo_Client.md) to
    return a specific author.


title: REST APIs
href: zk/RESTful_APIs.md#rest
type: markdown
snippet:
  The best way to think of GraphQL architecturally is to think of it as a
  > different technique for instantiating the _uniform interface_, _client/server
  > decoupling_, and _layered-system architecture_ contraints of traditional
  > [REST APIs](RESTful_APIs.md#rest). However, instead of making
  > GET or POST requests to a REST endpoint URL and passing parameters, you send a
  > structured query object.


title: query constants
href: zk/Apollo_Client.md#query-constants
type: markdown
snippet:
  As with queries and
  [query constants](Apollo_Client.md#query-constants) we
  wrap our mutation in a `gql` template string:


