Browse Source

insert posts sources

master
Peter Babič 3 months ago
parent
commit
97afdf2b0c
  1. 18
      content/blog/my-old-genetic-algorithm-project.md
  2. 132
      sources/following-renames-in-gitlog/.gitignore
  3. 99
      sources/following-renames-in-gitlog/README.md
  4. 809
      sources/following-renames-in-gitlog/package-lock.json
  5. 19
      sources/following-renames-in-gitlog/package.json
  6. 7
      sources/following-renames-in-gitlog/renamed-blog-post.md
  7. 10
      sources/following-renames-in-gitlog/server.ts
  8. 7
      sources/following-renames-in-gitlog/tsconfig.json
  9. 1
      sources/how-commit-history-tells-when-post-published/.gitignore
  10. 105
      sources/how-commit-history-tells-when-post-published/README.md
  11. 41
      sources/how-commit-history-tells-when-post-published/added.ts
  12. 44
      sources/how-commit-history-tells-when-post-published/example-diff.js
  13. 1693
      sources/how-commit-history-tells-when-post-published/package-lock.json
  14. 20
      sources/how-commit-history-tells-when-post-published/package.json
  15. 61
      sources/how-commit-history-tells-when-post-published/revvalk.ts
  16. 44
      sources/how-commit-history-tells-when-post-published/test.js
  17. 133
      sources/how-to-assert-sorted-dates-cypress/.gitignore
  18. 21
      sources/how-to-assert-sorted-dates-cypress/README.md
  19. 3
      sources/how-to-assert-sorted-dates-cypress/cypress.json
  20. 18
      sources/how-to-assert-sorted-dates-cypress/cypress/integration/spec.js
  21. 21
      sources/how-to-assert-sorted-dates-cypress/cypress/plugins/index.js
  22. 25
      sources/how-to-assert-sorted-dates-cypress/cypress/support/commands.js
  23. 20
      sources/how-to-assert-sorted-dates-cypress/cypress/support/index.js
  24. 28
      sources/how-to-assert-sorted-dates-cypress/index.html
  25. 13
      sources/how-to-assert-sorted-dates-cypress/index.js
  26. 2031
      sources/how-to-assert-sorted-dates-cypress/package-lock.json
  27. 22
      sources/how-to-assert-sorted-dates-cypress/package.json
  28. 135
      sources/prevent-push-when-skipping-cypress-tests/.gitignore
  29. 63
      sources/prevent-push-when-skipping-cypress-tests/README.md
  30. 1
      sources/prevent-push-when-skipping-cypress-tests/cypress.json
  31. 5
      sources/prevent-push-when-skipping-cypress-tests/cypress/fixtures/example.json
  32. 6
      sources/prevent-push-when-skipping-cypress-tests/cypress/integration/spec.js
  33. 21
      sources/prevent-push-when-skipping-cypress-tests/cypress/plugins/index.js
  34. 25
      sources/prevent-push-when-skipping-cypress-tests/cypress/support/commands.js
  35. 20
      sources/prevent-push-when-skipping-cypress-tests/cypress/support/index.js
  36. BIN
      sources/prevent-push-when-skipping-cypress-tests/demo.gif
  37. 2326
      sources/prevent-push-when-skipping-cypress-tests/package-lock.json
  38. 23
      sources/prevent-push-when-skipping-cypress-tests/package.json
  39. 8
      sources/prevent-push-when-skipping-cypress-tests/server.js
  40. 4
      sources/store-arrays-svelte-localstorage/.gitignore
  41. 23
      sources/store-arrays-svelte-localstorage/README.md
  42. BIN
      sources/store-arrays-svelte-localstorage/demo.gif
  43. 799
      sources/store-arrays-svelte-localstorage/package-lock.json
  44. 22
      sources/store-arrays-svelte-localstorage/package.json
  45. 80
      sources/store-arrays-svelte-localstorage/rollup.config.js
  46. 130
      sources/store-arrays-svelte-localstorage/scripts/setupTypeScript.js
  47. 10
      sources/store-arrays-svelte-localstorage/src/App.svelte
  48. 7
      sources/store-arrays-svelte-localstorage/src/main.js
  49. 10
      sources/store-arrays-svelte-localstorage/src/store.js
  50. 132
      sources/using-css-selectors-on-markdown/.gitignore
  51. 94
      sources/using-css-selectors-on-markdown/README.md
  52. 18
      sources/using-css-selectors-on-markdown/index.js
  53. 332
      sources/using-css-selectors-on-markdown/package-lock.json
  54. 19
      sources/using-css-selectors-on-markdown/package.json
  55. 9
      sources/using-css-selectors-on-markdown/post.md
  56. 132
      sources/yaml-metadata-in-markdown/.gitignore
  57. 29
      sources/yaml-metadata-in-markdown/README.md
  58. 7
      sources/yaml-metadata-in-markdown/example.md
  59. 23
      sources/yaml-metadata-in-markdown/index.js
  60. 989
      sources/yaml-metadata-in-markdown/package-lock.json
  61. 22
      sources/yaml-metadata-in-markdown/package.json
  62. 13
      sources/yaml-metadata-in-markdown/test/index.js

