chore: move file under 'misc' folder

This commit is contained in:
Marcello 2023-09-18 10:51:28 +02:00
parent f57b7ed075
commit 1f0748536f
4 changed files with 3 additions and 3 deletions

264
docs/misc/git.md Normal file
View file

@ -0,0 +1,264 @@
# Git
## Glossary
**GIT**: an open source, distributed version-control system
**GITHUB**: a platform for hosting and collaborating on Git repositories
**TREE**: directory that maps names to blobs or trees
**BLOB**: any file
**COMMIT**: snapshot of the entire repository + metadata, identified it's SHA-1 hash
**HEAD**: represents the current working directory, the HEAD pointer can be moved to different branches, tags, or commits when using git checkout
**BRANCH**: a lightweight movable pointer to a commit
**CLONE**: a local version of a repository, including all commits and branches
**REMOTE**: a common repository on GitHub that all team member use to exchange their changes
**FORK**: a copy of a repository on GitHub owned by a different user
**PULL REQUEST**: a place to compare and discuss the differences introduced on a branch with reviews, comments, integrated tests, and more
**REPOSITORY**: collection of files and folder of a project aka repo
**STAGING AREA/STASH**: area of temporary snapshots (not yet commits)
## Data Model
Data Model Structure:
```txt
<root> (tree)
|
|_ foo (tree)
| |_ bar.txt (blob, contents = "hello world")
|
|_ baz.txt (blob, contents = "git is wonderful")
```
Data Model as pseudocode:
```py
# a file is a bunch of bytes
blob = array<byte>
# a directory contains named files and directories
tree = map<string, tree | file>
# a commit has parents, metadata, and the top-level tree
commit = struct {
parent: array<commit>
author: string
message: string
snapshot: tree
}
# an object is either a blob, tree or commit
object = map<string, blob | tree | commit>
# commit identified by it's hash (unmutable)
def store(object):
id = sha1(object) # hash repo
objects<id> = object # store repo w/ index hash
# load the commit
def load(id):
return objects<id>
# human-readable names for SHA-1 hashes (mutable)
references = map<string, string>
# bind a reference to a hash
def update_reference(name, id):
references<name> = id
def read_reference(name):
return references<name>
def load_reference(name_or_id):
if name_or_id in references:
return load(references<name_or_id>)
else:
return load(name_or_id)
```
## Commands
`git <command> -h`: get help for a git command
`git <command> --help`: get man page for a git command
`git -C <path> <command>`: execute a git commend in the specified path
`git <command> <commit>^`: operate on commit *before* the provided commit hash
### Create Repository
`git init [<project_name>]`: initialize a brand new Git repository and begins tracking
`.gitignore`: specify intentionally untracked files to ignore
### Config
`git config --global user.name "<name>"`: set name attached to commits
`git config --global user.email "<email address>"`: set email attached to commits
`git config --global color.ui auto`: enable colorization of command line output
### Making Changes
`git status`: shows the status of changes as untracked, modified, or staged
`git add <filename1 filename2 ...>`: add files to the staging area
`git add -p <files>`: interactively stage chunks of a file
`git blame <file>`: show who last edited which line
`git commit`: save the snapshot to the project history
`git commit -m "message"`: commit and provide a message
`git commit -a`: automatically notice any modified (but not new) files and commit
`git commit -v|--verbose`: show unified diff between the HEAD commit and what would be committed
`git commit --amend`: modify latest commit with the new changes
`git commit --no-verify`: commit without executing hooks
`git commit --fixup <commit>`: mark commit as correction to another
`git diff <filename>`: show difference since the last commit
`git diff <commit> <filename>`: show differences in a file since a particular snapshot
`git diff <reference_1> <reference_2> <filename>`: show differences in a file between two snapshots
`git diff --cached`: show what is about to be committed
`git diff <first-branch>...<second-branch>`: show content diff between two branches
`git diff -w`: show diff ignoring whitespace differences
`git bisect`: binary search history (e.g. for regressions)
### Stashes
`git stash [push -m|--message]`: add all changes to the stash (and provide message)
`git stash list` list all stashes
`git stash show [<stash>]`: show changes in the stash
`git stash pop`: restore last stash
`git stash drop [<stash>]`: remove a stash from the list
`git stash clear`: remove all stashes
### Remotes
`git remote`: list remotes
`git remote -v`: list remotes names and URLs
`git remote show <remote>`: inspect the remote
`git remote add <remote> <url | path>`: add a remote
`git remote remove <remote>`: remove the specified remote
`git remote rename <old_name> <new_name>`: rename a remote
`git branch --set-upstream-to=<remote>/<remote branch>`: set up correspondence between local and remote branch
`git push`: send objects to default remote on current branch
`git push <remote> <branch>`: send objects to remote
`git push <remote> <local branch>:<remote branch>`: send objects to remote, and update remote reference
`git push --force`: overwrite remote with local version
`git push --force-with-lease`: overwrite remote with local version if remote has not been modified
`git push --force-with-lease --force-if--includes`: will verify if updates from the remote that may have been implicitly updated in the background are integrated locally before allowing a forced update
`git fetch [<remote>]`: retrieve objects/references from a remote
`git pull`: update the local branch with updates from its remote counterpart, same as `git fetch; git merge`
`git pull --ff`: when possible resolve the merge as a fast-forward (only update branch pointer, don't create merge commit). Otherwise create a merge commit.
`git fetch|pull --prune`: remove any remote-tracking references that no longer exist on the remote
`git fetch|pull --tags`: fetch all tags from the remote
`git clone <url> [<folder_name>]`: download repository and repo history from remote
`git clone --shallow`: clone only repo files, not history of commits
> **Note**: for a in depth explanation of `--force-if-includes` see [this][force-if-includes]
### Viewing Project History
`git log`: show history of changes
`git log -p`: show history of changes and complete differences
`git log --stat --summary`: show overview of the change
`git log --follow <file>`: list version history fo file, including renames
`git log --all --graph --decorate`: visualizes history as a DAG
`git log --oneline`: compact log
`git log <rev>`: Include commits that are reachable from `<rev>`
`git log ^<rev>`: Exclude commits that are reachable from `<rev>`
`git log <rev1>..<rev2>`: Include commits that are reachable from `<rev2>` but exclude those that are reachable from `<rev1>`.
When either `<rev1>` or `<rev2>` is omitted, it defaults to HEAD.
`git log <rev1>...<rev2>`: Include commits that are reachable from either `<rev1>` or `<rev2>` but exclude those that are reachable from both. When either `<rev1>` or `<rev2>` is omitted, it defaults to HEAD.
`git log <rev>^@`: Include anything reachable from `<rev>` parents but not the commit itself
`git shortlog`: list commits by author
`git reflog`: show record of when the tips of branches and other references were updated in the local repository
`git show <commit>`: output metadata and content changes of commit
`git cat-file -p <commit>`: output commit metadata
### Tag
Git supports two types of tags: *lightweight* and *annotated*.
A lightweight tag is very much like a branch that doesn't change—it's just a pointer to a specific commit.
Annotated tags, however, are stored as full objects in the Git database.
They're checksummed;contain the tagger name, email, and date; have a tagging message; and can be signed and verified with GNU Privacy Guard (GPG).
It's generally recommended creating annotated tags so it's possible to have all this information.
`git tag`: list existing tags
`git tag -l|--list <pattern>`: list existing tags matching a wildcard or pattern
`git tag <tag> [<commit_hash>]`: create a *lightweight* tag on the commit
`git tag -a <tag> [<commit_hash> -m <message>]`: create am *annotated* tag on the commit
`git push <remote> <tagname>`: push a tag to the remote
`git push <remote> --tags`: push commits and their tags (both types) to the remote
`git tag -d <tagname>`: delete a tag
`git push <remote> :refs/tags<tagname>:`: remove a tag from the remote
`git push <remote> --delete <tagname>`: remove a tag from the remote
`git checkout <tag>`: checkout a tag - **WARNING**: will go into *detached HEAD*
### Branching And Merging
![branch](img/git_branches.png "how branches work")
`git branch`: shows branches
`git branch -vv`: show branch + last commit + remote status
`git branch --merged [--remote]`: show branches (remote) that have been merged into current one (needs same history, merge squash/rebase break history)
`git branch <branch-name>`: create new branch
`git checkout -b <branch-name>`: create a branch and switches to it, same as `git branch <name>; git checkout <name>`
`git branch`: show list of all existing branches (* indicates current)
`git checkout <branch-name>`: change current branch (update HEAD) and update working directory
`git branch -d <branch-name>`: delete specified branch
`git branch -m <old_name> <new_name>`: rename a branch without affecting the branch's history
`git merge <branch-name>`: merges into current branch
`git merge --continue`: continue previous merge after solving a merge conflict
`git mergetool`: use a fancy tool to help resolve merge conflicts
`git rebase <branch>`: rebase current branch commits onto another branch
`git cherry-pick <commit>`: bring in a commit from another branch
`git cherry-pick <commit>^..<commit>`: bring in a range of commits from another branch (first included)
`git cherry-pick <commit>..<commit>`: bring in a range of commits from another branch (first excluded)
### Undo & Rewriting History
`git rm -r --cached <file>`: remove a file from being tracked
`git commit --amend`: replace last commit by creating a new one (can add files or rewrite commit message)
`git commit --amend -m "amended message"`: replace last commit by creating a new one (can add files or rewrite commit message)
`git commit --amend --no-edit`: replace last commit by creating a new one (can add files or rewrite commit message)
`git reset HEAD <file>`: unstage a file
`git reset <commit>`: undo all commits after specified commit, preserving changes locally
`git reset --soft <commit>`: revert to specific commit but keep changes and staged files
`git reset --hard <commit>`: discard all history and changes back to specified commit
`git checkout <file>`: discard changes
`git checkout -- <file>`: discard changes, no output to screen
`git restore .`: discard uncommitted changes
`git restore <file>`: discard uncommitted changes to file
`git restore --source <commit> <file>`: revert file to commit version
`git restore <deleted-file>`: recover deleted file if previously committed
`git rebase -i`: modify (reword, edit, drop, squash, merge, ...) current branch commits
`git rebase -i HEAD~<n>`: modify (reword, edit, drop, squash, merge, ...) *n* commits
`git rebase -i <commit>`: modify (reword, edit, drop, squash, merge, ...) *from* commit to latest
`git rebase --autostash`: automatically create a temporary stash entry before rebasing
`git rebase --autosquash`: automatically apply "squash!" or "fixup!" or "amend!" commits
> **WARN**: Changing history can have nasty side effects
<!-- links -->
[force-if-includes]: https://stackoverflow.com/a/65839129 "git --force-if-includes explanation"

384
docs/misc/graph-ql.md Normal file
View file

@ -0,0 +1,384 @@
# GraphQL
[How to GraphQL - The Fullstack Tutorial for GraphQL](https://www.howtographql.com/)
GraphQL is a query language for APIa, and a server-side runtime for executing queries by using a type system for the data. GraphQL isn't tied to any specific database or storage engine and is instead backed by existing code and data.
A GraphQL service is created by defining types and fields on those types, then providing functions for each field on each type.
---
## Schema and Types
### Object types and fields
The most basic components of a GraphQL schema are object types, which just represent a kind of object fetchable from the service, and what fields it has.
```graphql
type Type {
field: Type
field: Type! # non-nullable type
field: [Type] # array of objects
field: [Type!]! # non-nullable array of non-nullable objects
}
```
### Field Arguments
Every field on a GraphQL object type can have zero or more arguments. All arguments are named.
Arguments can be either *required* or *optional*. When an argument is optional, it's possible to define a default value.
```graphql
type Type {
field: Type,
field(namedArg: Type = defaultValue): Type
}
```
### Query and Mutation types
Every GraphQL service has a `query` type and may or may not have a `mutation` type. These types are the same as a regular object type, but they are special because they define the *entry point* of every GraphQL query.
### Scalar Types
A GraphQL object type has a name and fields, but at some point those fields have to resolve to some concrete data.
That's where the scalar types come in: they represent the *leaves* of the query. Scalar types do not have sub-types and fields.
GraphQL comes with a set of default scalar types out of the box:
- `Int`: A signed 32bit integer.
- `Float`: A signed double-precision floating-point value.
- `String`: A UTF8 character sequence.
- `Boolean`: `true` or `false`.
- `ID`: The ID scalar type represents a unique identifier, often used to refetch an object or as the key for a cache. The ID type is serialized in the same way as a `String`; however, defining it as an `ID` signifies that it is not intended to be humanreadable.
In most GraphQL service implementations, there is also a way to specify custom scalar types.
```graphql
scalar ScalarType
```
Then it's up to the implementation to define how that type should be serialized, deserialized, and validated.
### Enumeration Types
Also called *Enums*, enumeration types are a special kind of scalar that is restricted to a particular set of allowed values.
This allows to:
1. Validate that any arguments of this type are one of the allowed values
2. Communicate through the type system that a field will always be one of a finite set of values
```graphql
enum Type{
VALUE,
VALUE,
...
}
```
**Note**: GraphQL service implementations in various languages will have their own language-specific way to deal with enums. In languages that support enums as a first-class citizen, the implementation might take advantage of that; in a language like JavaScript with no enum support, these values might be internally mapped to a set of integers. However, these details don't leak out to the client, which can operate entirely in terms of the string names of the enum values.
## Lists and Non-Null
Object types, scalars, and enums are the only kinds of types that can be defined in GraphQL.
But when used in other parts of the schema, or in the query variable declarations, it's possible apply additional *type modifiers* that affect **validation** of those values.
It's possible to mark a field as *Non-Null* by adding an exclamation mark, `!` after the type name. This means that the server always expects to return a non-null value for this field, and if it ends up getting a null value that will actually trigger a GraphQL execution error, letting the client know that something has gone wrong.
The *Non-Null* type modifier can also be used when defining arguments for a field, which will cause the GraphQL server to return a validation error if a null value is passed as that argument, whether in the GraphQL string or in the variables.
It's possible to use a type modifier to mark a type as a `List`, which indicates that this field will return an array of that type. In the schema language, this is denoted by wrapping the type in square brackets, `[` and `]`. It works the same for arguments, where the validation step will expect an array for that value.
### Interfaces
Like many type systems, GraphQL supports interfaces. An Interface is an abstract type that includes a certain set of fields that a type must include to implement the interface.
Interfaces are useful when returning an object or set of objects, but those might be of several different types.
```graphql
interface Interface {
fieldA: TypeA
fieldB: TypeB
}
type Type implements Interface {
fieldA: TypeA,
fieldB: TypeB
field: Type,
...
}
```
### Union Type
Interfaces are useful when returning an object or set of objects, but those might be of several different types.
```graphql
union Union = TypeA | TypeB | TypeC
```
**Note**: members of a union type need to be *concrete* object types; it's not possible to create a union type out of interfaces or other unions.
### Input Type
In the GraphQL schema language, input types look exactly the same as regular object types, but with the keyword input instead of type:
```graphql
input Input {
field: Type,
...
}
```
The fields on an input object type can themselves refer to input object types, but it's not possible to mix input and output types in the schema.
Input object types also can't have arguments on their fields.
---
## Queries, Mutations and Subscriptions
### Simple Query
```graphql
{
field { # root field
... # payload
}
}
```
```json
{
"data" : {
"field": {
...
}
}
}
```
### Query Arguments
In a system like REST, it's possible to only pass a single set of arguments - the query parameters and URL segments in your request.
But in GraphQL, every field and nested object can get its own set of arguments, making GraphQL a complete replacement for making multiple API fetches.
It's aldo possible to pass arguments into scalar fields, to implement data transformations once on the server, instead of on every client separately.
```graphql
{
fieldA(arg: value) # filter results
fieldB(arg: value)
...
}
```
### Aliases
```graphql
{
aliasA: field(arg: valueA) {
field
}
aliasB: field(arg: valueB) {
field
}
}
```
### Fragments
Fragments allow to construct sets of fields, and then include them in queries where that are needed.
The concept of fragments is frequently used to split complicated application data requirements into smaller chunks.
```graphql
{
aliasA: field(arg: valueA) {
...fragment
},
aliasB: field(arg: valueB) {
...fragment
}
}
# define a set of fields to be retrieved
fragment fragment on Type {
field
...
}
```
### Using variables inside fragments
It is possible for fragments to access variables declared in the query or mutation.
```graphql
query Query($var: Type = value) {
aliasA: field(arg: valueA) {
...fragment
}
aliasB: field(arg: valueB) {
...fragment
}
}
fragment fragment on Type{
field
field(arg: $var) {
field
...
}
}
}
```
### Operation Name
The *operation type* is either `query`, `mutation`, or `subscription` and describes what type of operation it's intended to be done. The operation type is required unless when using the *query shorthand syntax*, in which case it's not possible to supply a name or variable definitions for the operation.
The *operation name* is a meaningful and explicit name for the operation. It is only required in multi-operation documents, but its use is encouraged because it is very helpful for debugging and server-side logging. When something goes wrong it is easier to identify a query in the codebase by name instead of trying to decipher the contents.
```graphql
query Operation {
...
}
```
### Variables
When working with variables, three things need to be done:
1. Replace the static value in the query with `$variableName`
2. Declare `$variableName` as one of the variables accepted by the query
3. Pass `variableName: value` in the separate, transport-specific (usually JSON) variables dictionary
```graphql
query Operation($var: Type = defaultValue) {
field(arg: $var) {
field
...
}
}
```
All declared variables must be either *scalars*, *enums*, or *input* object types. So to pass a complex object into a field, the input type that matches on the server must be known.
Variable definitions can be *optional* or *required*. If the field requires a non-null argument, then the variable has to be required as well.
Default values can also be assigned to the variables in the query by adding the default value after the type declaration. When default values are provided for all variables, it's possible to call the query without passing any variables. If any variables are passed as part of the variables dictionary, they will override the defaults.
### Directives
A directive can be attached to a field or fragment inclusion, and can affect execution of the query in any way the server desires.
The core GraphQL specification includes exactly two directives, which must be supported by any spec-compliant GraphQL server implementation:
- `@include(if: Boolean)` Only include this field in the result if the argument is `true`.
- `@skip(if: Boolean)` Skip this field if the argument is `true`.
Server implementations may also add experimental features by defining completely new directives.
### Mutations
Operations of mutations:
- **Creating** new data
- **Updating** existing data
- **Deleting** existing data
```graphql
mutation Operation {
createObject(arg: value, ...) {
field
..
}
}
```
### Subscriptions
Open a stable connection with the server to receive real-time updates on the operations happening.
```graphql
subscription Operation {
event { # get notified when event happens
field # data received on notification
...
}
}
```
### Inline Fragments
If you are querying a field that returns an interface or a union type, you will need to use inline fragments to access data on the underlying concrete type. Named fragments can also be used in the same way, since a named fragment always has a type attached.
```graphql
query Operation($var: Type) {
field(arg: $var) { # interface of union
field
... on ConcreteTypeA {
fieldA
}
... on ConcreteTypeB{
fieldB
}
}
}
```
### Meta Fields
GraphQL allows to request `__typename`, a meta field, at any point in a query to get the name of the object type at that point.
```graphql
{
field(arg: value) {
__typename
... on Type {
field
}
}
}
```
---
## Execution
After being validated, a GraphQL query is executed by a GraphQL server which returns a result that mirrors the shape of the requested query, typically as JSON.
Each field on each type is backed by a function called the *resolver* which is provided by the GraphQL server developer. When a field is executed, the corresponding *resolver* is called to produce the next value.
If a field produces a scalar value like a string or number, then the execution completes. However if a field produces an object value then the query will contain another selection of fields which apply to that object. This continues until scalar values are reached. GraphQL queries always end at scalar values.
### Root fields and Resolvers
At the top level of every GraphQL server is a type that represents all of the possible entry points into the GraphQL API, it's often called the *Root* type or the *Query* type.
```graphql
# root types for entry-points
type Query {
rootField(arg: Type = defValue, ...): Type
... # other query entry points
}
type Mutation {
rootField(arg: Type = defValue, ...): Type
... # other mutation entry points
}
type Subscription {
rootField(arg: Type = defValue, ...): Type
... # other subscription entry points
}
```
A resolver function receives four arguments:
- `obj` The previous object, which for a field on the root Query type is often not used.
- `args` The arguments provided to the field in the GraphQL query.
- `context` A value which is provided to every resolver and holds important contextual information like the currently logged in user, or access to a database.
- `info` A value which holds field-specific information relevant to the current query as well as the schema details

View file

@ -0,0 +1,66 @@
# Common Regex Syntax
## Character Types
`\d` any digit (0-9)
`\D` any non digit character
`\s` whitespace (space, tab, new line)
`\S` any non whitespace characters
`\w` any alphanumeric character (a-z, A-Z)
`\W` any non alphanumeric character
`\b` whitespace surrounding words (only at row start or end)
`\B` whitespace surrounding words (not at row start or end)
`\A` search only at string start
`\Z` search only at string end
`.` any characters but newline (CRLF, CR, LF)
## Quantifiers
`+` one or more repetitions
`*` zero or more repetitions
`?` zero or one repetition
`{m}` exactly *m* times
`{m, n}` at least *m* times, at most *n* times
The `*`, `x`, and `?` qualifiers are all greedy; they match as much text as possible
Adding `?` *after* the qualifier makes it perform the match in non-greedy or minimal fashion; as few characters as possible will be matched.
## Special Characters
`\a, \b, \f, \n, \r, \t, \u, \U, \v, \x, \\, \?, \*, \+ , \., \^, \$` special characters
`\(`, `\)`, `\[`, `\]` brackets escaping
## Delimiters
`^` match must be at start of string/line
`$` match must be at end of string/line
`^__$` match must be whole string
## Character classes
`[__]` one of the characters in the class (`[ab]` --> a or b)
`[__]{m , n}` consecutive characters in the class (`[aeiou]{2}` --> ae, ao, ...)
`[a-z]` sequence of lowercase characters
`[A-Z]` sequence of uppercase characters
`[a-zA-Z]` sequence of lowercase or uppercase characters
`[a-z][A-Z]` sequence of lowercase characters followed by sequence of uppercase characters
`[^__]` anything but the elements of the class (include `\n` to avoid matching line endings)
`^`, `\`, `-` and `]` must be escaped to be used in classes: `[ \]\[\^\- ]`
## Groups
`(__)` capturing group
`(?:__)` non-capturing group
`(REGEX_1 | REGEX_2)` match in multiple regex (R1 OR R2)
`(?=__)` match only if `__` is next substring
`(?!__)` match only if `__` is not next substring
`(?<=__)` match only if `__` is previous substring
`(?<!__)` match only if `__` is not previous substring
`\<number>` refers to n-th group
## Special Cases
`(.*)` match anything
`(.*?)` match anything, non-greedy match