Shreyas Minocha’s Wiki
Welcome to my wiki.
At the moment, it contains mostly programming-related stuff.
Some pages may be empty (save for a heading). These pages serve as placeholders for future content.
License
Computer Science
Math
Linear Algebra
Vectors
- Physics Student
- Arrows with direction and magnitude
- Can freely be panned in space without changing their meaning
- CS Student
- Lists
- Math Student
- Support the operations:
- Vector addition
- Multiplication of a vector by a scalar
- Abstract
- Support the operations:
Inter-convertible.
Calculus
Single Variable Calculus
Privacy
Hosting an onion mirror
Mining onions
Install eschalot.
./eschalot -t4 -v -p prefix
- 4 threads
- verbose
- prefix
prefix
eotk
Not anonymous
Place the private key generated by eschalot in secrets.d/a2s3c4d5e6f7g8h9.key
, replacing a2s3c4d5e6f7g8h9
with the domain found by eschalot.
Create a2s3c4d5e6f7g8h9.conf
:
set project project-name
hardmap secrets.d/a2s3c4d5e6f7g8h9.key clearnet.example.com
eotk config a2s3c4d5e6f7g8h9.conf
eotk start project-name
nginx
must be installed and in PATH
.
The user running eotk
must be the owner of secrets.d
and a2s3c4d5e6f7g8h9.conf
See also: The Onion Diaries
Programming
Bourne-Again Shell
for DATE in "2020-06-22 2020-06-27 2020-07-02 2020-07-17"; do
echo "$DATE"
done
cron
minute / hour / dOM / month / dOW
global:
-
*
— any value -
,
— set of values -
-
— value range -
minute
1
–59
-
hour
0
–23
-
dOM
1
–31
-
month
1
–12
JAN
–DEC
-
dOW
0
–6
SUN
–SAT
# For scripts that don't need root privileges
crontab -e
# For scripts that need to be run as root
sudo crontab -e
0 0 * * * command
0 0 1 * * certbot renew
Links
- https://crontab.guru
CSS
Make list items wrap vertically
Use column-count
.
.container {
column-count: 8;
}
Grid
div#container
header
aside
main
footer
#container {
display: grid;
grid-template-areas:
"left header header"
"left content content"
"footer footer footer";
}
header { grid-area: header; }
aside { grid-area: left; }
main { grid-area: content; }
footer { grid-area: footer; }
Center things
.hero {
display: grid;
place-items: center;
}
date
# identical to `date +%Y-%m-%d`
date +%F
Docker
Deploying a container
docker pull foo/bar
docker run -p <host>:<container> -d foo/bar
docker run -p <host>:<container> -e x='y' -e port='9000' -d foo/bar
docker ps
docker logs a344d52bc2f2
docker stop a344d52bc2f2
Creating a container
docker build -t foo/bar .
Eleventy
npm i -g @11ty/eleventy
-
.eleventy.js
-
.eleventyignore
-
dir
input
output
includes
layouts
data
conf.addPassthroughCopy({
static: '/'
});
Setting a layout for a collection
If the collection is collection/
, set common keys in collection/collection.json
:
{
"tags": "collection",
"layout": "../layouts/collection.pug"
}
Frontmatter keys in layout files
They’re globals.
---
name: Foo
chairperson: bar
---
extends /layouts/base.pug
block content
p=name
p=chairperson
Fish
Loops
for file in *.txt;
echo "$file";
end
while read word;
echo "$word"
end < /usr/share/dict/words
while test -f foo;
true
end
Conditions
if test $status -ne 0;
echo "oop—"
end
-eq
-ne
-gt
-ge
-lt
-le
-f
-d
if ...;
echo something
else if ...;
echo something_else
else;
echo something_else_altogether
end
Variables
set foo hi
-l
— scoped local to the current block-g
— global scope-x
— environment variable
Command Substitution
set total (math "$total+1")
Gatsby
Git
Commit case-change file renames
git mv -f README.md readme.md
GPG sign commits
[user]
…
email = example@example.com
signingkey = 00000000
Verify commits
git verify-commit c567d83
Rename branches
git branch -m old new
Githooks
Executing local hooks from global hooks
#!/usr/bin/env bash
if [ -e ./.git/hooks/commit-msg ]; then
./.git/hooks/commit-msg "$@"
fi
…
Hooks won’t work
chmod +x
?
Push to upstream by default
Just set your
push.default
toupstream
to push branches to their upstreams (which is the same that pull will pull from […]), rather than pushing branches to ones matching in name (which is the default setting forpush.default
— matching).
[push]
default = upstream
Useful for easily pushing to a remote branch with a name different from that of the local branch. Long-form method:
git push origin local-branch:remote-branch
Patches
Generating patches
git format-patch --to example@example.com head~..head
Applying patches
git apply 0001-Example.patch
git am 0001-Example.patch
send-email
[sendemail]
smtpserver = mail.example.com
smtpuser = foo
smtpencryption = tls
smtpserverport = 587
from = foo-alias@example.com
confirm = auto
git send-email --to '~sircmpwn/email-test-drive@lists.sr.ht' head^
git send-email --annotate -v2 head^
Subdirectory filter
See Move files from one repository to another, preserving git history.
Git Internals
Git is not magic.
Git is fundamentally a content-addressable filesystem with a VCS user interface written on top of it.
“Porcelain” — Higher-level, more user-friendly commands.
“Plumbing” — Lower-level commands meant for interfacing with the VCS toolkit.
$ ls -F1 .git
config
— project-specific configurationindex
— git stores staging index information in this fileHEAD
— points to the currently checked-out branchhooks/
— client-side and server-side hooksinfo/
— global exclude fileobjects/
— stores contentrefs/
— “stores pointers into commit objects in that data (branches, tags, remotes and more)”
Objects
[A]t the core of Git is a simple key-value data store. What this means is that you can insert any kind of content into a Git repository, for which Git will hand you back a unique key you can use later to retrieve that content.
Blob
Git is similar to the UNIX file system in some ways. However, git was designed to work with files that don’t change often. File content is saved as a “blob” in git. Two files with the same content anywhere in the world will be stored as the same blob by git. The blob does not store metadata such as the file’s name or mode.
git hash-object
takes a file, optionally writes it to the database (with -w
), and prints the 40-character SHA checksum hash by which it will be identified. The checksum itself is a checksum of the file contents along with a header.
$ echo 'foo' > a.txt
$ echo 'foo' > b.txt
$ git init
$ git hash-object -w a.txt
257cc5642cb1a054f08cc83f2d943e56fd3ebe99
$ git hash-object -w b.txt
257cc5642cb1a054f08cc83f2d943e56fd3ebe99
$ find .git/objects -type f
The above lists “files” in .git/objects
. For example, .git/objects/25/7cc5642cb1a054f08cc83f2d943e56fd3ebe99
. 25
are the first two characters of the hash, 7cc5642cb1a054f08cc83f2d943e56fd3ebe99
are the other 38. Git presumably does this subdirectory-thing to avoid constraints imposed by some filesystems on the maximum number of files in a directory.
$ git cat-file -t 257cc5642cb1a054f08cc83f2d943e56fd3ebe99
blob
$ git cat-file blob 257cc5642cb1a054f08cc83f2d943e56fd3ebe99
foo
$ git cat-file -p 257cc5642cb1a054f08cc83f2d943e56fd3ebe99
foo
Tree
Trees group blobs and store the metadata associated with the blobs. They correspond loosely with the concept of directories in the UNIX filesystem.
$ git cat-file -p 'master^{tree}'
100644 blob 664e5860e5a29097e673e14639dbae33d71098f4 .eslintignore [
100644 blob 0d20ca61dfe1a9ad35862d403aa3e582c21cda51 .eslintrc.yml
100644 blob d124b533c0893da4a15aa5447bf4d5a5583a9fec .gitignore
100644 blob 8a4cf69715b929acd1683ad1fb6af4c5cbd2ff64 .stylelintrc.yml
040000 tree 7c73db8e4c875dbb9c75e54139048f3ce763c89b archetypes
100644 blob b82eeb6841cf2a466ee3c7fcf05cbf829a6a2ca7 config.yml
040000 tree e395cf748a2199479e1d8e835c6fe90066983adb content
100644 blob 8feae855aeb0f392eaad037cf3534fe22a26a525 gulpfile.js
040000 tree 8f4aa58a3fa460e1a52c40f55f8a4749e8ace81f layouts
100644 blob dd85817db646256ba284950fda7ecffd541a42ad package-lock.json
100644 blob 5abbb73bc45270fff66606f0edf0e4bce35c6197 package.json
100644 blob 0c576833121dc7ff51f73b3ad399e2a6ea9b2235 readme.md
040000 tree 6a1072a6112e0903cc8ab48373234bbee4e4acf9 static
Directories are stored as trees.
Git normally creates a tree by taking the state of the index (staging area) and writing a series of tree objects from it. To create a tree manually, we must first set up an index by staging some files.
$ git update-index --add --cacheinfo 100644 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 b.txt
Git’s modes are based on UNIX’s, but are much stricter. The following are the valid modes for files:
Mode | Description |
---|---|
100644 | Normal |
100755 | Executable |
120000 | Symlink |
git write-tree
writes the staging area to a tree.
$ git write-tree
b6643bc0af3fefb3ea606e41cee107ec08fbbed8
$ git cat-file -t b6643bc0af3fefb3ea606e41cee107ec08fbbed8
tree
$ git cat-file -p b6643bc0af3fefb3ea606e41cee107ec08fbbed8
100644 blob 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 b.txt
See also
- https://git-scm.com/book/en/v2/Git-Internals-Plumbing-and-Porcelain
- https://jwiegley.github.io/git-from-the-bottom-up/
Git on a server
SSH daemon must be running, of course and git
must be installed and on the PATH
.
Create a git
user.
Add ssh public keys to their .ssh/authorized_keys
1
Change the git
user’s shell to git-shell
, lest they may wreak havoc.
Optionally, set up:
-
git-http-backend
-
gitweb, gitlist, … whatever you fancy
Consider adding no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty
Permissions after pushes
core.sharedRepository
: group
, all
, or octal permission bits.
git init --bare --shared[=all]
GraphQL
Haskell
Haskell is a purely functional programming language.
Disclaimer: I’m no Haskell expert. These are just notes I’m compiling as I learn Haskell and as such, they may be prone to inaccuracies or glaring errors.
“Functional languages excel at wholemeal programming, a term coined by Geraint Jones. Wholemeal programming means to think big: work with an entire list, rather than a sequence of elements; develop a solution space, rather than an individual solution; imagine a graph, rather than a single path. The wholemeal approach often offers new insights or provides new perspectives on a given problem. It is nicely complemented by the idea of projective programming: first solve a more general problem, then extract the interesting bits and pieces by transforming the general program into more specialised ones.”
—Ralf Hinze
There is no precise, accepted meaning for the term “functional”. But when we say that Haskell is a functional language, we usually have in mind two things:
- Functions are first-class, that is, functions are values which can be used in exactly the same ways as any other sort of value.
- The meaning of Haskell programs is centered around evaluating expressions rather than executing instructions.
About
Haskell:
- is statically typed.
- has type inference.
- is lazy.
- is cool and unique (for people used to OO languages).
Basics
BTW functions (and lots of other stuff) in Haskell are immutable. FP is different from imperative languages in that it doesn’t have the concept of state.
Comments
Comments begin with --
and run till the end of the line.
Basic operators
Arithmetic
+
-
*
/
(float division)
Boolean
&&
||
not
Logical
==
/=
— “≠”>
<
>=
<=
Other
:
— “cons” operator. Adds something to the beginning of a list++
— concatenation operator!!
— list indexing operator. e.g.[1, 2, 3] !! 2
gives3
Basic in-built functions
-
succ
— “successor” -
pred
— “predecessor” -
min
-
max
-
head
— first element of a list -
tail
— all but first element of a list -
last
— last element of a list -
init
— all but last element of a list -
length
-
null
— checks if a list is empty, that is, if it is[]
-
reverse
— reverses a list -
take
—take x y
returns the firstx
elements of listy
-
drop
—drop x y
removes and returns the firstx
elements of listy
-
maximum
— returns the largest element of a list—
minimum
—maximum
s brother -
sum
— ∑ over a list -
products
— ∏ over a list -
elem
— whether an element is in a list -
mod
—mod x y
is the remainder wheny
is divided byx
-
even
-
odd
-
div
— integer division.
Functions can also be called in the infix form. For example, elem 2 [1, 2, 3]
is equivalent to 2 `elem` [1, 2, 3]
.
Functions
ƒ x y = x*y
creates a function ƒ
that “takes two parameters x
and y
“ and returns their product. Quoting to indicate this is not exactly accurate, but suffices for the time-being.
Pattern matching
Pattern matching consists of specifying patterns to which some data should conform and then checking to see if it does and deconstructing the data according to those patterns. When defining functions, you can define separate function bodies for different patterns.
—LYAH
factorial 0 = 1
factorial n = n * factorial (n - 1)
addVectors (x1, y1) (x2, y2) = (x1 + x2, y1 + y2)
length' [] = 0
length' (_:rest) = 1 + length' rest
capital "" = "Empty string"
capital all@(x:xs) = "The first letter of " ++ all ++ " is " ++ [x]
While matching against an expression that uses ++
might be intuitive in some cases, this just can’t be done.
Guards
bmiTell bmi
| bmi <= 18.5 = "Underweight"
| bmi <= 25.0 = "Normal"
| bmi <= 30.0 = "Overweight"
| otherwise = "Obese"
bmiTell weight height
| weight / (height ^ 2) <= 18.5 = "Underweight"
| weight / (height ^ 2) <= 25.0 = "Normal"
| weight / (height ^ 2) <= 30.0 = "Overweight"
| otherwise = "Obese"
Guards can be written inline (often at the cost of readability).
where
bmiTell weight height
| bmi <= 18.5 = "Underweight"
| bmi <= 25.0 = "Normal"
| bmi <= 30.0 = "Overweight"
| otherwise = "Obese"
where bmi = weight / (height ^ 2)
where
bindings must be aligned neatly as follows:
bmiTell weight height
| bmi <= thin = "Underweight"
| bmi <= normal = "Normal"
| bmi <= fat = "Overweight"
| otherwise = "Obese"
where bmi = weight / (height ^ 2)
thin = 18.5
normal = 25.0
fat = 30.0
where
bindings are scoped to the function. where
bindings can also be used to pattern match. where
bindings can be nested.
let
–in
expression
let <binding> in <expression>
These are similar to where
bindings in many respects. where
bindings are syntactic constructs while let
–in
are expressions (that evaluate to the expression after in
) themselves. Which to use when is often a stylistic choice.
let
expressions are very versatile.
4 * (let a = 9 in a + 1) + 2
[let square x = x * x in (square 5, square 3, square 2)]
(let (a,b,c) = (1,2,3) in a+b+c) * 100
calcBmis pair = [bmi | (w, h) <- pair, let bmi = w / h ^ 2]
When we want to bind several variables on the same line, we separate the bindings with ;
.
if
–then
–else
expressions
case
expressions
They are … expressions!
case <expression> of <pattern> -> <result>
<pattern> -> <result>
<pattern> -> <result>
…
Ranges
[1..20]
is a list with elements 1
to 20
. Similarly, ['a'..'f']
is a list with characters 'a'
through 'z'
. [2,4..20]
is a list of all even numbers from 2
to 20
. Haskell range-step specifying capabilities don’t extend beyond simple arithmetic progressions. [20,19..1]
will work as expected, but [20..1]
will not. Using floating points in ranges is not a good idea.
Haskell’s cool in that you can create infinite lists. For example, let x = [1,2..]
creates and stores an infinite list of natural numbers. Since Haskell is lazy, it does not evaluate the list until it needs to. take 29 x
and take 500 x
return the first 29 and 500 natural numbers respectively.
cycle
— cycles a list into an infinite listrepeat
—repeat x
returns an infinite list containing infinitex
s.
List comprehensions
COOL!
let perfectSquares = [x^2 | x <- [0..]]
— an infinite list of perfect squareslet evenNumbers = [x | x <- [0..], x `mod` 2 == 0]
— a relatively ugly way of producing an infinite list of even numbers
Filtering is a common pattern in FP.
[x*y | x <- [2,5,10], y <- [8,10,11]]
— multiplies all pairs (x, y) wherex
is an element of[2,5,10]
andy
is an element of[8,10,11]
.
Here are a few more examples:
let nouns = ["hobo","frog","pope"]
let adjectives = ["lazy","grouchy","scheming"]
let combos = [adjective ++ " " ++ noun | adjective <- adjectives, noun <- nouns]
length' list = sum [1 | _ <- list]
-- `_` indicates that we don't care about what the element we derive from `list` actually is. We sum a list which is equivalent to a list with as many `1`s as the number of elements in `list`.
stripSpaces str = [chr | chr <- str, chr /= ' ']
BTW nested list comprehensions are possible on nested lists.
Tuples
Tuples:
- are immutable
- are typed —
(Int, Char)
is incompatible with(Int, String)
. Also,(Int, Int)
is incompatible with(Int, Int, Int)
- are not “cons-able”
Functions on tuples:
fst
— returns the first element of a tuplesnd
— returns the second element of a tuple
Some people advise against using tuples with > 2 elements.
Types and Typeclasses
As mentioned earlier, Haskell is statically typed. It has a powerful and “expressive” type system.
Haskell has type inference, but explicit types annotations have several benefits:
- Serve as a form of documentation.
- Some run-time errors wil now be compile-time errors.
Common types
Int
— bounded. 32 or 64 bits depending on the machine.Integer
— not bounded.BigInteger
of sortsFloat
Double
Bool
Char
Typeclasses
A typeclass is an interface of sorts that implements certain defined behaviour. If a type is a part of a typeclass, it will implement the behaviour that the typeclass defines.
The prefix :t
can be used to examine the type of an expression in GHCi.
Common typeclasses
Eq
— support equality testingOrd
— types whose values can be ordered.Ordering
is a type that can beGT
,LT
orEQ
.Show
— can be represented as strings, that is, they can be converted to strings.Read
— can be converted from stringsEnum
— sequentially ordered types. Can be used in list ranges. Havesucc
s andpred
s.Bounded
— have upper and lower boundsNum
— “numeric”. Can behave like numbers.Integral
— “integers”. ImplementsNum
.Floating
— “floating point numbers”. Also implementsNum
.
Relevant functions
compare
read
show
The following are not functions, but polymorphic constants:
minBound
— For example,minBound :: Int
maxBound
— For example,maxBound :: Int
Whole numbers are also polymorphic constants — 20 :: Float
.
Type annotations
count :: Int
count = 0
::
is to be read as “has the type”.
isPrime :: Int -> Bool
isPrime num = …
isPrime
takes an Int
as a parameter and returns a Bool
.
contains :: [Int] -> Int -> Bool
contains arr elem = …
contains
takes a list of Int
and an Int
and returns a Bool
. The reason for this slightly unintuitive syntax for functions that take more than one parameter has a very good reason that will come up later.
Names of types begin with uppercase letters.
Type variables
Class constraints
Recursion
Recursion is an important pattern in FP. While the fibonacci sequence, factorial etc are cliché examples of recursion, many more functions can be written with recursion.
maximum
replicate
reverse
zip
sum
product
Obligatory cliché Haskell quicksort:
quicksort (pivot:rest) =
let lessThan = quicksort [x | x <- rest, x <= pivot]
greaterThan = quicksort [x | x <- rest, x > pivot]
in lessThan ++ [pivot] ++ greaterThan
A successful Haskell programmer must think in haskell.
Higher order functions
Currying, Partial Applications
Maps, filters
Lambdas
Folds
Function application with $
Function composition
Resources
- LYAH. Many examples here are adapted from LYAH.
- UPenn’s CIS194
- Haskell awesome list
- FP awesome list
HTTP
- client establishes TCP connection with server
- client sends a request
- server sends a response with a status code and, optionally, a body
Request Methods
GET
— retrieve resourcePOST
— submit an entity and cause side-effects on the serverPUT
— replace the target resource with the payloadPATCH
— partial modifications to a resourceDELETE
— delete resourceHEAD
—GET
response sans the response bodyOPTIONS
— list of possible request methods for a resourceCONNECT
TRACE
Cookies
When a response contains the Set-Cookie
header, a cookie is set on the client.
HTTP/2.0 200 OK
Set-Cookie: foo=bar
Set-Cookie: baz=baj
With subsequent requests, the client will include the foo
and baz
cookies in the Cookie
header.
GET /path HTTP/2.0
Host: example.com
Cookie: foo=bar; baz=baj
Expires
…
Set-Cookie: foo=bar; Expires=Wed, 21 Oct 2021 07:28:00 GMT;
the time and date set is relative to the client
Security
Secure
— cookie sent only with HTTPSHttpOnly
— inaccessible via JavaScript. only sent and modified by requests and responses respectively
JavaScript
Constructs
for … of
loops through the items of an iterable.
for … in
loops through the keys of an object.
Using for … in
is discouraged.
- for (const key in obj) {
+ for (const key of Object.keys(obj)) {
Array
Functional
filter
reduce(callback, init)
—callback: (acc, current, idx, array)
map
forEach
some
every
Search
['foo', 'bar', 'baz'].includes('bar')
// true
[{ id: 2 }, { id: 3 }, { id: 9 }].find((item) => item.id === 3);
// { id: 3 }
Object
Object.assign
Copy the values of all of the enumerable own properties from one or more source objects to a target object. Returns the target object.
Object.assign(defaults, passed); // Mutates `defaults`
const options = Object.assign({}, defaults, passed); // Doesn't mutate `defaults`
Date
toLocalDateString(locales?, options?)
options
weekday
long
short
narrow
era
long
short
narrow
year
numeric
2-digit
month
numeric
2-digit
long
short
narrow
day
numeric
two-digit
hour
,minute
,second
numeric
two-digit
timeZoneName
long
short
const options = { weekday: "short", day: "numeric", month: "short" };
const today = new Date();
console.log(today.toLocaleDateString(undefined, options)); // Tue, Jun 2
AVA
npm install --save-dev ava
mkdir test
import test from "ava";
test("should foo", (t) => {
t.pass();
});
t.pass
t.fail
t.assert
|t.truthy
t.falsy
t.true
t.false
t.is
t.not
t.deepEqual
t.notDeepEqual
t.throws
t.notThrows
t.throwsAsync
t.notThrowsAsync
t.regex
t.notRegex
test
test.skip
test.failing
test.todo
got
npm i got
import got from "got";
await got("https://example.com");
got.get
got.post
got.put
got.patch
got.delete
got.head
Don’t forget the
await
Using response body
const response = await got("https://example.com");
const body = JSON.parse(response.body);
Search parameters
await got.get("https://example.com/foo", {
searchParams: {
sort: "ascending",
items: 100,
page: 2,
},
});
Headers
await got("https://example.com", {
headers: {
"user-agent": "got v1.0.0",
},
});
Extending
const api = got.extend({
prefixUrl: "https://api.example.com",
});
await api.get("/foo");
await api.delete("/foo");
POST requests
await got.post("https://example.com", {
json: {
name: "John",
},
responseType: "json",
});
Jest
toBe
toEqual
toBeNull
toBeDefined
toBeUndefined
toBeCloseTo
toBeTruthy
toBeFalsy
toBeGreaterThan
toBeGreaterThanOrEqual
toBeLessThan
toBeLessThanOrEqual
toMatch
toContain
toHaveLength
toHaveProperty
toThrow
toBeInstanceOf
JSONPath
JSONPath is a syntax to query json structures.
Examples
An incomplete set of examples of using JSON path follows.
Example Data:
{
"name": "Super hero squad",
"homeTown": "Metro City",
"formed": 2016,
"secretBase": "Super tower",
"active": true,
"members": [
{
"name": "Molecule Man",
"age": 29,
"secretIdentity": "Dan Jukes",
"powers": [
"Radiation resistance", "Turning tiny", "Radiation blast"
]
},
{
"name": "Madame Uppercut",
"age": 39,
"secretIdentity": "Jane Wilson",
"powers": [
"Million tonne punch", "Damage resistance", "Superhuman reflexes"
]
},
{
"name": "Eternal Flame",
"age": 1000000,
"secretIdentity": "Unknown",
"powers": [
"Immortality", "Heat Immunity", "Inferno", "Teleportation", "Interdimensional travel"
]
}
]
}
$.members
[
[
{
name: "Molecule Man",
age: 29,
secretIdentity: "Dan Jukes",
powers: ["Radiation resistance", "Turning tiny", "Radiation blast"],
},
{
name: "Madame Uppercut",
age: 39,
secretIdentity: "Jane Wilson",
powers: [
"Million tonne punch",
"Damage resistance",
"Superhuman reflexes",
],
},
{
name: "Eternal Flame",
age: 1000000,
secretIdentity: "Unknown",
powers: [
"Immortality",
"Heat Immunity",
"Inferno",
"Teleportation",
"Interdimensional travel",
],
},
],
];
$.members.*
[
{
name: "Molecule Man",
age: 29,
secretIdentity: "Dan Jukes",
powers: ["Radiation resistance", "Turning tiny", "Radiation blast"],
},
{
name: "Madame Uppercut",
age: 39,
secretIdentity: "Jane Wilson",
powers: [
"Million tonne punch",
"Damage resistance",
"Superhuman reflexes",
],
},
{
name: "Eternal Flame",
age: 1000000,
secretIdentity: "Unknown",
powers: [
"Immortality",
"Heat Immunity",
"Inferno",
"Teleportation",
"Interdimensional travel",
],
},
];
$..name
Values of all keys name
. ..
is called the recursive descendant operator.
["Super Hero Squad", "Molecule Man", "Madame Uppercut", "Eternal Flame"];
$.members[*].name
Values of the name key of all members
["Molecule Man", "Madame Uppercut", "Eternal Flame"];
$.members[2].*
Element at index 2
of the array members
.
{
"name": "Eternal Flame",
"age": 1000000,
"secretIdentity": "Unknown",
"powers": [
"Immortality", "Heat Immunity", "Inferno", "Teleportation",
"Interdimensional travel"
]
}
Also valid:
$.members[:2]
: First two elements ofmembers
$.members[0,2]
: Elements at indices0
and2
$..*
[all values of the JSON structure]
Formal syntax
From https://www.npmjs.com/package/jsonpath#jsonpath-syntax.
JSONPath | Description |
---|---|
$ | The root object/element |
@ | The current object/element |
. | Child member operator |
.. | Recursive descendant operator; JSONPath borrows this syntax from E4X |
* | Wildcard matching all objects/elements regardless their names |
[] | Subscript operator |
[,] | Union operator for alternate names or array indices as a set |
[start:end:step] | Array slice operator borrowed from ES4 / Python |
?() | Applies a filter (script) expression via static evaluation |
() | Script expression via static evaluation |
Knex
import knex from 'knex';
const db = knex({
client: 'mysql',
connection: {
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_DB
}
});
db('table').insert({ name: 'Foo' });
Koa
Koa is a minimal web framework for node.js.
Only methods that are common to nearly all HTTP servers are integrated directly into Koa’s small ~570 SLOC codebase. This includes things like content negotiation, normalization of node inconsistencies, redirection, and a few others.
Koa is not bundled with any middleware.
This is quite unlike express.
There is an ecosystem of npm modules around koa that implement all sorts of useful middleware.
Koa leverages async
functions, allowing us to avoid callback hell and implement error handling with greater ease.
Koa is awesome [citation needed].
Useful modules
Minimal Koa app
import Koa from "koa";
import Router from "koa-router";
const app = new Koa();
const router = new Router();
router.get("/", async (ctx) => {
ctx.body = "response";
});
app.use(router.routes());
app.use(router.allowedMethods())
app.listen(process.env.PORT || 3000);
Local Storage
const storage = window.localStorage;
storage.setItem(key, val);
storage.getItem(key);
storage.removeItem(key);
storage.clear();
LaTeX
Math
\alpha
,\Alpha
\beta
,\Beta
- …
\sin
,\cos
,\tan
, …
Subscripts — a_1
a_{n+1}
Superscripts — a^2
a^{n+1}
\frac{1}{2}
\sqrt{2}
Sums
\sum_{x=1}^{\infty} \frac{1}{x}
\sum_{init}^{limit} term
Integrals
\int_{lower}^{upper} term \mathrm{d}x
Big operators
\sum
\prod
\int
Formatting
- Roman —
\mathrm
- Italic —
\mathit
- Bold —
\mathbf
- Calligraphic —
\mathcal
- Double-lined —
\mathbb
Symbols
\leq
,\geq
\subset
,\supset
,\subseteq
,\supseteq
\therefore
,\because
\pm
,\mp
\times
,\div
,\cdot
\cap
,\cup
\exists
,\nexists
,\forall
\neg
,\land
,\lor
\subset
,\supset
,\in
,\notin
\dots
,\cdots
,\vdots
,\ddots
Linux from Scratch
Version 9.1 (March 1st, 2020)
Packages
Zlib-1.2.11
compression-decompression
libz
Bzip2-1.0.8
compression-decompression
bzip2
, bunzip2
primarily.
Also bz{cat,cmp,diff,egrep,fgrep,grep,less,more}
among others.
libbz2
Xz-5.2.4
compression-decompression
lzma
, unlzma
, xz
, unxz
primarily.
{lz,xz}{cat,cmp,diff,egrep,fgrep,grep,less,more}
Libraries
liblzma
File-5.38
determine filetypes of files
file
libmagic
— magic number recognition
Readline-8.0
command-line editing and history
libreadline
— commands for repl input manipulationlibhistory
— handle command-line history lines
M4-1.4.18
macro processor
m4
Bc-2.5.3
arbitrary precision number processing
bc
, dc
(rpn)
Binutils-2.34
linker, assembler, and other stuff for handling object files
…
…
GMP-6.2.0
math libs
libgmp
— math functionslibgmpxx
— math functions, but for C++
MPFR-4.0.2
arbitrary precision math
libmpfr
MPC-1.1.0
complex number math
libmpc
Attr-2.4.48
file extended attributes
attr
, {get,set}fattr
libattr
Acl-2.2.53
access control lists. fine-grained file/dir access control
chacl
— “change ACL”{get,set}facl
libacl
Shadow-4.8.1
tools to securely handle passwords
ch{age,fn,passwd,sh}
chgpasswd
group{add,del,mems,mod}
gp{ck,conv,unconv}
user{add,del,mod}
…
GCC-9.2.0
gnu compiler collection
c compiler
{c,g}++
{,g}cc
gcov{,-dump,-tool}
— coverage testing tool
…
Pkg-config-0.29.2
Ncurses-6.2
“libraries for terminal-independent handling of character screens”
Libcap-2.31
“capabilities” (aka privileges)
Sed-4.8
stream editor. find-replace
sed
Psmisc-23.2
display info about running processes
Iana-Etc-2.30
data for network services|protocols
Installs /etc/protocols
and /etc/services
Bison-3.5.2
parser generator
bison
— given rules generates parser codeyacc
(”yet another compiler compiler”)
liby
Flex-2.6.4
kinda like bison?
flex
, flex++
, …
libfl
Grep-3.4
find with regex
{e,f,}grep
e
: extended
f
: “fixed strings”
Bash-5.0
shell
bash
, bashbug
Libtool-2.4.6
generic library for consistent shared library support
GDBM-1.18.1
GNU DB Manager
database utils. key-value stores. crud.
Gperf-3.1
“generates a perfect hash function from a key set”
Expat-2.2.9
parse XML with C
xmlwf
. xml well-formed?
libexpat
Inetutils-1.9.4
networking tools
dnsdomainname
{,t}ftp
hostname
ifconfig
ping{,6}
talk
telnet
traceroute
Perl-5.30.1
Practical Extraction and Report Language
perl{,bug,doc,ivp,thanks,5.30.1}
, pod{…}
(documentation format), …
XML::Parser-2.46
perl interface to expat
Intltool-0.51.0
i18n tool to extract translatable strings from source files
intltoolize
, intltool-{extract,merge,prepare,update}
Autoconf-2.69
creates shell scripts to auto-configure source code
Automake-1.16.1
Kmod-26
kernel modules
Gettext-0.20.1
i18n
Libelf from Elfutils-0.178
executable and linked files
Libffi-3.3
OpenSSL-1.1.1d
Python-3.8.1
Ninja-1.10.0
simple build system
Meson-0.53.1
another simple build system
Coreutils-8.31
buncha random unix-ey tools
Check-0.14.0
testing/assertion
Diffutils-3.7
diff and siblings
Gawk-5.0.1
Findutils-4.7.0
finding files and things
Groff-1.22.4
document processing
GRUB-2.04
grand unified bootloader
bootloader
Less-551
pager
Gzip-1.10
compression-decompression
Zstd-1.4.4
compression-decompression
IPRoute2-5.5.0
Kbd-2.2.0
Libpipeline-1.5.2
Make-4.3
build systems
Patch-2.7.6
apply patches (typically) created via diff
Man-DB-2.9.0
man pages.
Tar-1.32
Texinfo-6.7
info pages. man pages, except longer.
Vim-8.2.0190
vim.
MDX
MD + JSX = MDX
MDX allows using JSX components within markdown. This means it’s possible to import powerful components like charts, interactive playgrounds etc and use them within markdown.
I love markdown as an authoring format, but it’s limitations can get real, making it unsuitable for anything beyond vanilla content. MDX breaks this barrier.
MDX has no runtime, all compilation occurs during the build stage.
Deployment Options
- Gatsby —
gatsby-plugin-mdx
- Charge
- React
- Parcel | Webpack
- Zero
Links
nginx
Engine X
location modifier pattern {
…
}
Modifiers:
- (none) — prefix match
=
— exact match~
— case-sensitive regex~*
— case-insensitive regex^~
— non-regex
client_max_body_size 25M;
add_header x-header "value";
Logging
log_format minimal '[$time_local] $status "$request" $body_bytes_sent bytes'
access_log path minimal;
error_log path severity;
Default severity: error
Port 80 traffic → Port 443
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
Clean URLs
try_files $uri $uri.html $uri/index.html =404;
rewrite ^/index(?:\.html|/)?$ / permanent;
rewrite ^/(.*)/index(?:\.html|/)?$ /$1 permanent;
rewrite ^/(.*)(?:\.html|/)$ /$1 permanent;
—URLs Without Trailing Slash or Extension
SSI
Server-side includes
ssi on;
Commands
Subdirectory → subdomain mapping
server_name ~^(?<sub>.+)\.mirrors\.example\.com$;
root /var/www/mirrors/$sub;
Pug
Indentation-based. Indentation must be consistent.
doctype html
a(href="https://example.com")
nav
ul
li: a(href="https://example.com") Example
li: a(href="https://example.com/1") One
li: a(href="https://example.com/1") One
li: a …
is shorthand for:
<li>
<a>…</a>
</li>
.main //- <div class="main">
…
#this //- <div id="this">
…
button.link.button //- <button class="link button">
Conditionals
if followers.length == 0
p No followers
Iteration
ul
each user in activeUsers
li: img(src=`/img/{user.id}`)
each val, key in {1: 'one', 2: 'two', 3: 'three'}
each val, index in ['zero', 'one', 'two']
Includes
Inheritance
Interpolation
Mixins
Python
if low <= num <= high: # this works!
pass
from itertools import product as cartesian_product
print(cartesian_product(['a', 'f', 'd'], [3, 4, 5]))
from functools import reduce
from operators import mul
print(reduce(mul, [5, 9, 2, 10, 4]))
Flask
Flask is a web framework for python. If Django is the Express of the python world, Flask is the Koa (these analogies aren’t perfectly accurate, but analogies never are).
Hello world
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello world!'
- Set
FLASK_APP
to the name of the file containing the app. - Set
FLASK_ENV
todevelopment
if in dev environment.
Run flask run
to run the app.
Path parameters
@app.route('/user/<username>')
def user_profile(username):
return 'User profile for {}'.format(username)
@app.route('/user/<string:username>')
def user_profile(username):
return 'User profile for {}'.format(username)
Converters:
string
int
float
path
uuid
Checking HTTP method
from flask import request
@app.route('/resource/<id>', methods=['GET', 'PUT'])
def resource(id):
return resource.method
Trailing slash vs no trailing slash
In the following example, the canonical URL is /path/
. /path
will redirect to /path/
app.route('/path/')
The opposite is true in the following example.
app.route('/path/')
URL building
from flask import url_for
@app.route('/')
def index():
...
@app.route('/dashboard')
def dashboard():
...
@app.route('/user/<username>')
def profile():
...
url_for('index') # '/'
url_for('dashboard', page='2') # '/dashboard?page=2'
url_for('profile', username='ansh') # '/user/ansh'
Static files
In production, web server software should serve static files. In development, flask is configured to automatically serve files in static
under /static
.
Regular Expressions
Links
- Regex for Regular Folk — shameless plug 🙃
Scalable Vector Graphics
<svg
viewbox="0 0 100 100"
width="100" height="100"
version="1.1" xmlns="http://www.w3.org/2000/svg"
>
…
</svg>
Strokes are centered across paths by default. This may complicate width and coordinate calculation.
stroke-alignment := "inside" | "outside" | "center"
Shapes
rect
<rect x="0" y="0" width="100" height="100" stroke="black" />
line
<line x1="0" y1="0" x2="100" y2="100" stroke="black" />
polyline
<polyline points="0,0, 0,20 20,20 20,0 0,0" stroke="black" />
Each of the points defined are connected by lines.
Scheme
(+ 5 6)
(+ (* 4 6) (/ 1 2))
(quote (1 2 3 4 5))
(quote (a b c))
(quote (+ a b c))
'(1 2 3 4 5)
'(a b c)
'(+ a b c)
'str
SQL
MySQL
My S-Q-L
mysql -u root -p
Shell
Create user
create user 'someuser' identified by 'password';
Create DB
create database somedb;
grant all privileges on somedb.* to 'someuser';
flush privileges;
Change user password
alter user 'someuser' identified by 'password';
Export and Import
mysqldump -u someuser --password somedb > somedb.sql
mysql -u someuser --password somedb < somedb.sql
Troubleshooting
Authentication
Client does not support authentication protocol
alter user 'user'@'localhost' identified by 'new_pwd';
alter user 'user'@'localhost' identified with mysql_native_password BY 'new_pwd';
Connection
SQL Queries
Some illustrative examples follow. Usually it will be obvious what the query is doing.
select a, b, c from table;
select * from table;
select distinct city from table;
select distinct city, country from table;
select first_name, last_name from students where marks > 80;
select first_name, last_name from students where marks != 42;
select first_name, last_name from students where marks between 80 and 90;
select city from table where amount > 5000 and tax < 50;
select score from table where name == "Shreyas" or name == "Sister";
select score from table where name in ("Shreyas", "Sister");
select score from table where name in (select first_name from family);
select customer_name, commodity, price from commodities order by price desc, customer, commodity asc;
select name from customers where phone_number is not null;
update customers set bonus_points = 0, redeemed_points = 0 where id = 25;
If you omit the
where
clause in anupdate
statement, ALL records will be updated!
delete from customers where first_name="Jeff";
If you omit the
where
clause in adelete
statement, ALL records will be deleted!
delete from customers;
select first_name, city from customers limit 50;`
The limit
syntax is MySQL-specific.
select employee_id, max(shipping_fee) from orders;
select min(price) from inventory;
select max(price) from inventory;
select avg(price) from inventory;
select sum(price) from inventory;
Svelte
Svelte is a “framework-less framework”.
- No virtual DOM
- Single-file components
- Templating-like syntax
<script>
...
</script>
<style>
...
</style>
…
<script>
let subject = "world";
</script>
<span>Hello {subject}</span>
Styles are component-scoped.
Templating
{#if condition}
<code>true</code>
{/if}
{#if condition}
<code>true</code>
{:else}
<code>true</code>
{/if}
{#if condition}
…
{:else if other}
…
{:else}
…
{/if}
{#each array as element}
<li>{element}</li>
{/each}
{#each array as element, index}
<li>{element}</li>
{/each}
{#each array as {a, b, c}}
<li>{element}</li>
{/each}
Reactivity
<script>
let num = 1;
$: let double = num * 2;
$: let triple = num * 3;
</script>
<input type="range" bind:value={num}>
<li>x: {num}</li>
<li>2x: {double}</li>
<li>3x: {triple}</li>
$:
means “re-run whenever these values change”
Events
on:click
on:mousemove
on:submit
- …
|once
|preventDefault
Bindings
bind:value
<script>
let name;
</script>
<input bind:value={name} placeholder="John Doe">
<p>
Hi {name}
</p>
bind:checked
bind:group
Links
The Pragmatic Programmer
All of this is quoted from The Pragmatic Programmer‘s appendices.
Tips
1. Care About Your Craft
Why spend your life developing software unless you care about doing it well?
2. Think! About Your Work
Turn off the autopilot and take control. Constantly critique and appraise your work.
3. Provide Options, Don’t Make Lame Excuses
Instead of excuses, provide options. Don’t say it can’t be done; explain what can be done.
4. Don’t Live with Broken Windows
Fix bad designs, wrong decisions, and poor code when you see them.
5. Be a Catalyst for Change
You can’t force change on people. Instead, show them how the future might be and help them participate in creating it.
6. Remember the Big Picture
Don’t get so engrossed in the details that you forget to check what’s happening around you.
7. Make Quality a Requirements Issue
Involve your users in determining the project’s real quality requirements.
8. Invest Regularly in Your Knowledge Portfolio
Make learning a habit.
9. Critically Analyze What You Read and Hear
Don’t be swayed by vendors, media hype, or dogma. Analyze information in terms of you and your project.
10. It’s Both What You Say and the Way You Say It
There’s no point in having great ideas if you don’t communicate them effectively.
11. DRY—Don’t Repeat Yourself
Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
12. Make It Easy to Reuse
If it’s easy to reuse, people will. Create an environment that supports reuse.
13. Eliminate Effects Between Unrelated Things
Design components that are self-contained, independent, and have a single, well-defined purpose.
14. There Are No Final Decisions
No decision is cast in stone. Instead, consider each as being written in the sand at the beach, and plan for change.
15. Use Tracer Bullets to Find the Target
Tracer bullets let you home in on your target by trying things and seeing how close they land.
16. Prototype to Learn
Prototyping is a learning experience. Its value lies not in the code you produce, but in the lessons you learn.
17. Program Close to the Problem Domain
Design and code in your user’s language.
18. Estimate to Avoid Surprises
Estimate before you start. You’ll spot potential problems up front.
19. Iterate the Schedule with the Code
Use experience you gain as you implement to refine the project time scales.
20. Keep Knowledge in Plain Text
Plain text won’t become obsolete. It helps leverage your work and simplifies debugging and testing.
21. Use the Power of Command Shells
Use the shell when graphical user interfaces don’t cut it.
22. Use a Single Editor Well
The editor should be an extension of your hand; make sure your editor is configurable, extensible, and programmable.
23. Always Use Source Code Control
Source code control is a time machine for your work—you can go back.
24. Fix the Problem, Not the Blame
It doesn’t really matter whether the bug is your fault or someone else’s—it is still your problem, and it still needs to be fixed.
25. Don’t Panic When Debugging
Take a deep breath and THINK! about what could be causing the bug.
26. “select” Isn’t Broken
It is rare to find a bug in the OS or the compiler, or even a third-party product or library. The bug is most likely in the application.
27. Don’t Assume It—Prove It
Prove your assumptions in the actual environment—with real data and boundary conditions.
28. Learn a Text Manipulation Language
You spend a large part of each day working with text. Why not have the computer do some of it for you?
29. Write Code That Writes Code
Code generators increase your productivity and help avoid duplication.
30. You Can’t Write Perfect Software
Software can’t be perfect. Protect your code and users from the inevitable errors.
31. Design with Contracts
Use contracts to document and verify that code does no more and no less than it claims to do.
32. Crash Early
A dead program normally does a lot less damage than a crippled one.
33. Use Assertions to Prevent the Impossible
Assertions validate your assumptions. Use them to protect your code from an uncertain world.
34. Use Exceptions for Exceptional Problems
Exceptions can suffer from all the readability and maintainability problems of classic spaghetti code. Reserve exceptions for exceptional things.
35. Finish What You Start
Where possible, the routine or object that allocates a resource should be responsible for deallocating it.
36. Minimize Coupling Between Modules
Avoid coupling by writing “shy” code and applying the Law of Demeter.
37. Configure, Don’t Integrate
Implement technology choices for an application as configuration options, not through integration or engineering.
38. Put Abstractions in Code, Details in Metadata
Program for the general case, and put the specifics outside the compiled code base.
39. Analyze Workflow to Improve Concurrency
Exploit concurrency in your user’s workflow.
40. Design Using Services
Design in terms of services—independent, concurrent objects behind well-defined, consistent interfaces.
41. Always Design for Concurrency
Allow for concurrency, and you’ll design cleaner interfaces with fewer assumptions.
42. Separate Views from Models
Gain flexibility at low cost by designing your application in terms of models and views.
43. Use Blackboards to Coordinate Workflow
Use blackboards to coordinate disparate facts and agents, while maintaining independence and isolation among participants.
44. Don’t Program by Coincidence
Rely only on reliable things. Beware of accidental complexity, and don’t confuse a happy coincidence with a purposeful plan.
45. Estimate the Order of Your Algorithms
Get a feel for how long things are likely to take before you write code.
46. Test Your Estimates
Mathematical analysis of algorithms doesn’t tell you everything. Try timing your code in its target environment.
47. Refactor Early, Refactor Often
Just as you might weed and rearrange a garden, rewrite, rework, and re-architect code when it needs it. Fix the root of the problem.
48. Design to Test
Start thinking about testing before you write a line of code.
49. Test Your Software, or Your Users Will
Test ruthlessly. Don’t make your users find bugs for you.
50. Don’t Use Wizard Code You Don’t Understand
Wizards can generate reams of code. Make sure you understand all of it before you incorporate it into your project.
51. Don’t Gather Requirements—Dig for Them
Requirements rarely lie on the surface. They’re buried deep beneath layers of assumptions, misconceptions, and politics.
52. Work with a User to Think Like a User
It’s the best way to gain insight into how the system will really be used.
53. Abstractions Live Longer than Details
Invest in the abstraction, not the implementation. Abstractions can survive the barrage of changes from different implementations and new technologies.
54. Use a Project Glossary
Create and maintain a single source of all the specific terms and vocabulary for a project.
55. Don’t Think Outside the Box—Find the Box
When faced with an impossible problem, identify the real constraints. Ask yourself: “Does it have to be done this way? Does it have to be done at all?”
56. Start When You’re Ready
You’ve been building experience all your life. Don’t ignore niggling doubts.
57. Some Things Are Better Done than Described
Don’t fall into the specification spiral—at some point you need to start coding.
58. Don’t Be a Slave to Formal Methods
Don’t blindly adopt any technique without putting it into the context of your development practices and capabilities.
59. Costly Tools Don’t Produce Better Designs
Beware of vendor hype, industry dogma, and the aura of the price tag. Judge tools on their merits.
60. Organize Teams Around Functionality
Don’t separate designers from coders, testers from data modelers. Build teams the way you build code.
61. Don’t Use Manual Procedures
A shell script or batch file will execute the same instructions, in the same order, time after time.
62. Test Early. Test Often. Test Automatically
Tests that run with every build are much more effective than test plans that sit on a shelf.
63. Coding Ain’t Done ’Til All the Tests Run
’Nuff said.
64. Use Saboteurs to Test Your Testing
Introduce bugs on purpose in a separate copy of the source to verify that testing will catch them.
65. Test State Coverage, Not Code Coverage
Identify and test significant program states. Just testing lines of code isn’t enough.
66. Find Bugs Once
Once a human tester finds a bug, it should be the last time a human tester finds that bug. Automatic tests should check for it from then on.
67. English is Just a Programming Language
Write documents as you would write code: honor the DRY principle, use metadata, MVC, automatic generation, and so on.
68. Build Documentation In, Don’t Bolt It On
Documentation created separately from code is less likely to be correct and up to date.
69. Gently Exceed Your Users’ Expectations
Come to understand your users’ expectations, then deliver just that little bit more.
70. Sign Your Work
Craftsmen of an earlier age were proud to sign their work. You should be, too.
Checklist
✔ Languages to Learn
Tired of C, C++, and Java? Try CLOS, Dylan, Eiffel, Objective C, Prolog, Smalltalk, or TOM. Each of these languages has different capabilities and a different “flavor.” Try a small project at home using one or more of them.
✔ The WISDOM Acrostic
- What do you want them to learn?
- What is their interest in what you’ve got to say?
- How sophisticated are they?
- How much detail do they want?
- Whom do you want to own the information?
- How can you motivate them to listen to you?
✔ How to Maintain Orthogonality
- Design independent, well-defined components. Keep your code decoupled.
- Avoid global data.
- Refactor similar functions.
✔ Things to prototype
- Architecture
- New functionality in an existing system
- Structure or contents of external data Third-party tools or components
- Performance issues
- User interface design
✔ ArchitecturalQuestions
- Are responsibilities well defined?
- Are the collaborations well defined?
- Is coupling minimized?
- Can you identify potential duplication?
- Are interface definitions and constraints accept- able?
- Can modules access needed data—when needed?
✔ Debugging Checklist
- Is the problem being reported a direct result of the underlying bug, or merely a symptom?
- Is the bug really in the compiler? Is it in the OS? Or is it in your code?
- If you explained this problem in detail to a coworker, what would you say?
- If the suspect code passes its unit tests, are the tests complete enough? What happens if you run the unit test with this data?
- Do the conditions that caused this bug exist anywhere else in the system?
✔ Law of Demeter for Functions
An object’s method should call only methods belonging to:
- Itself
- Any parameters passed in
- Objects it creates
- Component objects
✔ How to Program Deliberately
- Stay aware of what you’re doing.
- Don’t code blindfolded.
- Proceed from a plan.
- Rely only on reliable things.
- Document your assumptions.
- Test assumptions as well as code.
- Prioritize your effort.
- Don’t be a slave to history.
✔ When to Refactor
- You discover a violation of the DRY principle.
- You find things that could be more orthogonal.
- Your knowledge improves.
- The requirements evolve.
- You need to improve performance.
✔ Cutting the Gordian Knot
When solving impossible problems, ask yourself:
- Is there an easier way?
- Am I solving the right problem?
- Why is this a problem?
- What makes it hard?
- Do I have to do it this way?
- Does it have to be done at all?
✔ Aspects of Testing
- Unit testing
- Integration testing
- Validation and verification
- Resource exhaustion, errors, and recovery Performance testing
- Usability testing
- Testing the tests themselves
The Twelve-Factor App
Codebase
One codebase tracked in revision control, many deploys
- Always use a VCS
x
codebases =x
apps- “Multiple apps sharing the same code is a violation of twelve-factor.” Create modules and use those instead.
- A deploy is a running instance of the app.
- “There is only one codebase per app, but there will be many deploys of the app.”
Dependencies
Explicitly declare and isolate dependencies
- Never rely on implicit existence of system-wide packages or system tools. If necessary, vendor the tool in question into the app.
- Explicitly declare dependencies via a dependency declaration manifest.
- Use a dependency isolation tool.
Config
Store config in the environment
An app’s config is everything that is likely to vary between deploys (staging, production, developer environments, etc).
- Twelve-factor requires strict separation of config from code.
- The twelve-factor app stores config in environment variables.
- Grouping config into named groups is not recommended since it does not scale well.
In a twelve-factor app, env vars are granular controls, each fully orthogonal to other env vars. They are never grouped together as “environments”, but instead are independently managed for each deploy. This is a model that scales up smoothly […].
Backing services
Treat backing services as attached resources
A backing service is any service the app consumes over the network as part of its normal operation.
Examples:
- Databases
- SMTP services
- Logging services
- Caching systems
- API-accessible consumer services
Keep in mind that:
- The code for a twelve-factor app makes no distinction between local and third party services.
- Each backing services is a resource. These attached services are loosely coupled with the deploy they are associated with.
- It should be possible to attach and detach resources from deploys at will.
Build, release, run
Strictly separate build and run stages
Processes
Execute the app as one or more stateless processes
Port binding
Export services via port binding
Concurrency
Scale out via the process model
Disposability
Maximize robustness with fast startup and graceful shutdown
Dev/prod parity
Keep development, staging, and production as similar as possible
Logs
Treat logs as event streams
Admin processes
Run admin/management tasks as one-off processes
TypeScript
Type annotations
Intended contract of a variable/function.
let foo: string;
function bar(a: string, b?: number): void {
…
}
(foo: string) => boolean
let primes: number[];
Interfaces
interface Rule {
readonly message: string,
readonly test?: (commitMessage: string) => boolean;
}
Type aliases
Enums
enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY,
SATURDAY, SUNDAY
}
enum Result {
pass = 'type',
fail = 'fail',
info = 'info'
}
Classes
Unix CLI Tools
Disks and drives
Wipe empty space
sudo dd if=/dev/zero of=out bs=1M count=1024
shred -n 5 --remove out
Bootable drive
sudo dd if=Downloads/os.iso of=/dev/disk3 bs=4m && sync
General
date
date
date +"%Y-%m-%d"
date +%s
Files
sed
sed 's/foo/bar/g' file
sed 's#foo#bar#g' file
sed --in-place='' 's/foo/bar/g' file
find
shred
shred --remove file
find <dir> -type f -exec shred --remove {} \;
Access control
groupadd
groupadd foo
useradd
useradd \
-s /bin/bash \
-g foo \
-m \
bar
Security
GnuPG CLI
Encrypt files
gpg --encrypt --recipient DEADBEEF file.pdf
gpg --encrypt --recipient 'john@example.com' file.pdf
gpg --encrypt --recipient DEADBEEF --trust-model always file.pdf
Decrypt files
gpg --decrypt file.pdf.gpg > file.pdf
Verifying signatures
gpg --verify dl.zip.sig dl.zip
Import keys
curl https://example.com/key.asc | gpg --import
gpg --import key.asc
Trust levels
- Ultimate — it’s your own key
- Full — you’ve verified the identity of the key owner and signed their public key
- Marginal — enough to make the key show up as “valid”
Links
HTTP Security Headers
-
X-Content-Type-Options
nosniff
-
X-Frame-Options
SAMEORIGIN
-
X-XSS-Protection
1; mode-block
-
Strict-Transport-Security
max-age=31536000; includeSubDomains
-
Referer-Policy
same-origin
-
Content-Security
default-src: 'self'
Some directives:
default-src
script-src
object-src
style-src
img-src
media-src
font-src
frame-src
connect-src
form-action
Values:
- (Possibly incomplete) Domains
- Wildcards permitted for some parts
'none'
'self'
— doesn’t include subdomains'unsafe-inline'
— Inline JS and CSS'unsafe-eval'
-
Feature-Policy
Links
JSON Web Tokens
Auth mechanism.
-
Backend
- has a secret key
-
Frontend
- sends a request with a header and a payload
-
Backend
- signs the header+payload with the secret key
- using the algorithm specified in the header
- returns the token to the frontend
- signs the header+payload with the secret key
-
Frontend
-
must send the token with every request to protected routes.
Authorization: Bearer <token>
-
-
Backend
- then independently computes the signature of the header+payload.
- If it matches the signature in the token, access is granted.
- then independently computes the signature of the header+payload.
Since the frontend doesn’t know the secret key, it cannot create signatures that will check out at the backend. Thus, the frontend cannot successfully tamper with the payload.
Can be used for stateless auth!
Parts:
- header
- payload
- signature
header.payload.signature
Parts
Header
{
"alg": "HS256",
"typ": "JWT"
}
Base64 Encode.
Payload
Contains claims.
{
"sub": "9234",
"username": "john",
"admin": false
}
Base64 Encode.
Payload is tamper-proof, but publically visible.
Signature verification
const computedSignature = HMACSHA256(
base64UrlEncode(token.header) + "." +
base64UrlEncode(token.payload),
secret
);
if (token.signature === computedSignature) {
return true;
}
return false;
Links
ufw
sudo ufw allow 3000
sudo ufw status [numbered]
sudo ufw reload
sudo ufw delete 4
Don’t accidentally block the SSH port