18
content/blog/my-old-genetic-algorithm-project.md

@ -1,18 +0,0 @@
---
draft: true
title: "%"
date: "2021-07-01"
updated: "2021-07-01"
taxonomies:
tags: ["journal", "programming"]
---
Making a slides for presenting solution to a combinatorics problem recently
I had to revisit one of my older projects, or quite really old -
circa 2013. That time I was still attending University in the lovely Slovak
city of Kosice.
The project was a demonstration of the genetic algorithm we were currently
discussing during classes. I set to see for myself what the lecturer was
talking about. Although it was not required to write a single, I was not
satisfied with just seeing some key notes.

132
sources/following-renames-in-gitlog/.gitignore

@ -0,0 +1,132 @@
# Created by https://www.toptal.com/developers/gitignore/api/node,linux
# Edit at https://www.toptal.com/developers/gitignore?templates=node,linux
### Linux ###
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
### Node ###
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
.env*.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# End of https://www.toptal.com/developers/gitignore/api/node,linux

99
sources/following-renames-in-gitlog/README.md

@ -0,0 +1,99 @@
# Following renames in gitlog
This demo serves as a minimal working example for the blog post
<https://peterbabic.dev/blog/following-renames-in-gitlog>
The method outlined here is curently used in my blog to determine when the
markdown blog post file was published and also when it was last edited.
## Setup
```bash
git clone https://git.peterbabic.dev/demo/following-renames-gitlog.git
cd following-renames-gitlog
npm install
npm run dev
```
This should produce the following output:
```js
{
status: [ 'M' ],
files: [ 'renamed-blog-post.md' ],
subject: 'add additional sentence to to blog post',
authorName: 'Peter Babič',
authorDate: '2020-12-03 22:07:31 +0100'
}
{
status: [ 'M' ],
files: [ 'renamed-blog-post.md' ],
subject: 'insert a chapter into post',
authorName: 'Peter Babič',
authorDate: '2020-12-03 21:51:19 +0100'
}
{
status: [ 'R100', 'D' ],
files: [ 'renamed-blog-post.md', 'blog-post.md' ],
subject: 'rename blog post',
authorName: 'Peter Babič',
authorDate: '2020-12-03 21:49:27 +0100'
}
{
status: [ 'A' ],
files: [ 'blog-post.md' ],
subject: 'insert blog post file to track',
authorName: 'Peter Babič',
authorDate: '2020-12-03 20:54:27 +0100'
}
```
Which is equivalent to the command
```bash
git log --follow --name-status renamed-blog-post.md
```
Producing the output
```
commit 48831b93a453f7c88838620509ccae6f9feaf851
Author: Peter Babič <peter@babic.dev>
Date: Thu Dec 3 22:07:31 2020 +0100
add additional sentence to to blog post
M renamed-blog-post.md
commit f6732cbfb7d787f62190b983f73901dd05f749e5
Author: Peter Babič <peter@babic.dev>
Date: Thu Dec 3 21:51:19 2020 +0100
insert a chapter into post
M renamed-blog-post.md
commit 70955f7c2ecdec469226f8226a10ad313497972e
Author: Peter Babič <peter@babic.dev>
Date: Thu Dec 3 21:49:27 2020 +0100
rename blog post
R100 blog-post.md renamed-blog-post.md
commit 86b45b4a5a7aee4726834e70f0ede60ac961abc5
Author: Peter Babič <peter@babic.dev>
Date: Thu Dec 3 20:54:27 2020 +0100
insert blog post file to track
A blog-post.md
```
With the difference that the former is already parsed and ready to use in a
script.
## License
MIT

809
sources/following-renames-in-gitlog/package-lock.json

@ -0,0 +1,809 @@
{
"name": "gitlog-published",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@types/strip-bom": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz",
"integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=",
"dev": true
},
"@types/strip-json-comments": {
"version": "0.0.30",
"resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz",
"integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==",
"dev": true
},
"anymatch": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
"integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
"dev": true,
"requires": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
}
},
"arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
"dev": true
},
"array-find-index": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
"integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
"dev": true
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"dev": true
},
"binary-extensions": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
"integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
"dev": true
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dev": true,
"requires": {
"fill-range": "^7.0.1"
}
},
"buffer-from": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
"dev": true
},
"camelcase": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
"integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
"dev": true
},
"camelcase-keys": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
"integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
"dev": true,
"requires": {
"camelcase": "^2.0.0",
"map-obj": "^1.0.0"
}
},
"chokidar": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz",
"integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==",
"dev": true,
"requires": {
"anymatch": "~3.1.1",
"braces": "~3.0.2",
"fsevents": "~2.1.2",
"glob-parent": "~5.1.0",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.5.0"
}
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"create-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"dev": true
},
"currently-unhandled": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
"integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
"dev": true,
"requires": {
"array-find-index": "^1.0.1"
}
},
"date-fns": {
"version": "2.16.1",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.16.1.tgz",
"integrity": "sha512-sAJVKx/FqrLYHAQeN7VpJrPhagZc9R4ImZIWYRFZaaohR3KzmuK88touwsSwSVT8Qcbd4zoDsnGfX4GFB4imyQ=="
},
"dateformat": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz",
"integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=",
"dev": true,
"requires": {
"get-stdin": "^4.0.1",
"meow": "^3.3.0"
}
},
"debug": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"requires": {
"ms": "2.1.2"
}
},
"decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
"dev": true
},
"diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"dev": true
},
"dynamic-dedupe": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz",
"integrity": "sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE=",
"dev": true,
"requires": {
"xtend": "^4.0.0"
}
},
"error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
"dev": true,
"requires": {
"is-arrayish": "^0.2.1"
}
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dev": true,
"requires": {
"to-regex-range": "^5.0.1"
}
},
"find-up": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
"integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
"dev": true,
"requires": {
"path-exists": "^2.0.0",
"pinkie-promise": "^2.0.0"
}
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"fsevents": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
"integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
"dev": true,
"optional": true
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
},
"get-stdin": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
"integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
"dev": true
},
"gitlog": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/gitlog/-/gitlog-4.0.3.tgz",
"integrity": "sha512-rWejI3r/UXo2egYMJRwI3w/lTVNjP8yT9oz29hkv69qlatKj3Y0PmUYU1x+3fILx+qJJBKjEEHgYTFygOV3a+Q==",
"requires": {
"debug": "^4.1.1",
"tslib": "^1.11.1"
}
},
"glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"glob-parent": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
"integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
"dev": true,
"requires": {
"is-glob": "^4.0.1"
}
},
"graceful-fs": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
"dev": true
},
"has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"dev": true,
"requires": {
"function-bind": "^1.1.1"
}
},
"hosted-git-info": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
"integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
"dev": true
},
"indent-string": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
"integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
"dev": true,
"requires": {
"repeating": "^2.0.0"
}
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
"dev": true
},
"is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"dev": true,
"requires": {
"binary-extensions": "^2.0.0"
}
},
"is-core-module": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz",
"integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==",
"dev": true,
"requires": {
"has": "^1.0.3"
}
},
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
"dev": true
},
"is-finite": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz",
"integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==",
"dev": true
},
"is-glob": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
"dev": true,
"requires": {
"is-extglob": "^2.1.1"
}
},
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true
},
"is-utf8": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
"integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
"dev": true
},
"load-json-file": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
"dev": true,
"requires": {
"graceful-fs": "^4.1.2",
"parse-json": "^2.2.0",
"pify": "^2.0.0",
"pinkie-promise": "^2.0.0",
"strip-bom": "^2.0.0"
}
},
"loud-rejection": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
"integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
"dev": true,
"requires": {
"currently-unhandled": "^0.4.1",
"signal-exit": "^3.0.0"
}
},
"make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"dev": true
},
"map-obj": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
"integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
"dev": true
},
"meow": {
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
"integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
"dev": true,
"requires": {
"camelcase-keys": "^2.0.0",
"decamelize": "^1.1.2",
"loud-rejection": "^1.0.0",
"map-obj": "^1.0.1",
"minimist": "^1.1.3",
"normalize-package-data": "^2.3.4",
"object-assign": "^4.0.1",
"read-pkg-up": "^1.0.1",
"redent": "^1.0.0",
"trim-newlines": "^1.0.0"
}
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
"dev": true
},
"mkdirp": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
"dev": true
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"normalize-package-data": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
"integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
"dev": true,
"requires": {
"hosted-git-info": "^2.1.4",
"resolve": "^1.10.0",
"semver": "2 || 3 || 4 || 5",
"validate-npm-package-license": "^3.0.1"
}
},
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"dev": true
},
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
"dev": true
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"requires": {
"wrappy": "1"
}
},
"parse-json": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
"integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
"dev": true,
"requires": {
"error-ex": "^1.2.0"
}
},
"path-exists": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
"integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
"dev": true,
"requires": {
"pinkie-promise": "^2.0.0"
}
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true
},
"path-parse": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
"dev": true
},
"path-type": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
"integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
"dev": true,
"requires": {
"graceful-fs": "^4.1.2",
"pify": "^2.0.0",
"pinkie-promise": "^2.0.0"
}
},
"picomatch": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
"dev": true
},
"pify": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
"dev": true
},
"pinkie": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
"integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
"dev": true
},
"pinkie-promise": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
"integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
"dev": true,
"requires": {
"pinkie": "^2.0.0"
}
},
"read-pkg": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
"integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
"dev": true,
"requires": {
"load-json-file": "^1.0.0",
"normalize-package-data": "^2.3.2",
"path-type": "^1.0.0"
}
},
"read-pkg-up": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
"integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
"dev": true,
"requires": {
"find-up": "^1.0.0",
"read-pkg": "^1.0.0"
}
},
"readdirp": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
"integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
"dev": true,
"requires": {
"picomatch": "^2.2.1"
}
},
"redent": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
"integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
"dev": true,
"requires": {
"indent-string": "^2.1.0",
"strip-indent": "^1.0.1"
}
},
"repeating": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
"integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
"dev": true,
"requires": {
"is-finite": "^1.0.0"
}
},
"resolve": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz",
"integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==",
"dev": true,
"requires": {
"is-core-module": "^2.1.0",
"path-parse": "^1.0.6"
}
},
"rimraf": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
"dev": true,
"requires": {
"glob": "^7.1.3"
}
},
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true
},
"signal-exit": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
"dev": true
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
},
"source-map-support": {
"version": "0.5.19",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
"integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
"dev": true,
"requires": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
"spdx-correct": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
"integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
"dev": true,
"requires": {
"spdx-expression-parse": "^3.0.0",
"spdx-license-ids": "^3.0.0"
}
},
"spdx-exceptions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
"integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
"dev": true
},
"spdx-expression-parse": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
"integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
"dev": true,
"requires": {
"spdx-exceptions": "^2.1.0",
"spdx-license-ids": "^3.0.0"
}
},
"spdx-license-ids": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz",
"integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==",
"dev": true
},
"strip-bom": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
"integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
"dev": true,
"requires": {
"is-utf8": "^0.2.0"
}
},
"strip-indent": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
"integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
"dev": true,
"requires": {
"get-stdin": "^4.0.1"
}
},
"strip-json-comments": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
"dev": true
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"requires": {
"is-number": "^7.0.0"
}
},
"tree-kill": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
"integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
"dev": true
},
"trim-newlines": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
"integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
"dev": true
},
"ts-node": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.0.tgz",
"integrity": "sha512-0yqcL4sgruCvM+w64LiAfNJo6+lHfCYc5Ajj4yiLNkJ9oZ2HWaa+Kso7htYOOxVQ7+csAjdUjffOe9PIqC4pMg==",
"dev": true,
"requires": {
"arg": "^4.1.0",
"create-require": "^1.1.0",
"diff": "^4.0.1",
"make-error": "^1.1.1",
"source-map-support": "^0.5.17",
"yn": "3.1.1"
}
},
"ts-node-dev": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-1.0.0.tgz",
"integrity": "sha512-leA/3TgGtnVU77fGngBwVZztqyDRXirytR7dMtMWZS5b2hGpLl+VDnB0F/gf3A+HEPSzS/KwxgXFP7/LtgX4MQ==",
"dev": true,
"requires": {
"chokidar": "^3.4.0",
"dateformat": "~1.0.4-1.2.3",
"dynamic-dedupe": "^0.3.0",
"minimist": "^1.2.5",
"mkdirp": "^1.0.4",
"resolve": "^1.0.0",
"rimraf": "^2.6.1",
"source-map-support": "^0.5.12",
"tree-kill": "^1.2.2",
"ts-node": "^9.0.0",
"tsconfig": "^7.0.0"
}
},
"tsconfig": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz",
"integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==",
"dev": true,
"requires": {
"@types/strip-bom": "^3.0.0",
"@types/strip-json-comments": "0.0.30",
"strip-bom": "^3.0.0",
"strip-json-comments": "^2.0.0"
},
"dependencies": {
"strip-bom": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
"integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
"dev": true
}
}
},
"tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"typescript": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.2.tgz",
"integrity": "sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ==",
"dev": true
},
"validate-npm-package-license": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
"integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
"dev": true,
"requires": {
"spdx-correct": "^3.0.0",
"spdx-expression-parse": "^3.0.0"
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
},
"xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
"dev": true
},
"yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"dev": true
}
}
}

19
sources/following-renames-in-gitlog/package.json

@ -0,0 +1,19 @@
{
"name": "gitlog-published",
"version": "1.0.0",
"description": "",
"main": "server.ts",
"scripts": {
"dev": "ts-node-dev --respawn server.ts"
},
"author": "peter.babic",
"license": "MIT",
"devDependencies": {
"ts-node-dev": "^1.0.0",
"typescript": "^4.1.2"
},
"dependencies": {
"date-fns": "^2.16.1",
"gitlog": "^4.0.3"
}
}

7
sources/following-renames-in-gitlog/renamed-blog-post.md

@ -0,0 +1,7 @@
# Example post
Lorem ipsum dolor sit amet ...
## Next chapter
Chapter and a new sentence.

10
sources/following-renames-in-gitlog/server.ts

@ -0,0 +1,10 @@
import gitlog, { GitlogOptions } from "gitlog"
const options: GitlogOptions = {
repo: ".",
fields: ["subject", "authorName", "authorDate"] as const,
branch: "--follow",
file: "renamed-blog-post.md",
}
gitlog(options).forEach(entry => console.log(entry))

7
sources/following-renames-in-gitlog/tsconfig.json

@ -0,0 +1,7 @@
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"lib": ["ES2017", "DOM"]
}
}

1
sources/how-commit-history-tells-when-post-published/.gitignore

@ -0,0 +1 @@
node_modules/

105
sources/how-commit-history-tells-when-post-published/README.md

@ -0,0 +1,105 @@
# Introduction
This repository serves as a proof-of-concept and starting point for using
[nodegit](https://github.com/nodegit/nodegit) to figure out when a file was
created and when it was last updated, not based on timestamps (atime,
ctime, mtime) but based solely on commit history.
## Motivation
The way how timestamps are set is distribution dependent. Or in other
words, they depend on `atime` option set in `/etc/fstab/`. You can read
about different options in an Arch
[wiki](https://wiki.archlinux.org/index.php/Fstab#atime_options).
The way how timestamps are read also depends on access to the filesystem,
which may or may not be avaiable. Overall, for the purpose of tracking when
a markdown file was created and updated, this is not a universal, nor a
portable solution.
## Alternatives
A common solution to this problem is to store this timestamps in a database
of some kind. But setting up a database just for the purpose of storing a
filename and it's timestamps might not be desirable. This also adds a
complexity in a form of synchronizing the filenames in the filesystem and a
database.
Of course, when the database with the timestamps is already there, one
could just store the entire markdown content in itm instead of just the
filename, but then again, you cold not write the markdown file easily with
your editor.
## Solution
In a git based workflow, the required timestamps are already stored in a
repository. According to a StackOverflow
[question](https://stackoverflow.com/questions/11533199/git-find-commit-where-file-was-added)
this can be done like this:
```bash
# get a commit where a file foo.js was created
git log --diff-filter=A -- foo.js
```
Using a `git-diff`
[documentation](https://git-scm.com/docs/git-diff#Documentation/git-diff.txt---diff-filterACDMRTUXB82308203)
we can elaborate further:
```bash
# get a commit where a file foo.js was modified
git log --diff-filter=M -- foo.js
```
This proves that the task can be done. However, ideally we need to do it
programatically, without the need for running `bash`, which could also be
OS dependent, but natively in javascript. A layer of abstraction that
servers as a wrapper of git commands would suffice, because it would
presumably be less OS dependent.
## Solution
As with the most things in a javascript world, not one, but multiple such
abstraction layers / wrappers already exists. I would not list them all
here. Instead, without any research, somehow `nodegit` appealed to me as a
best tool for the job.
Running `npm run dev` shows the dates when file `added.ts` was created and
modified based on the commit history.
## Caveat
One problem that I have found with this approach is renaming the file. We
use [fileHistoryWalk](https://www.nodegit.org/api/revwalk/#fileHistoryWalk)
for walking the commit history. It returns an array of objects of type
`<HistoryEntry>`, which looks like it is not documented in an API as of
time of writing. Each object contains a _commit_, a _date_ and a _status_
entry. The first two are easy to work with but, since it is not documented,
at first I could not find out what that _status_ means. Experimentally I
have found it correlates to the
[diff delta](https://www.nodegit.org/api/diff/#DELTA) enum.
We can see, that value 4 stands for `RENAMED`, but since, we walk the
history of just one file, and renaming actually creates two filenames in a
commit history, this results in lost data. However, when not renaming
files, it works like a charm.
## Notes
- typescript is used here instead of javascript
- [date-fns](https://github.com/date-fns/date-fns) is used for formatting
the timestamps
## Further reading
- https://github.community/t/show-file-history-for-renamed-files/1740
- https://stackoverflow.com/questions/40957424/using-nodegit-how-can-i-find-the-date-a-given-file-was-last-updated-in-a-git-re
- https://github.com/nodegit/nodegit/issues/1116
- https://github.com/nodegit/nodegit/issues/1228
- https://github.com/nodegit/nodegit/blob/master/examples/walk-history-for-file.js
- https://stackoverflow.com/questions/51609682/nodegit-filehistorywalk-doesnt-show-merge-commit
- https://stackoverflow.com/questions/40957424/using-nodegit-how-can-i-find-the-date-a-given-file-was-last-updated-in-a-git-re:w
## License
MIT

41
sources/how-commit-history-tells-when-post-published/added.ts

@ -0,0 +1,41 @@
import { Repository, Commit, Diff, ConvenientPatch } from "nodegit"
;(async () => {
const repo = await Repository.open(".")
const master = await repo.getMasterCommit()
const history = master.history()
history.on("commit", async (commit: Commit) => {
const commitDiff = await commit.getDiff()
commitDiff.forEach(async (diff: Diff) => {
console.log(
"--- COMMIT ---\n",
commit.sha(),
commit.author().email(),
commit.date(),
commit.message(),
"deltas: ",
diff.numDeltas(),
diff?.getDelta(1)?.oldFile()?.path()
)
const patches = await diff.patches()
patches.forEach(async (patch: ConvenientPatch) => {
//const hunks = await patch.hunks()
/*hunks.forEach(async (hunk: ConvenientHunk) => {
console.log("diff: ", patch.oldFile().path(), patch.newFile().path())
console.log(hunk.header().trim())
const lines = await hunk.lines()
lines.forEach(async (line: DiffLine) => {
console.log(
String.fromCharCode(line.origin()) + line.content().trim()
)
})
})*/
})
})
})
history.start()
})()

44
sources/how-commit-history-tells-when-post-published/example-diff.js

@ -0,0 +1,44 @@
var nodegit = require("nodegit")
var path = require("path")
// This code examines the diffs between a particular commit and all of its
// parents. Since this commit is not a merge, it only has one parent. This is
// similar to doing `git show`.
nodegit.Repository.open(path.resolve(__dirname, ".git"))
.then(function (repo) {
return repo.getMasterCommit()
})
.then(function (commit) {
console.log("commit " + commit.sha())
console.log(
"Author:",
commit.author().name() + " <" + commit.author().email() + ">"
)
console.log("Date:", commit.date())
console.log("\n " + commit.message())
return commit.getDiff()
})
.done(function (diffList) {
diffList.forEach(function (diff) {
diff.patches().then(function (patches) {
patches.forEach(function (patch) {
patch.hunks().then(function (hunks) {
hunks.forEach(function (hunk) {
hunk.lines().then(function (lines) {
console.log(lines)
//console.log("diff", patch.oldFile().path(),
//patch.newFile().path());
//console.log(hunk.header().trim());
//lines.forEach(function(line) {
//console.log(String.fromCharCode(line.origin()) +
//line.content().trim());
//});
})
})
})
})
})
})
})

1693
sources/how-commit-history-tells-when-post-published/package-lock.json

File diff suppressed because it is too large

20
sources/how-commit-history-tells-when-post-published/package.json

@ -0,0 +1,20 @@
{
"name": "nodegit-test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "npx ts-node-dev --respawn revvalk.ts"
},
"author": "",
"license": "ISC",
"dependencies": {
"date-fns": "^2.14.0",
"nodegit": "^0.26.5"
},
"devDependencies": {
"@types/nodegit": "^0.26.6",
"ts-node-dev": "^1.0.0-pre.50",
"typescript": "^3.9.6"
}
}

61
sources/how-commit-history-tells-when-post-published/revvalk.ts

@ -0,0 +1,61 @@
import { Repository, Revwalk, Commit } from "nodegit"
import { format } from "date-fns"
enum STATUS {
"UNMODIFIED",
"ADDED",
"DELETED",
"MODIFIED",
}
const fileName = "added.ts"
const maxCount = 500
;(async () => {
const repo = await Repository.open(".")
const master = await repo.getMasterCommit()
const walker = repo.createRevWalk()
walker.push(master.id())
walker.sorting(Revwalk.SORT.REVERSE)
const fileHistory = await walker.fileHistoryWalk(fileName, maxCount)
let created: Date = new Date()
let modified: Date = new Date()
created.setTime(0)
modified.setTime(0)
fileHistory.forEach(file => {
const commit: Commit = file?.commit
const date = commit.date()
const status = file?.status
if (status === STATUS.ADDED && date.getTime() > created.getTime()) {
created = date
}
if (
status === STATUS.MODIFIED &&
date.getTime() > modified.getTime()
) {
modified = date
}
/*console.log(
commit.sha(),
commit.date(),
commit.author().email(),
"status: ",
STATUS[status]
)*/
})
const formatDate = (date: Date) => format(date, "dd-MM-yyyy")
console.log(
fileName,
"created:",
formatDate(created),
"modified:",
formatDate(modified)
)
})()

44
sources/how-commit-history-tells-when-post-published/test.js

@ -0,0 +1,44 @@
const Git = require("nodegit")
// Open the repository directory.
Git.Repository.open(".")
// Open the master branch.
.then(function (repo) {
return repo.getMasterCommit()
})
// Display information about commits on master.
.then(function (firstCommitOnMaster) {
// Create a new history event emitter.
var history = firstCommitOnMaster.history()
// Create a counter to only show up to 9 entries.
var count = 0
// Listen for commit events from the history.
history.on("commit", function (commit) {
// Disregard commits past 9.
if (++count >= 9) {
return
}
// Show the commit sha.
console.log("commit " + commit.sha())
// Store the author object.
var author = commit.author()
// Display author information.
console.log(
"Author:\t" + author.name() + " <" + author.email() + ">"
)
// Show the commit date.
console.log("Date:\t" + commit.date())
// Give some space and show the message.
console.log("\n " + commit.message())
})
// Start emitting events.
history.start()
})

133
sources/how-to-assert-sorted-dates-cypress/.gitignore

@ -0,0 +1,133 @@
cypress/screenshots
cypress/videos
# Created by https://www.toptal.com/developers/gitignore/api/node,linux
# Edit at https://www.toptal.com/developers/gitignore?templates=node,linux
### Linux ###
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
### Node ###
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
.env*.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# End of https://www.toptal.com/developers/gitignore/api/node,linux

21
sources/how-to-assert-sorted-dates-cypress/README.md

@ -0,0 +1,21 @@
# Asserting sorted dates in Cypress
This demo serves as a minimal working example for the blog post
<https://peterbabic.dev/blog/how-to-assert-sorted-dates-cypress>
## Setup
```bash
git clone https://git.peterbabic.dev/demo/datetime-sorted-cypress.git
cd datetime-sorted-cypress
npm install
npm run test
```
The test should pass. Consider playing with the [index.html](index.html),
re-ordering the dates to affect the test result.
## License
MIT

3
sources/how-to-assert-sorted-dates-cypress/cypress.json

@ -0,0 +1,3 @@
{
"baseUrl": "http://localhost:3000/"
}

18
sources/how-to-assert-sorted-dates-cypress/cypress/integration/spec.js

@ -0,0 +1,18 @@
/// <reference types="cypress" />
import { parse } from "date-fns"
describe("Date list should", () => {
it("have dates sorted chronologically", () => {
cy.visit("/")
const parseDate = date => parse(date, "dd.MM.yyyy", new Date())
let prevDate = parseDate("01.01.1970")
cy.get("ul#sorted li").each($pre => {
const currentDate = parseDate($pre.text())
expect(prevDate).to.be.lte(currentDate)
prevDate = currentDate
})
})
})

21
sources/how-to-assert-sorted-dates-cypress/cypress/plugins/index.js

@ -0,0 +1,21 @@
/// <reference types="cypress" />
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
}

25
sources/how-to-assert-sorted-dates-cypress/cypress/support/commands.js

@ -0,0 +1,25 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add("login", (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })

20
sources/how-to-assert-sorted-dates-cypress/cypress/support/index.js

@ -0,0 +1,20 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here: