diff --git a/.yo-rc.json b/.yo-rc.json index dcde6e6..c9c532e 100644 --- a/.yo-rc.json +++ b/.yo-rc.json @@ -1,5 +1,18 @@ { "generator-tsmod": { + "addedFilesSafe": { + ".eslintrc.js": "661c7c22fbe2a894f22ac1e32568d3faa6f760c3", + "docs/.vuepress/config.js": "6a5e033facba2a2688eec8e64682b1d1848a711e", + "docs/.vuepress/public/images/hero.png": "f7d092f830ac982576d2db89dcbd434dc43a519d", + "docs/README.md": "2a4ea15be4beb2585a479cb28d653e0d0b824cec", + "docs/nav.01.guide/README.md": "436ec15d007cdd6899ec19dc1036bc01df6b3b9b", + "docs/nav.01.guide/guide--nc/usage.md": "436ec15d007cdd6899ec19dc1036bc01df6b3b9b", + "docs/nav.02.api/01.typedoc-iframe.md": "de3fe9eeebedcc31abeef79c3e2eb9ad8b19ac5b", + "jest.config.js": "0bd134f06add10c42a03e4b115aef2a323e4b136", + "lint-staged.config.js": "cbb09ecb17251589a793f69fea1a59c20f82a2c5", + "prettier.config.js": "2339672f6e5b8d3aeebe63b98613dca158b8b650", + "tsconfig.json": "86c1ebbd8975dcf218636f0a737b1bb310c2fd9a" + }, "createdDirs": ["module-files", ".github", ".husky"], "addedData": { "package.json": { @@ -8,7 +21,7 @@ "author.name": "Özüm Eldoğan", "author.url": "https://www.ozum.net/", "bugs": "https://github.com/ozum/pg-generator/issues", - "engines.node": ">= 12.0.0", + "engines.node": ">= 14.0.0", "files": ["dist", "!dist/**/@(*.spec|*.test)*", "!dist/**/__test__", "module-files"], "repository": "ozum/pg-generator", "scripts.build": "tsc", @@ -32,8 +45,8 @@ "vuepress.google-analytics-id": "" }, "normal": { - "devDependencies.@commitlint/cli": "^11.0.0", - "devDependencies.@commitlint/config-conventional": "^11.0.0", + "devDependencies.@commitlint/cli": "^12.0.1", + "devDependencies.@commitlint/config-conventional": "^12.0.1", "devDependencies.@ozum/pinst": "^2.1.4", "devDependencies.@types/jest": "^26.0.20", "devDependencies.@types/node": "^14.14.31", @@ -46,7 +59,7 @@ "devDependencies.concat-md": "^0.3.5", "devDependencies.eslint": "^7.20.0", "devDependencies.eslint-config-airbnb-base": "^14.1.0", - "devDependencies.eslint-config-prettier": "^7.2.0", + "devDependencies.eslint-config-prettier": "^8.1.0", "devDependencies.eslint-plugin-import": "^2.22.0", "devDependencies.eslint-plugin-jest": "^24.1.5", "devDependencies.eslint-plugin-prettier": "^3.3.1", @@ -60,31 +73,19 @@ "devDependencies.readmeasy": "^0.2.7", "devDependencies.ts-jest": "^26.5.1", "devDependencies.ts-node-dev": "^1.1.1", - "devDependencies.typedoc": "^0.20.27", + "devDependencies.typedoc": "^0.20.28", "devDependencies.typedoc-neo-theme": "^1.1.0", "devDependencies.typedoc-plugin-example-tag": "^1.0.2", - "devDependencies.typedoc-plugin-markdown": "^3.5.0", + "devDependencies.typedoc-plugin-markdown": "^3.6.0", "devDependencies.typedoc-plugin-param-names": "^2.0.0", "devDependencies.typescript": "^4.1.5", "devDependencies.vuepress": "^1.8.2", "devDependencies.vuepress-bar": "^0.3.5", + "devDependencies.vuepress-plugin-mermaidjs": "^1.8.1", "devDependencies.walkdir": "^0.4.1" } } }, - "addedFilesSafe": { - ".eslintrc.js": "661c7c22fbe2a894f22ac1e32568d3faa6f760c3", - "docs/.vuepress/config.js": "88d80937f65fd1a32bda8b35ca3a5101cbaf4f8c", - "docs/.vuepress/public/images/hero.png": "f7d092f830ac982576d2db89dcbd434dc43a519d", - "docs/README.md": "2a4ea15be4beb2585a479cb28d653e0d0b824cec", - "docs/nav.01.guide/README.md": "436ec15d007cdd6899ec19dc1036bc01df6b3b9b", - "docs/nav.01.guide/guide--nc/usage.md": "436ec15d007cdd6899ec19dc1036bc01df6b3b9b", - "docs/nav.02.api/01.typedoc-iframe.md": "de3fe9eeebedcc31abeef79c3e2eb9ad8b19ac5b", - "jest.config.js": "0bd134f06add10c42a03e4b115aef2a323e4b136", - "lint-staged.config.js": "cbb09ecb17251589a793f69fea1a59c20f82a2c5", - "prettier.config.js": "2339672f6e5b8d3aeebe63b98613dca158b8b650", - "tsconfig.json": "86c1ebbd8975dcf218636f0a737b1bb310c2fd9a" - }, "addedFiles": [ ".commitlintrc", ".czrc", diff --git a/README.md b/README.md index 264fd68..6661058 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,19 @@ Template based scaffolding tool for PostgreSQL. - [Methods](#methods) - [generate](#generate-1) - [Interfaces](#interfaces-1) -- [Interface: GeneratorOptions](#interface-generatoroptions) +- [Interface: ClientOptions](#interface-clientoptions) + - [Hierarchy](#hierarchy) - [Properties](#properties) + - [client](#client) + - [connectionString](#connectionstring) + - [database](#database) + - [host](#host) + - [password](#password) + - [port](#port) + - [ssl](#ssl) + - [user](#user) +- [Interface: GeneratorOptions](#interface-generatoroptions) + - [Properties](#properties-1) - [clear](#clear) - [context](#context) - [contextFile](#contextfile) @@ -42,11 +53,17 @@ Template based scaffolding tool for PostgreSQL. - [camelCase](#camelcase) - [classCase](#classcase) - [clearDefault](#cleardefault) + - [concat](#concat) - [dashCase](#dashcase) - [dboClassName](#dboclassname) - [dboColumnTypeModifier](#dbocolumntypemodifier) + - [doubleQuote](#doublequote) + - [fill](#fill) + - [human](#human) - [lcFirst](#lcfirst) - - [makeJsDoc](#makejsdoc) + - [linePrefix](#lineprefix) + - [listAttribute](#listattribute) + - [maxLength](#maxlength) - [padRight](#padright) - [pascalCase](#pascalcase) - [plural](#plural) @@ -59,7 +76,11 @@ Template based scaffolding tool for PostgreSQL. - [strip](#strip) - [stripPrefix](#stripprefix) - [stripSuffix](#stripsuffix) + - [titleCase](#titlecase) - [uniqueArray](#uniquearray) + - [wordWrap](#wordwrap) + - [wrap](#wrap) + - [wrapIf](#wrapif) @@ -94,6 +115,7 @@ Template based scaffolding tool for PostgreSQL. ### Interfaces +- [ClientOptions](#interfacesclientoptionsmd) - [GeneratorOptions](#interfacesgeneratoroptionsmd) ## Type aliases @@ -108,18 +130,18 @@ Context provided to render function. | Name | Type | | :--- | :--------------------- | +| `c` | _Record_ | | `o` | Db \| DbObject | -| `x` | _Record_ | -Defined in: [types/index.ts:53](https://github.com/ozum/pg-generator/blob/1b8e16d/src/types/index.ts#L53) +Defined in: [types/index.ts:53](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/types/index.ts#L53) --- ### Options -Ƭ **Options**: [_GeneratorOptions_](#interfacesgeneratoroptionsmd) & ClientOptions +Ƭ **Options**: [_GeneratorOptions_](#interfacesgeneratoroptionsmd) & [_ClientOptions_](#interfacesclientoptionsmd) -Defined in: [types/index.ts:50](https://github.com/ozum/pg-generator/blob/1b8e16d/src/types/index.ts#L50) +Defined in: [types/index.ts:50](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/types/index.ts#L50) ## Functions @@ -145,7 +167,7 @@ generate(require.resolve("./local-generator"), options); **Returns:** _Promise_ -Defined in: [generate.ts:15](https://github.com/ozum/pg-generator/blob/1b8e16d/src/generate.ts#L15) +Defined in: [generate.ts:15](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/generate.ts#L15) ▸ **generate**(`generator`: _string_, `subGenerator?`: _string_, `options?`: [_Options_](#options)): _Promise_ @@ -168,7 +190,7 @@ generate(require.resolve("./local-generator"), "sub-generator", options); **Returns:** _Promise_ -Defined in: [generate.ts:27](https://github.com/ozum/pg-generator/blob/1b8e16d/src/generate.ts#L27) +Defined in: [generate.ts:27](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/generate.ts#L27) # Classes @@ -209,7 +231,7 @@ Creates an instance of PgGenerator. **Returns:** [_PgGenerator_](#classespggeneratormd) -Defined in: [pg-generator.ts:23](https://github.com/ozum/pg-generator/blob/1b8e16d/src/pg-generator.ts#L23) +Defined in: [pg-generator.ts:24](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/pg-generator.ts#L24) ## Methods @@ -227,10 +249,102 @@ Additionally copies all files in `[rootDir]/files` to the output directory. **Returns:** _Promise_ -Defined in: [pg-generator.ts:47](https://github.com/ozum/pg-generator/blob/1b8e16d/src/pg-generator.ts#L47) +Defined in: [pg-generator.ts:51](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/pg-generator.ts#L51) # Interfaces + + +[pg-generator](#readmemd) / ClientOptions + +# Interface: ClientOptions + +## Hierarchy + +- _PgStructureOptions_ + + ↳ **ClientOptions** + +## Properties + +### client + +• `Optional` **client**: _undefined_ \| _string_ \| _Client_ \| ClientConfig + +Either a [node-postgres client](https://node-postgres.com/api/client) or a configuration object or a connection string to create a [node-postgres client](https://node-postgres.com/api/client). + +Defined in: [types/index.ts:20](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/types/index.ts#L20) + +--- + +### connectionString + +• `Optional` **connectionString**: _undefined_ \| _string_ + +Connection string to connect to the database e.g. postgres://user:password@host:5432/database + +Defined in: [types/index.ts:35](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/types/index.ts#L35) + +--- + +### database + +• `Optional` **database**: _undefined_ \| _string_ + +Database to connect. Default from environment var: PGDATABASE || DB_DATABASE + +Defined in: [types/index.ts:31](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/types/index.ts#L31) + +--- + +### host + +• `Optional` **host**: _undefined_ \| _string_ + +Database host. Default from environment var: PGHOST || DB_HOST + +Defined in: [types/index.ts:29](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/types/index.ts#L29) + +--- + +### password + +• `Optional` **password**: _undefined_ \| _string_ + +Database password. Default from environment var: PGPASSWORD || DB_PASSWORD + +Defined in: [types/index.ts:27](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/types/index.ts#L27) + +--- + +### port + +• `Optional` **port**: _undefined_ \| _string_ + +Database port. Default from environment var: PGPORT || DB_PORT + +Defined in: [types/index.ts:33](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/types/index.ts#L33) + +--- + +### ssl + +• `Optional` **ssl**: _any_ + +Passed directly to node.TLSSocket, supports all tls.connect options + +Defined in: [types/index.ts:37](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/types/index.ts#L37) + +--- + +### user + +• `Optional` **user**: _undefined_ \| _string_ + +Database username. Default from environment var: PGUSER || USER || DB_USER + +Defined in: [types/index.ts:25](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/types/index.ts#L25) + [pg-generator](#readmemd) / GeneratorOptions @@ -247,7 +361,7 @@ Options for generation and reverse engineering process. Options extends [pg-stru Whether to clear the destination directory before creating files. -Defined in: [types/index.ts:7](https://github.com/ozum/pg-generator/blob/1b8e16d/src/types/index.ts#L7) +Defined in: [types/index.ts:7](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/types/index.ts#L7) --- @@ -257,7 +371,7 @@ Defined in: [types/index.ts:7](https://github.com/ozum/pg-generator/blob/1b8e16d Extra context data. This data is merged with and overridden by data from context file. -Defined in: [types/index.ts:13](https://github.com/ozum/pg-generator/blob/1b8e16d/src/types/index.ts#L13) +Defined in: [types/index.ts:13](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/types/index.ts#L13) --- @@ -267,7 +381,7 @@ Defined in: [types/index.ts:13](https://github.com/ozum/pg-generator/blob/1b8e16 Path to a JSON or JS file providing extra context for templates. -Defined in: [types/index.ts:11](https://github.com/ozum/pg-generator/blob/1b8e16d/src/types/index.ts#L11) +Defined in: [types/index.ts:11](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/types/index.ts#L11) --- @@ -277,7 +391,7 @@ Defined in: [types/index.ts:11](https://github.com/ozum/pg-generator/blob/1b8e16 Whether to log output to console. -Defined in: [types/index.ts:15](https://github.com/ozum/pg-generator/blob/1b8e16d/src/types/index.ts#L15) +Defined in: [types/index.ts:15](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/types/index.ts#L15) --- @@ -287,7 +401,7 @@ Defined in: [types/index.ts:15](https://github.com/ozum/pg-generator/blob/1b8e16 Path of the output directory. -Defined in: [types/index.ts:9](https://github.com/ozum/pg-generator/blob/1b8e16d/src/types/index.ts#L9) +Defined in: [types/index.ts:9](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/types/index.ts#L9) # Modules @@ -313,7 +427,7 @@ Defined in: [types/index.ts:9](https://github.com/ozum/pg-generator/blob/1b8e16d **Returns:** _string_ -Defined in: converters/mermaid-to-svg.ts:8 +Defined in: [converters/mermaid-to-svg.ts:8](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/converters/mermaid-to-svg.ts#L8) @@ -325,7 +439,7 @@ Defined in: converters/mermaid-to-svg.ts:8 ### camelCase -▸ **camelCase**(`input`: _string_): _string_ +▸ **camelCase**(`input?`: _string_): _string_ Converts the given input to the camel case. @@ -337,21 +451,21 @@ camelCase("user-name"); // userName #### Parameters: -| Name | Type | Description | -| :------ | :------- | :------------------------------ | -| `input` | _string_ | is the input string to convert. | +| Name | Type | Default value | Description | +| :------ | :------- | :------------ | :------------------------------ | +| `input` | _string_ | "" | is the input string to convert. | **Returns:** _string_ string as camel case. -Defined in: [utils/filter-functions.ts:48](https://github.com/ozum/pg-generator/blob/1b8e16d/src/utils/filter-functions.ts#L48) +Defined in: [utils/filter-functions.ts:49](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L49) --- ### classCase -▸ **classCase**(`input`: _string_): _string_ +▸ **classCase**(`input?`: _string_): _string_ Converts the given input to the class name. @@ -363,15 +477,15 @@ classCase("user-name"); // UserName #### Parameters: -| Name | Type | Description | -| :------ | :------- | :------------------------------ | -| `input` | _string_ | is the input string to convert. | +| Name | Type | Default value | Description | +| :------ | :------- | :------------ | :------------------------------ | +| `input` | _string_ | "" | is the input string to convert. | **Returns:** _string_ string as class case. -Defined in: [utils/filter-functions.ts:74](https://github.com/ozum/pg-generator/blob/1b8e16d/src/utils/filter-functions.ts#L74) +Defined in: [utils/filter-functions.ts:75](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L75) --- @@ -401,13 +515,30 @@ clearDefaultValue("'No ''value'' given'"); // "No value 'given'" default value to be used in a template. -Defined in: [utils/filter-functions.ts:26](https://github.com/ozum/pg-generator/blob/1b8e16d/src/utils/filter-functions.ts#L26) +Defined in: [utils/filter-functions.ts:27](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L27) + +--- + +### concat + +▸ **concat**(`input`: _Record_, ...`objects`: _Record_[]): _Record_ + +#### Parameters: + +| Name | Type | +| :----------- | :----------------------- | +| `input` | _Record_ | +| `...objects` | _Record_[] | + +**Returns:** _Record_ + +Defined in: [utils/filter-functions.ts:477](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L477) --- ### dashCase -▸ **dashCase**(`input`: _string_): _string_ +▸ **dashCase**(`input?`: _string_): _string_ Converts the given input to the dash case. @@ -419,40 +550,40 @@ dashCase("User Name"); // user-name #### Parameters: -| Name | Type | Description | -| :------ | :------- | :------------------------------ | -| `input` | _string_ | is the input string to convert. | +| Name | Type | Default value | Description | +| :------ | :------- | :------------ | :------------------------------ | +| `input` | _string_ | "" | is the input string to convert. | **Returns:** _string_ string as dash case. -Defined in: [utils/filter-functions.ts:100](https://github.com/ozum/pg-generator/blob/1b8e16d/src/utils/filter-functions.ts#L100) +Defined in: [utils/filter-functions.ts:101](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L101) --- ### dboClassName -▸ **dboClassName**(`object`: DbObject, `schema?`: _boolean_): _string_ +▸ **dboClassName**(`object?`: DbObject, `schema?`: _boolean_): _string_ Returns given the given database object name as a class name. #### Parameters: -| Name | Type | Default value | Description | -| :------- | :-------- | :------------ | :--------------------------------------------- | -| `object` | DbObject | - | is the object to get the name as a class name. | -| `schema` | _boolean_ | false | is whether to include schema name. | +| Name | Type | Default value | Description | +| :-------- | :-------- | :------------ | :--------------------------------------------- | +| `object?` | DbObject | - | is the object to get the name as a class name. | +| `schema` | _boolean_ | false | is whether to include schema name. | **Returns:** _string_ -Defined in: [utils/filter-functions.ts:319](https://github.com/ozum/pg-generator/blob/1b8e16d/src/utils/filter-functions.ts#L319) +Defined in: [utils/filter-functions.ts:493](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L493) --- ### dboColumnTypeModifier -▸ **dboColumnTypeModifier**(`column`: Column): _string_ +▸ **dboColumnTypeModifier**(`column?`: Column): _string_ Returns column length, precision and scale ready to be used in templates. @@ -465,21 +596,103 @@ columnTypeModifier(name); // (20) #### Parameters: -| Name | Type | Description | -| :------- | :----- | :---------------------------- | -| `column` | Column | is the column to get details. | +| Name | Type | Description | +| :-------- | :----- | :---------------------------- | +| `column?` | Column | is the column to get details. | **Returns:** _string_ modifier string. -Defined in: [utils/filter-functions.ts:333](https://github.com/ozum/pg-generator/blob/1b8e16d/src/utils/filter-functions.ts#L333) +Defined in: [utils/filter-functions.ts:508](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L508) + +--- + +### doubleQuote + +▸ **doubleQuote**(`input?`: _string_): _string_ + +Wraps the given string with double quotes. + +#### Example + +```typescript +plural("Some "example" text"); // "some \"example\" text" +``` + +#### Parameters: + +| Name | Type | Description | +| :------- | :------- | :---------------------------------------------- | +| `input?` | _string_ | is the input string to wrap with double quotes. | + +**Returns:** _string_ + +string with quotes. + +Defined in: [utils/filter-functions.ts:207](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L207) + +--- + +### fill + +▸ **fill**(`input?`: _string_, `length?`: _number_, `char?`: _string_): _string_ + +Completes given input's length using with given character (by default space). It may be used to align +strings in JSDoc etc. + +#### Example + +```typescript +completeWithChar("member", "10"); // "member " +completeWithChar("member", "10", "-"); // "member----" +``` + +#### Parameters: + +| Name | Type | Default value | Description | +| :------- | :------- | :------------ | :--------------------------------------- | +| `input` | _string_ | "" | is the input to complete length of. | +| `length` | _number_ | 20 | is the length of the finel string. | +| `char` | _string_ | " " | is the character to be used for filling. | + +**Returns:** _string_ + +Defined in: [utils/filter-functions.ts:294](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L294) + +--- + +### human + +▸ **human**(`input?`: _string_, `lowFirstLetter?`: _boolean_): _string_ + +Converts text to natural language. + +#### Example + +```typescript +human("message_properties"); // "Message properties" +human("message_properties", true); // "message properties" +``` + +#### Parameters: + +| Name | Type | Default value | Description | +| :---------------- | :-------- | :------------ | :------------------------------------------- | +| `input` | _string_ | "" | is the input string to convert. | +| `lowFirstLetter?` | _boolean_ | - | is whther to use small letter in first word. | + +**Returns:** _string_ + +string in human readable form. + +Defined in: [utils/filter-functions.ts:155](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L155) --- ### lcFirst -▸ **lcFirst**(`input`: _string_): _string_ +▸ **lcFirst**(`input?`: _string_): _string_ Converts the given input's first letter to the lower case. @@ -491,75 +704,149 @@ plural("User_name"); // User_name #### Parameters: -| Name | Type | Description | -| :------ | :------- | :------------------------------ | -| `input` | _string_ | is the input string to convert. | +| Name | Type | Default value | Description | +| :------ | :------- | :------------ | :------------------------------ | +| `input` | _string_ | "" | is the input string to convert. | **Returns:** _string_ string with lower first case. -Defined in: [utils/filter-functions.ts:139](https://github.com/ozum/pg-generator/blob/1b8e16d/src/utils/filter-functions.ts#L139) +Defined in: [utils/filter-functions.ts:168](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L168) --- -### makeJsDoc +### linePrefix -▸ **makeJsDoc**(`input?`: _string_): _string_ +▸ **linePrefix**(`input?`: _string_, `prefix`: _string_): _string_ -Converts given string to JSOC lines by adding "\*" at the start of each line. +Adds given prefix each of the lines of given text. #### Example ```typescript -makeJsDoc(` +linePrefix( + ` Text line 1 Text line 2 -`); +`, + "// " +); -// * Text line 1 -// * Text line 1 +// Text line 1 +// Text line 2 ``` **`returs`** the result string. #### Parameters: -| Name | Type | Default value | Description | -| :------ | :------- | :------------ | :------------------------------ | -| `input` | _string_ | "" | is the input string to convert. | +| Name | Type | Default value | Description | +| :------- | :------- | :------------ | :-------------------------------------- | +| `input` | _string_ | "" | is the input string. | +| `prefix` | _string_ | - | is the prefix to add each of the lines. | + +**Returns:** _string_ + +Defined in: [utils/filter-functions.ts:357](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L357) + +--- + +### listAttribute + +▸ **listAttribute**(`objects`: T[], `attribute?`: keyof T, `options?`: { `join?`: _string_ ; `quote?`: _single_ \| _double_ \| _json_ ; `wrap?`: _string_ }): _string_ + +Returns an attribute of each objects as a CSV (comma separated values) + +#### Example + +```typescript +const objects = [{ name: "a" }, { name: "b" }, { name: "c" }]; + +listAttribute(objects, "name"); // a, b, c +listAttribute(objects, "name", { quote: "json" }); // "a", "b", "c" +listAttribute(objects, "name", { quote: "single" }); // 'a', 'b', 'c' +listAttribute(objects, "name", { quote: "json", wrap: "[]" }); // ["a", "b", "c"] +listAttribute(objects, "name", { quote: "json", wrap: "[]" }); // "a" +``` + +#### Type parameters: + +| Name | Type | +| :--- | :-------- | +| `T` | _unknown_ | + +#### Parameters: + +| Name | Type | Description | +| :--------------- | :----------------------------- | :-------------------------------------------------------------- | +| `objects` | T[] | are the array of objects to get attribute of. | +| `attribute` | keyof T | is the attribute to get for each object. | +| `options` | _object_ | are the options. | +| `options.join?` | _string_ | is the character to join list. | +| `options.quote?` | _single_ \| _double_ \| _json_ | is whether to add quotes around attributes. | +| `options.wrap?` | _string_ | is the characters to wrap the list if length is greater than 1. | + +**Returns:** _string_ + +the list as a string. + +Defined in: [utils/filter-functions.ts:449](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L449) + +--- + +### maxLength + +▸ **maxLength**(`input?`: _string_, `length?`: _number_): _string_ + +Cuts the text after given number of characters. + +#### Example + +```typescript +maxLength("some example text", 7); // "some ex..."; +``` + +#### Parameters: + +| Name | Type | Default value | Description | +| :------- | :------- | :------------ | :----------------------------- | +| `input` | _string_ | "" | is the text to shorten. | +| `length` | _number_ | 50 | is the maximum length allowed. | **Returns:** _string_ -Defined in: [utils/filter-functions.ts:237](https://github.com/ozum/pg-generator/blob/1b8e16d/src/utils/filter-functions.ts#L237) +cut text + +Defined in: [utils/filter-functions.ts:278](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L278) --- ### padRight -▸ **padRight**(`input`: _string_, `totalLength`: _number_, `paddingString?`: _string_): _string_ +▸ **padRight**(`input`: _string_ \| _undefined_, `totalLength`: _number_, `paddingString?`: _string_): _string_ Pads given string's end with given padding string to complete its length to count. #### Parameters: -| Name | Type | Default value | Description | -| :-------------- | :------- | :------------ | :---------------------------------------- | -| `input` | _string_ | - | is the input string to convert. | -| `totalLength` | _number_ | - | is the total length of the result string. | -| `paddingString` | _string_ | " " | is the string to pad with. | +| Name | Type | Default value | Description | +| :-------------- | :---------------------- | :------------ | :---------------------------------------- | +| `input` | _string_ \| _undefined_ | - | is the input string to convert. | +| `totalLength` | _number_ | - | is the total length of the result string. | +| `paddingString` | _string_ | " " | is the string to pad with. | **Returns:** _string_ the string padded with padding string. -Defined in: [utils/filter-functions.ts:216](https://github.com/ozum/pg-generator/blob/1b8e16d/src/utils/filter-functions.ts#L216) +Defined in: [utils/filter-functions.ts:261](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L261) --- ### pascalCase -▸ **pascalCase**(`input`: _string_): _string_ +▸ **pascalCase**(`input?`: _string_): _string_ Converts the given input to the pascal case. @@ -571,21 +858,21 @@ pascalCase("user-name"); // UserName #### Parameters: -| Name | Type | Description | -| :------ | :------- | :------------------------------ | -| `input` | _string_ | is the input string to convert. | +| Name | Type | Default value | Description | +| :------ | :------- | :------------ | :------------------------------ | +| `input` | _string_ | "" | is the input string to convert. | **Returns:** _string_ string as pascal case. -Defined in: [utils/filter-functions.ts:61](https://github.com/ozum/pg-generator/blob/1b8e16d/src/utils/filter-functions.ts#L61) +Defined in: [utils/filter-functions.ts:62](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L62) --- ### plural -▸ **plural**(`input`: _string_): _string_ +▸ **plural**(`input?`: _string_): _string_ Converts the given input to the plural form. @@ -597,21 +884,21 @@ plural("user_name"); // user_names #### Parameters: -| Name | Type | Description | -| :------ | :------- | :------------------------------ | -| `input` | _string_ | is the input string to convert. | +| Name | Type | Default value | Description | +| :------ | :------- | :------------ | :------------------------------ | +| `input` | _string_ | "" | is the input string to convert. | **Returns:** _string_ string in plural form. -Defined in: [utils/filter-functions.ts:126](https://github.com/ozum/pg-generator/blob/1b8e16d/src/utils/filter-functions.ts#L126) +Defined in: [utils/filter-functions.ts:140](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L140) --- ### quote -▸ **quote**(`input`: _string_): _string_ +▸ **quote**(`input?`: _string_): _string_ Wraps the given string with quotes. @@ -623,41 +910,41 @@ plural("user_name"); // "user_name" #### Parameters: -| Name | Type | Description | -| :------ | :------- | :--------------------------------------- | -| `input` | _string_ | is the input string to wrap with quotes. | +| Name | Type | Description | +| :------- | :------- | :--------------------------------------- | +| `input?` | _string_ | is the input string to wrap with quotes. | **Returns:** _string_ string with quotes. -Defined in: [utils/filter-functions.ts:152](https://github.com/ozum/pg-generator/blob/1b8e16d/src/utils/filter-functions.ts#L152) +Defined in: [utils/filter-functions.ts:181](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L181) --- ### singleLine -▸ **singleLine**(`input`: _string_): _string_ +▸ **singleLine**(`input?`: _string_): _string_ -If given data is a multi line string replcaes new lines with escape characters. May be used to prevent JS multi line errors. +If given data is a multi line string replaces new lines with escape characters. May be used to prevent JS multi line errors. #### Parameters: -| Name | Type | Description | -| :------ | :------- | :----------------------- | -| `input` | _string_ | is the input to convert. | +| Name | Type | Default value | Description | +| :------ | :------- | :------------ | :----------------------- | +| `input` | _string_ | "" | is the input to convert. | **Returns:** _string_ the string with escape characters. -Defined in: [utils/filter-functions.ts:293](https://github.com/ozum/pg-generator/blob/1b8e16d/src/utils/filter-functions.ts#L293) +Defined in: [utils/filter-functions.ts:415](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L415) --- ### singleQuote -▸ **singleQuote**(`input`: _string_): _string_ +▸ **singleQuote**(`input?`: _string_): _string_ Wraps the given string with single quotes. @@ -669,21 +956,21 @@ plural("Some 'example' text"); // 'some \'example\' text' #### Parameters: -| Name | Type | Description | -| :------ | :------- | :--------------------------------------- | -| `input` | _string_ | is the input string to wrap with quotes. | +| Name | Type | Description | +| :------- | :------- | :---------------------------------------------- | +| `input?` | _string_ | is the input string to wrap with single quotes. | **Returns:** _string_ string with quotes. -Defined in: [utils/filter-functions.ts:165](https://github.com/ozum/pg-generator/blob/1b8e16d/src/utils/filter-functions.ts#L165) +Defined in: [utils/filter-functions.ts:194](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L194) --- ### singular -▸ **singular**(`input`: _string_): _string_ +▸ **singular**(`input?`: _string_): _string_ Converts the given input to the singular form. @@ -695,21 +982,21 @@ singular("user_names"); // user_name #### Parameters: -| Name | Type | Description | -| :------ | :------- | :------------------------------ | -| `input` | _string_ | is the input string to convert. | +| Name | Type | Default value | Description | +| :------ | :------- | :------------ | :------------------------------ | +| `input` | _string_ | "" | is the input string to convert. | **Returns:** _string_ string in singular form. -Defined in: [utils/filter-functions.ts:113](https://github.com/ozum/pg-generator/blob/1b8e16d/src/utils/filter-functions.ts#L113) +Defined in: [utils/filter-functions.ts:127](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L127) --- ### snakeCase -▸ **snakeCase**(`input`: _string_): _string_ +▸ **snakeCase**(`input?`: _string_): _string_ Converts the given input to the snake case. @@ -721,21 +1008,21 @@ snakeCase("userName"); // user_name #### Parameters: -| Name | Type | Description | -| :------ | :------- | :------------------------------ | -| `input` | _string_ | is the input string to convert. | +| Name | Type | Default value | Description | +| :------ | :------- | :------------ | :------------------------------ | +| `input` | _string_ | "" | is the input string to convert. | **Returns:** _string_ string as snake case. -Defined in: [utils/filter-functions.ts:87](https://github.com/ozum/pg-generator/blob/1b8e16d/src/utils/filter-functions.ts#L87) +Defined in: [utils/filter-functions.ts:88](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L88) --- ### stringify -▸ **stringify**(`input`: _any_, `options?`: { `nullToUndef?`: _boolean_ ; `raw?`: _boolean_ }): _string_ +▸ **stringify**(`input`: _any_, `options?`: { `indent?`: _number_ ; `nullToUndef?`: _boolean_ ; `raw?`: _boolean_ }): _string_ If given data is object or array, converts it to string. @@ -744,24 +1031,25 @@ If given data is object or array, converts it to string. #### Parameters: -| Name | Type | Description | -| :--------------------- | :-------- | :----------------------- | -| `input` | _any_ | is the input to convert. | -| `options` | _object_ | - | -| `options.nullToUndef?` | _boolean_ | - | -| `options.raw?` | _boolean_ | - | +| Name | Type | Description | +| :--------------------- | :-------- | :---------------------------------------------- | +| `input` | _any_ | is the input to convert. | +| `options` | _object_ | are the options. | +| `options.indent?` | _number_ | is size of the indentation of each level. | +| `options.nullToUndef?` | _boolean_ | if true, converts all null values to undefined. | +| `options.raw?` | _boolean_ | if true, does not add quotes around values. | **Returns:** _string_ converted value. -Defined in: [utils/filter-functions.ts:270](https://github.com/ozum/pg-generator/blob/1b8e16d/src/utils/filter-functions.ts#L270) +Defined in: [utils/filter-functions.ts:392](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L392) --- ### strip -▸ **strip**(`input`: _string_, ...`removeList`: (_string_ \| { `name`: _string_ })[]): _string_ +▸ **strip**(`input`: _string_ \| _undefined_, ...`removeList`: (_string_ \| { `name`: _string_ })[]): _string_ Vairadic function which strips all of the given strings or database object's names from the source string. @@ -769,20 +1057,20 @@ Vairadic function which strips all of the given strings or database object's nam | Name | Type | Description | | :-------------- | :----------------------------------- | :------------------------------------------------------ | -| `input` | _string_ | is the input string to convert. | +| `input` | _string_ \| _undefined_ | is the input string to convert. | | `...removeList` | (_string_ \| { `name`: _string_ })[] | is the list of strings or objects to remove from input. | **Returns:** _string_ converted string. -Defined in: [utils/filter-functions.ts:202](https://github.com/ozum/pg-generator/blob/1b8e16d/src/utils/filter-functions.ts#L202) +Defined in: [utils/filter-functions.ts:246](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L246) --- ### stripPrefix -▸ **stripPrefix**(`input`: _string_, ...`removeList`: (_string_ \| { `name`: _string_ })[]): _string_ +▸ **stripPrefix**(`input`: _string_ \| _undefined_, ...`removeList`: (_string_ \| { `name`: _string_ })[]): _string_ Vairadic function which strips all of the given strings or database object's names from the start of the source string. @@ -790,20 +1078,20 @@ Vairadic function which strips all of the given strings or database object's nam | Name | Type | Description | | :-------------- | :----------------------------------- | :------------------------------------------------------ | -| `input` | _string_ | is the input string to convert. | +| `input` | _string_ \| _undefined_ | is the input string to convert. | | `...removeList` | (_string_ \| { `name`: _string_ })[] | is the list of strings or objects to remove from input. | **Returns:** _string_ converted string. -Defined in: [utils/filter-functions.ts:176](https://github.com/ozum/pg-generator/blob/1b8e16d/src/utils/filter-functions.ts#L176) +Defined in: [utils/filter-functions.ts:218](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L218) --- ### stripSuffix -▸ **stripSuffix**(`input`: _string_, ...`removeList`: (_string_ \| { `name`: _string_ })[]): _string_ +▸ **stripSuffix**(`input`: _string_ \| _undefined_, ...`removeList`: (_string_ \| { `name`: _string_ })[]): _string_ Vairadic function which strips all of the given strings or database object's names from the end of the source string. @@ -811,20 +1099,46 @@ Vairadic function which strips all of the given strings or database object's nam | Name | Type | Description | | :-------------- | :----------------------------------- | :------------------------------------------------------ | -| `input` | _string_ | is the input string to convert. | +| `input` | _string_ \| _undefined_ | is the input string to convert. | | `...removeList` | (_string_ \| { `name`: _string_ })[] | is the list of strings or objects to remove from input. | **Returns:** _string_ converted string. -Defined in: [utils/filter-functions.ts:189](https://github.com/ozum/pg-generator/blob/1b8e16d/src/utils/filter-functions.ts#L189) +Defined in: [utils/filter-functions.ts:232](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L232) + +--- + +### titleCase + +▸ **titleCase**(`input?`: _string_): _string_ + +Converts the given input to the title case. + +#### Example + +```typescript +titleCase("user_name"); // User Name +``` + +#### Parameters: + +| Name | Type | Default value | Description | +| :------ | :------- | :------------ | :------------------------------ | +| `input` | _string_ | "" | is the input string to convert. | + +**Returns:** _string_ + +string as title case. + +Defined in: [utils/filter-functions.ts:114](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L114) --- ### uniqueArray -▸ **uniqueArray**(`input`: T[]): T[] +▸ **uniqueArray**(`input?`: T[]): T[] Returns given array with unique elements by eliminating duplicate values. @@ -836,12 +1150,103 @@ Returns given array with unique elements by eliminating duplicate values. #### Parameters: -| Name | Type | Description | -| :------ | :--- | :----------------------------------------------- | -| `input` | T[] | is the input array to eliminate duplicates from. | +| Name | Type | Description | +| :------- | :--- | :----------------------------------------------- | +| `input?` | T[] | is the input array to eliminate duplicates from. | **Returns:** T[] the array with unique values. -Defined in: [utils/filter-functions.ts:303](https://github.com/ozum/pg-generator/blob/1b8e16d/src/utils/filter-functions.ts#L303) +Defined in: [utils/filter-functions.ts:425](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L425) + +--- + +### wordWrap + +▸ **wordWrap**(`input?`: _string_, `startOrStop?`: _number_, `stop?`: _number_): _string_ + +Word wraps given text. + +#### Example + +```typescript +wordWrap("The quick fox", 10); // "The quick\nfox" +wordWrap("The quick fox", 2, 10); // " The quick\n fox" +``` + +#### Parameters: + +| Name | Type | Default value | Description | +| :------------ | :------- | :------------ | :-------------------------------------------------------------------------------------------- | +| `input?` | _string_ | - | is the text to word wrap. | +| `startOrStop` | _number_ | 80 | is the start or the stop position of each line. (The stop position if this is single option.) | +| `stop?` | _number_ | - | is the stop position of each line. | + +**Returns:** _string_ + +word wrapped text. + +Defined in: [utils/filter-functions.ts:472](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L472) + +--- + +### wrap + +▸ **wrap**(`input?`: _string_, `wrapper?`: _string_): _string_ + +Wraps given text with start and end characters. By default it wraps with curly braces. + +#### Example + +```typescript +wrap("hello"); // "{hello}" +wrap("hello", "~"); // "~hello~" +wrap("hello", "[]"); // "[hello]" +``` + +#### Parameters: + +| Name | Type | Default value | Description | +| :-------- | :------- | :------------ | :------------------- | +| `input?` | _string_ | - | is the text to warp. | +| `wrapper` | _string_ | "{}" | - | + +**Returns:** _string_ + +wrapped text. + +Defined in: [utils/filter-functions.ts:312](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L312) + +--- + +### wrapIf + +▸ **wrapIf**(`input`: _string_ \| _undefined_, `condition`: _any_, `wrapper?`: _string_): _string_ + +Wraps given text with start and end characters if given condition is truthy. +By default it wraps with curly braces. + +#### Example + +```typescript +wrapIf("hello", "x"); // "{hello}" +wrapIf("hello", true); // "{hello}" +wrapIf("hello", false); // "hello" +wrapIf("hello", true, "~"); // "~hello~" +wrapIf("hello", true, "[]"); // "[hello]" +``` + +#### Parameters: + +| Name | Type | Default value | Description | +| :---------- | :---------------------- | :------------ | :--------------------------------- | +| `input` | _string_ \| _undefined_ | - | is the text to warp. | +| `condition` | _any_ | - | is the condition or value to test. | +| `wrapper` | _string_ | "{}" | - | + +**Returns:** _string_ + +wrapped text. + +Defined in: [utils/filter-functions.ts:336](https://github.com/ozum/pg-generator/blob/4ae6c3c/src/utils/filter-functions.ts#L336) diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 43c3901..aaa623c 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -1,6 +1,6 @@ // This is user editable config. -const baseCOnfig = require("../../module-files/configs/vuepress-config.js"); +const baseConfig = require("../../module-files/configs/vuepress-config.js"); module.exports = { - ...baseCOnfig, + ...baseConfig, }; diff --git a/docs/nav.01.guide/01.getting-started.md b/docs/nav.01.guide/01.getting-started.md new file mode 100644 index 0000000..3546897 --- /dev/null +++ b/docs/nav.01.guide/01.getting-started.md @@ -0,0 +1,62 @@ +# Getting Started + +This section will help you generate example files from the ground up. If you already have an existing project and would like to keep documentation inside the project, start from Step 3. + +- **Step 1:** Create a new directory and change into it. + + ```bash + $ mkdir my-project && cd my-project + ``` + +- **Step 2:** Create a `.env` file and add your credentials or use environment variables for database authorization. (You can also use parameters.) + + ```bash + $ touch .env + ``` + + Add and edit the following data to the `.env` file you just created. + + ```.env + DB_DATABASE=example + DB_HOST=localhost + DB_USER=user + DB_PASSWORD=password + ``` + +- **Step 3:** Install pg-generator locally or globally with your preferred package manager. If you install globally `pgen` command is available anywhere. + + ```bash + $ npm install -g pg-generator` + ``` + +- **Step 4:** Install a generator that contains templates. If you installed the pg-generator globally, install the generator globally too. For a start, you may install `pg-generator-example` to see how pg-generator works. `pg-generator-example` provides some example generators. + + ```bash + $ npm install -g pg-generator-example + ``` + +- **Step 5:** Run generator for your database. + + **CLI** + + ```bash + $ pgen example --out-dir models --clear + ``` + + **API** + + ```ts + import { generate } from "pg-generator"; + await generate("example", { outDir: "models", clear: true }); + ``` + + If you have complex relationships (e.g. multiple relations between the same tables etc.) in your database, you may get a naming collision error. You can try `--relation-name-functions optimal` and `--relation-name-functions descriptive`. They produce longer relation names to prevent a collision. + +## Examples + +See [pg-generator-example](https://www.npmjs.com/package/pg-generator-example) plugin for an example. It provides examples of: + +- Sub-generators for popular ORMs, markdown with mermaid support, and a report. +- Custom filters +- Custom context +- Shared partial usage diff --git a/docs/nav.01.guide/02.advanced.md b/docs/nav.01.guide/02.advanced.md new file mode 100644 index 0000000..aa8302d --- /dev/null +++ b/docs/nav.01.guide/02.advanced.md @@ -0,0 +1,9 @@ +# Advanced + +## Using Sub-Generators + +## Custom Context + +## Relation Names + +## Including & Excluding Schemas diff --git a/docs/nav.01.guide/06.changes.md b/docs/nav.01.guide/06.changes.md new file mode 100644 index 0000000..7bd7112 --- /dev/null +++ b/docs/nav.01.guide/06.changes.md @@ -0,0 +1,23 @@ +# Changes + +pg-generator is rewritten from scratch using TypeScript. The primary target of the new version is to make it simpler to use than the previous version is. The secondary target is making the generators (templates) easier to share using npm. As a result, major changes have been necessary. + +## Breaking Changes for Template Developers + +- Template file structure needs to be changed. +- Templates need modifications. +- Custom data and options files are merged into a single file. +- Uses pg-structure v7. See [v7 API](https://www.pg-structure.com/nav.02.api/) for details. The most notable change is `array` attribute is not needed (e.g. use `tables` instead of `tables.array`) + +| Old Name | New Name | Workload | +| ---------------- | ------------ | -------- | +| Templates | Generators | Light | +| Custom Data File | Context File | Moderate | +| Options File | Context File | Moderate | + +Please refer to [Creating a Generator ](nav.03.creating-generators) + +## Breaking Changes for Users + +- In the previous version templates are bundled with the library and hard to copy and modify for users. The new version does not provide built-in generators. Please install for `pg-generator-example` package from npm for example generators. Modify according to your needs and publish your generators. +- CLI tool was unnecessarily complex and have not so useful features for the majority of the users. New CLI is written from scratch and does not have interactive features anymore. diff --git a/docs/nav.01.guide/README.md b/docs/nav.01.guide/README.md index e10b99d..a4f0261 100644 --- a/docs/nav.01.guide/README.md +++ b/docs/nav.01.guide/README.md @@ -1 +1,57 @@ # Introduction + +## What is pg-generator + +pg-generator is a zero-config template-based scaffolding tool for PostgreSQL. It generates files for each database object (e.g. table, schema, view, column) of a PostgreSQL database. + +It processes every template file for each related database object. For example, a template file for a table is executed for each table in the database and written to disk. + +## Motivation + +We create lots of files, such as ORM models, reports, documentation based on the structure of the database. Synchronizing the files and the structure of the database is a real burden. A team member may forget to update ORM models or database documents after updating the database structure or could make a typo. Additionally, it is a slow and boring job. We developed the pg-generator for those kinds of jobs. Just create template files using your favorite templating engine and voila, pg-generator will create your files again, again, and again. + +## Features + +- Zero-config. The file tree of template files determines the final result. +- Provides CLI and API. +- Uses [pg-structure](https://www.pg-structure.com) under the hood, so every feature of the [pg-structure](https://www.pg-structure.com) is available in templates. +- Generators are template engine agnostic. You can use your favorite templating engine. +- Easy to share generators using npm. +- Supports most of the PostgreSQL objects. Every [class](https://www.pg-structure.com/nav.02.api/) of the pg-structure is available. + +## How It Works? + +Below is a simple example of a database and template files of a generator. + +### Database + +```mermaid +erDiagram + customer ||--o{ order : order_customer + order ||--|{ line_item : line_item_order + customer }|..|{ delivery_address : delivery_address_customer + + view_vip_customer +``` + +### Template Files of a Generator + +Brackets `[]` defines for which database object a template is for (see [classes](https://www.pg-structure.com/nav.02.api)), braces `{}` are for naming generated files, and `#` is used for filtering/converting the file name. For example; a template named `[table] {name}.js.njk` is executed for each database [table](https://www.pg-structure.com/nav.02.api/classes/table) and rendered content is written to disk using the name of the table. Also, the table object is passed to the template as the context data. For readability, an optional single space after brackets `[]` and spaces in braces `{}` are allowed. + +``` +└─ [db] index.js.njk + └─ models/ + └─ [table] {schema.name # dash-case}{name # dash-case}.js.njk + └─ [view] {name # dash-case}.js.njk +``` + +### Result + +``` +└─ index.js + └─ models/ + ├─ public.customer.js + ├─ public.delivery-address.js + ├─ public.line-item.js + └─ view-vip-customer.js +``` diff --git a/docs/nav.01.guide/guide--nc/usage.md b/docs/nav.01.guide/guide--nc/usage.md deleted file mode 100644 index 8f04b05..0000000 --- a/docs/nav.01.guide/guide--nc/usage.md +++ /dev/null @@ -1 +0,0 @@ -# Usage diff --git a/docs/nav.03.creating-generators/01.getting-started.md b/docs/nav.03.creating-generators/01.getting-started.md new file mode 100644 index 0000000..82e8176 --- /dev/null +++ b/docs/nav.03.creating-generators/01.getting-started.md @@ -0,0 +1,83 @@ +# Getting Started + +This section will help you generate a basic generator from the ground up. If you are not using TypeScript or Babel, please put files into the `lib` folder instead of the `src` folder. + +- **Step 1:** Create a new directory starting with "pg-generator" and change into it. + + ```bash + $ mkdir pg-generator-awesome && cd pg-generator-awesome + ``` + +- **Step 2:** Setup Node.js module. + + Create a `package.json` file and copy the following entries: + + ```json + { + "name": "pg-generator-awesome", + "version": "1.0.0", + "description": "pg-generator for my favorite ORM models.", + "files": ["dist", "lib"], + "keywords": ["pg-generator"] + } + ``` + +- **Step 3:** Install latest version of `pg-generator` and `nunjucks` templating engine we use in the examples. You can use any template engine. + + ```bash + $ npm install pg-generator nunjucks + ``` + +- **Step 4:** Create the default sub-generator `app`. + + ```bash + $ mkdir -p src/app/templates + ``` + +- **Step 5:** Add following generator and template file. + + **src/app/index.ts** + + ```ts + import { PgGenerator, Context } from "pg-generator"; + import { join } from "path"; + import { filterFunctions } from "pg-generator"; + import nunjucks, { Environment } from "nunjucks"; + + const nunjucksLoader = new nunjucks.FileSystemLoader(join(__dirname, "templates")); + const nunjucksEnvironment = new nunjucks.Environment(nunjucksLoader, { autoescape: false }); + Object.entries(...filterFunctions).forEach(([name, filter]) => nunjucksEnvironment.addFilter(name, filter)); + + export default class App extends PgGenerator { + /** + * Render content using context. Returned content is written to the disk by pg-generator. + * @param templatePath is the path of the template file. + * @param context is the data passed by pg-generator to the template file. + * @returns rendered content. + */ + protected async render(templatePath: string, context: Context): Promise { + return nunjucksEnvironment.render(templatePath, context); + } + } + ``` + + **src/app/templates/[table]{schema.name # dash-case}{name # dash-case}.md.njk** + + ```jinja2 + |PK|FK|Name|Type|NN|Index| + |:-:|:-:|---|---|:-:|:-:| + {%- for column in table.columns %} + |{{ "🔑" if column.isPrimaryKey }}|{{ "FK" if column.isForeignKey }}|{{column.name}}|{{column.type.name}}{{ column | dboColumnTypeModifier }}|{{ "●" if column.notNull else "○" }}|{{ column.indexes.length if column.indexes.length > 0 }}| + {%- endfor %} + ``` + + - **Step 6:** + +## Examples + +For advanced examples, see [pg-generator-example](https://github.com/ozum/pg-generator-example) plugin. It provides examples which you may use as a basis for your generators including: + +- Sub-generators for popular ORMs, markdown with mermaid support, and a report. +- Custom filters +- Custom context +- Shared partial usage diff --git a/docs/nav.03.creating-generators/02.adding-templates.md b/docs/nav.03.creating-generators/02.adding-templates.md new file mode 100644 index 0000000..8f0aa54 --- /dev/null +++ b/docs/nav.03.creating-generators/02.adding-templates.md @@ -0,0 +1,113 @@ +# Adding Templates + +pg-generator processes template files located in the `templates` folder in a generator and passes the corresponding database object and custom data provided by the user to the template file. + +Template files are executed for each corresponding database object. For example; `[db] index.js` file is processed once and passed the [db object](https://www.pg-structure.com/nav.02.api/classes/db), and `[table] {name}.js.njk` file is processed for each table in the database and passed [table object](https://www.pg-structure.com/nav.02.api/classes/table). + +See pg-structure [API](https://www.pg-structure.com/nav.02.api/) for all available objects. + +## Template Name + +The schema of a template name is as below: + +dist/app/templates/**_DESTINATION-DIR_**/_**\[DB-OBJECT\]**_ _**\{ VARIABLE # FILTER \}**_ _**\{ VARIABLE # FILTER \}**_ + +| Part | Description | +| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| **_DESTINATION-DIR_** | The irectory path of the file to be created in the destination. | +| _**\[DB-OBJECT\]**_ | The type of objects the template is related to (e.g. `db`, `schema`, `table`, `view`, `function` etc. See pg-structure [API](https://www.pg-structure.com/nav.02.api/)) | +| _**\{ VARIABLE \}**_ | The variable to substitute in destination file's name using database object. | +| **_# FILTER_** | The filter to apply variable name. May be chained to use multiple filters (e.g. `{ name # dash-case # singular }`). Filters may be written using dash-case or camel-case (e.g `class-case` or `classCase`). See [built-in filters](/nav.02.api/modules/filterfunctions). | + +### Examples + +```mermaid +erDiagram + customer ||--o{ order : order_customer + order ||--|{ line_item : line_item_order + customer }|..|{ delivery_address : delivery_address_customer + + view_vip_customer +``` + +| Template Path | Destination Path | +| ------------------------------------------------ | ----------------------------- | +| `models/[table] { name }.js.njk` | `models/customer.js` | +| `models/[table] { name # dash-case }.js.njk` | `models/line-item.js` | +| `models/[table]{name#class-case#plural}.js.njk` | `models/LineItems.js` | +| `models/{ schema.name }/[table] { name }.js.njk` | `models/public/line_items.js` | + +## Context Data + +Each template file is passed a context object. This context object contains the corresponding database object (e.g. `table`, `schema` etc.). Templates can access the database object either using object class name in camel case (e.g. `table`, `materailzedView` etc.) or using `o`. + +Also, a generator may add additional context data needed in templates too. For example, `pg-generator-example` sub-generatorsequelize6`adds sequelize types to be used in templates. Additionally, a generator may define default values in the context it adds, and provide the end-user the opportunity to change them using a custom context file or context module.`sequelize6`adds`addSchemaName`key with the default value`true` to decide whether to use PostgreSQL schema names in class names in generated files. + +A generator may add context data using `context()` method. + +```ts +export default class App extends PgGenerator { + context() { + return { + addSchemaName: true, + }; + } +} +``` + +### Special Keys + +There are some special keys in context. + +Data under the `global` key is sent to all templates all the time. + +Using the database object name in plural with the name of the target object, it is possible to send data to the template when that template is processed with the particular database object. + +For example, using the context below it is possible to send `skip: true` value only to table templates when they are processed with `public.product` table and `message: "Hello!"` to only schema templates when they are processed with `public` schema. + +```json +{ + "tables": { + "public.product": { + "skip": true + } + }, + "schemas": { + "public": { + "message": "Hello!" + } + } +} +``` + +## Example + +Below example is a nunjucks template that creates a markdown file for each table. + +**templates/[table] {name}.js.njk** + +```md +# {{ table | dboClassName(addSchemaName) | quote }} + +| Column | Type | +| ------ | ---- | + +{%- for column in table.columns %} +|{{ column.name }}|{{ column.type.name }}{{ column | dboColumnTypeModifier }}| +{%- endfor %} +``` + +The template first creates the title with the table's name. It uses the builtin [dboClassName](/nav.02.api/modules/filterfunctions.html#dboclassname) filter. `dboClassName` returns a class name using filtered database object. It takes a boolean parameter to decide whether to add PostgreSQL schema name to the class name. `addSchemaName` variable is taken from context. It's a good choice to provide a default value in the generator. The end-user may override it using a custom context file or context module. + +Then, the template creates a markdown table by looping through all columns of the table from context added by pg-generator automatically. [dboColumnTypeModifier](http://localhost:8080/nav.02.api/modules/filterfunctions.html#dbocolumntypemodifier) is also another built-in filter, which returns PostgreSQL data type modifiers of precision and scale such as `(1,2)`. + +The returned content is written to disk. + +## Tip + +See [pg-generator-example](https://www.npmjs.com/package/pg-generator-example) plugin for an example, how to develop your generators. It provides examples of: + +- Sub-generators for popular ORMs, markdown with mermaid support, and a report. +- Custom filters +- Custom context +- Shared partial usage diff --git a/docs/nav.03.creating-generators/03.generator-in-depth.md b/docs/nav.03.creating-generators/03.generator-in-depth.md new file mode 100644 index 0000000..8acbde1 --- /dev/null +++ b/docs/nav.03.creating-generators/03.generator-in-depth.md @@ -0,0 +1,20 @@ +# Generator in Depth + +## Events + +```mermaid +graph LR + clear --> init --> context --> render --> format --> process +``` + +### Clear + +### Init + +### Context + +### Render + +### Format + +### Process diff --git a/docs/nav.03.creating-generators/04.composability.md b/docs/nav.03.creating-generators/04.composability.md new file mode 100644 index 0000000..c4fa987 --- /dev/null +++ b/docs/nav.03.creating-generators/04.composability.md @@ -0,0 +1,48 @@ +# Composability + +# Getting Started + +## Planning Your Generators + +### Setup as Node Module + +A generator is a Node.js module. First, create your project folder. This folder should be started with `pg-generator`. For example, `pg-generator-name`. Name is the name of your generator. Create a `package.json` file and copy the following entries: + +```json +{ + "name": "pg-generator-name", + "version": "1.0.0", + "description": "pg-generator for my favorite ORM models.", + "files": ["dist"], + "keywords": ["pg-generator"] +} +``` + +Add the latest version of the pg-generator using `npm install pg-generator`. + +### File Tree + +The default generator is called `app` and when you execute `pgen name` command or `generate("name")` function without any sub-generator, the `app` sub-generator is executed. This should be in the `app` sub-directory. + +Other sub-generators have the same names as their folder names. For example; the `report` sub-generator is stored in the `report` sub-folder and executed with `pgen name:report` command or `generate("name", "report")` function. + +### Add Templates + +Create `templates` folder in the sub-generator folder and put your template files here. See [adding templates section](/nav.03.creating-generators/02.adding-templates). + +### Extend Base Generator + +In the generator's index.js file, you would extend the base generator. Just provide a `render()` method. The template file's path and context object is passed to the render method, and you should return rendered content. Returned content will be written to disk. You can use any templating engine. Below we use nunjucks. + +```ts +import { PgGenerator } from "pg-generator`; +import nunjucks from "../utils/nunjucks"; + +export default class App extends PgGenerator { + async render(templatePath: string, context: Context): Promise { + return nunjucks.render(templatePath, context); + } +} +``` + +See [generator in depth section](/nav.03.creating-generators/02.generator-in-depth). diff --git a/docs/nav.03.creating-generators/README.md b/docs/nav.03.creating-generators/README.md new file mode 100644 index 0000000..e0772ec --- /dev/null +++ b/docs/nav.03.creating-generators/README.md @@ -0,0 +1,83 @@ +# Introduction + +## What is a Generator + +Generators are pg-generator plugins developed as Node.js modules. pg-generator creates files for the database structure using generators. A generator contains one or more sub-generators. If generator name starts with "pg-generator", it can be used without prefix. `pgen example` command executes "pg-generator-example" plugin. + +## What is a Sub-Generator + +Sub generators are JavaScript files exporting a default class that extend [PgGenerator Class](http://localhost:8080/nav.02.api/classes/pggenerator.html) and have templates folder. You should put your sub-generators in their sub-folder in `lib`, `dist`, or `generators` folder. + +The required default sub-generator name is `app`. When you execute `pgen name` command or `generate("name")` function without providing a sub-generator name, the `app` sub-generator is executed, which is located in the `app` sub-directory. You may add additional sub-generators and name them as you wish. The folder name is the name of the sub-generator. + +Below is an example of a generator that has 3 sub-generators: `app`, `md`, and `orm`. + +``` +├─ package.json +└─ dist/ + ├─ app/ + ├─ md/ + ├─ orm/ +``` + +| CLI | API | Sub-Generator | +| --------------- | ------------------------- | ------------- | +| `pgen name` | `generate("name")` | `dist/app/` | +| `pgen name:app` | `generate("name", "app")` | `dist/app/` | +| `pgen name:md` | `generate("name", "md")` | `dist/md/` | +| `pgen name:orm` | `generate("name", "orm")` | `dist/orm/` | + +## Templates + +Template files are located in the `templates` folder of a sub-generator. Any templating engine can be used. Generated files are created by processing the templates. pg-generator decides how to process a template and what to pass as context data using the template's file name. Please see [adding templates section](/nav.03.creating-generators/02.adding-templates) for details. + +Templates related to the database objects are processed for each database object they are related to. Other files in the templates folder are copied to the destination without any processing. + +For example: + +``` +├─ package.json +└─ dist/ + └─ app/ + └─ templates/ + ├─ [table] {name}.js.njk + └─ README.md +``` + +The `[table] {name}.js.njk` template is processed for each table. As a result, a JavaScript file is created for each database table. On the other hand, `README.md` is not processed and just copied to the destination. + +## Processed Files + +| P | Path | Notes | +| --- | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | +| | `dist/partials/` | This folder may be used to store partial template files shared between several sub-generators. | +| | `dist/utils/` | This folder may be used to store utility code. | +| ✔ | `dist/*/` | Any other folders are used as a sub-generator (e.g. `dist/app`, `dist/report`). | +| ✔ | `dist/*/templates/` | Template files corresponding to database objects are processed for each object. Non-template files are copied to the destination. | +| | `dist/*/templates/partials/` | This folder may be used to store partial template files for a specific sub-generator. | + +**✔**: pg-generator only processes files or folders marked with ✔. Other files and folders are ignored by the pg-generator and may be used for utility purposes or storing for template partials. + +Below is an example of all files summarized above. + +``` +├─ package.json +└─ dist/ + ├─ partials/ + ├─ utils/ + ├─ app/ + │ ├─ index.js + │ └─ templates/ + │ ├─ partials/ + │ ├─ README.md + │ ├─ [db] index.js.njk + │ └─ models/ + │ ├─ [table] {schema.name # dash-case}{name # dash-case}.js.njk + │ └─ [view] {name # dash-case}.js.njk + └─ report/ + ├─ index.js + └─ templates/ + └─ [db] report.md.njk +``` + +Above structure provide `pgen name` and `pgen name:report` in CLI, as well as `generate("name")` and `generate("name", "report")` functions in API. diff --git a/docs/nav.03.creating-generators/filters.md b/docs/nav.03.creating-generators/filters.md new file mode 100644 index 0000000..9bd0008 --- /dev/null +++ b/docs/nav.03.creating-generators/filters.md @@ -0,0 +1,79 @@ +# Filters + +If your favorite template engine supports, pg-generator provides some built-in filters to be added to the template engine. Filters are JS functions. + +## Adding Filters + +Below is examples showing how to add filters to the [nunjucks](https://mozilla.github.io/nunjucks/) templating engine. Nunjucks already has some [built-in filters](https://mozilla.github.io/nunjucks/templating.html#builtin-filters). We will add our filters. + +## Adding pg-generator Built-In Filters + +Please see [built-in filters](/nav.02.api/modules/filterfunctions) for all available filters. + +```ts +import { join } from "path"; +import { filterFunctions } from "pg-generator"; +import nunjucks, { Environment } from "nunjucks"; + +const environment = new nunjucks.FileSystemLoader(join(__dirname, "templates")); +Object.entries(filters).forEach(([name, filter]) => environment.addFilter(name, filter)); +``` + +## Adding Custom Filters + +It is a best practice to move complex operations into your custom filters, and leave as few business logic as possible to templates. This also makes your complex operations easy to test, debug and share. + +```ts +import { join } from "path"; +import nunjucks, { Environment } from "nunjucks"; + +const customFilters = { + hello: (input) => `Hello! ${input}`, +}; + +const environment = new nunjucks.FileSystemLoader(join(__dirname, "templates")); +Object.entries(customFilters).forEach(([name, filter]) => environment.addFilter(name, filter)); +``` + +## Ready to Use Function + +Below is an example function which combines the examples above and ready to be used in your generators. + +```ts +import { join } from "path"; +import { filterFunctions } from "pg-generator"; +import nunjucks, { Environment } from "nunjucks"; + +/** Custom filters example */ +const customFilters = { + /** Adds hello at the beginning of its input. */ + hello: (input) => `Hello! ${input}`, + /** Filters can be used for object stoo. Below filter returns non-serial required columns. */ + requiredColumns: (table) => table.columns.filter((column) => !column.isSerial && column.notNull), +}; + + +/** + * This function is not related to `pg-generator`. It creates `nunjucks` template engine environment + * for the given generator and adds filters provided by `pg-generator`. + * `pg-generator` is template agnostic, you can use any template engine. + * + * @param generatorPath is the path of the generator. + * + * @see https://mozilla.github.io/nunjucks + */ +export function getNunjucks(generatorPath: string): Environment { + // Create `nunjucks` environment. + const environment = new nunjucks.Environment( + // Add given sub-generator path and shared "partials" path to the list of template paths. + new nunjucks.FileSystemLoader([join(generatorPath, "templates"), join(__dirname, "../partials")]), + { autoescape: false } + ); + + // Add pg-generator built-in filters and custom filters to nunjucks. + // Filters are not nunjucks specific, many template engines have a similar mechanism. + const filters = { ...filterFunctions, ...customFilters }; + Object.entries(filters).forEach(([name, filter]) => environment.addFilter(name, filter)); + + return environment; +``` diff --git a/module-files/configs/.eslintrc.js b/module-files/configs/.eslintrc.js index ff9490a..98d72dd 100644 --- a/module-files/configs/.eslintrc.js +++ b/module-files/configs/.eslintrc.js @@ -22,7 +22,6 @@ module.exports = { "eslint:recommended", // TURN ON ESLint recommended rules. "plugin:@typescript-eslint/eslint-recommended", "plugin:@typescript-eslint/recommended", // TURN ON TypeScript rules by using `typescript-eslint/typescript-eslint`. - "prettier/@typescript-eslint", // TURN OFF ESLint TypesSript rules which conflict with Prettier by using `prettier/eslint-config-prettier`. ], plugins: ["@typescript-eslint"], settings: { @@ -63,7 +62,6 @@ module.exports = { "plugin:jest/recommended", // TURN ON Jest rules by using "jest-community/eslint-plugin-jest". "airbnb-base", // TURN ON airbnb-base rules. "plugin:prettier/recommended", // RUN Prettier as ESLint rule by using `prettier/eslint-plugin-prettier` and TURN OFF ESLint rules which conflict with Prettier by using `prettier/eslint-config-prettier`. - "prettier/@typescript-eslint", // TURN OFF ESLint TypesSript rules which conflict with Prettier by using `prettier/eslint-config-prettier`. ], }, ], diff --git a/module-files/configs/vuepress-config.js b/module-files/configs/vuepress-config.js index 595a790..6785d87 100644 --- a/module-files/configs/vuepress-config.js +++ b/module-files/configs/vuepress-config.js @@ -5,7 +5,7 @@ const packageData = require("../../package.json"); const GOOGLE_ANALYTICS_ID = packageData.vuepress && packageData.vuepress["google-analytics-id"]; const { nav, sidebar } = getVuePressBars(join(__dirname, "../../docs"), { addReadMeToFirstGroup: false }); -const plugins = ["@vuepress/active-header-links", "@vuepress/pwa"]; +const plugins = ["@vuepress/active-header-links", "@vuepress/pwa", "vuepress-plugin-mermaidjs"]; if (GOOGLE_ANALYTICS_ID) plugins.push(["@vuepress/google-analytics", { ga: GOOGLE_ANALYTICS_ID }]); diff --git a/package-lock.json b/package-lock.json index 8b52216..08e423c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { "name": "pg-generator", - "version": "1.0.0", + "version": "0.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "version": "1.0.0", + "version": "0.0.0", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -18,15 +18,17 @@ "lodash.get": "^4.4.2", "lodash.merge": "^4.6.2", "meow": "^9.0.0", - "meow-helper": "^1.6.0", - "pg-structure": "^7.7.0" + "meow-helper": "^1.6.2", + "pg-structure": "^7.12.1", + "prettier": "^2.2.1", + "wordwrap": "^1.0.0" }, "bin": { "pgen": "dist/bin/pgen.js" }, "devDependencies": { - "@commitlint/cli": "^11.0.0", - "@commitlint/config-conventional": "^11.0.0", + "@commitlint/cli": "^12.0.1", + "@commitlint/config-conventional": "^12.0.1", "@ozum/pinst": "^2.1.4", "@types/inflection": "^1.5.28", "@types/jest": "^26.0.20", @@ -34,6 +36,7 @@ "@types/lodash.merge": "^4.6.6", "@types/node": "^14.14.31", "@types/pg": "^7.14.10", + "@types/wordwrap": "^1.0.0", "@typescript-eslint/eslint-plugin": "^4.15.1", "@typescript-eslint/parser": "^4.15.1", "@vuepress/plugin-active-header-links": "^1.8.2", @@ -43,7 +46,7 @@ "concat-md": "^0.3.5", "eslint": "^7.20.0", "eslint-config-airbnb-base": "^14.1.0", - "eslint-config-prettier": "^7.2.0", + "eslint-config-prettier": "^8.1.0", "eslint-plugin-import": "^2.22.0", "eslint-plugin-jest": "^24.1.5", "eslint-plugin-prettier": "^3.3.1", @@ -57,18 +60,19 @@ "readmeasy": "^0.2.7", "ts-jest": "^26.5.1", "ts-node-dev": "^1.1.1", - "typedoc": "^0.20.27", + "typedoc": "^0.20.28", "typedoc-neo-theme": "^1.1.0", "typedoc-plugin-example-tag": "^1.0.2", - "typedoc-plugin-markdown": "^3.5.0", + "typedoc-plugin-markdown": "^3.6.0", "typedoc-plugin-param-names": "^2.0.0", "typescript": "^4.1.5", "vuepress": "^1.8.2", "vuepress-bar": "^0.3.5", + "vuepress-plugin-mermaidjs": "^1.8.1", "walkdir": "^0.4.1" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 14.0.0" } }, "node_modules/@babel/code-frame": { @@ -1284,6 +1288,12 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "node_modules/@braintree/sanitize-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-3.1.0.tgz", + "integrity": "sha512-GcIY79elgB+azP74j8vqkiXz8xLFfIzbQJdlwOPisgbKT00tviJQuEghOXSMVxJ00HoYJbGswr4kcllUc4xCcg==", + "dev": true + }, "node_modules/@cnakazawa/watch": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz", @@ -1301,54 +1311,176 @@ } }, "node_modules/@commitlint/cli": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-11.0.0.tgz", - "integrity": "sha512-YWZWg1DuqqO5Zjh7vUOeSX76vm0FFyz4y0cpGMFhrhvUi5unc4IVfCXZ6337R9zxuBtmveiRuuhQqnRRer+13g==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-12.0.1.tgz", + "integrity": "sha512-V+cMYNHJOr40XT9Kvz3Vrz1Eh7QE1rjQrUbifawDAqcOrBJFuoXwU2SAcRtYFCSqFy9EhbreQGhZFs8dYb90KA==", "dev": true, "dependencies": { - "@babel/runtime": "^7.11.2", - "@commitlint/format": "^11.0.0", - "@commitlint/lint": "^11.0.0", - "@commitlint/load": "^11.0.0", - "@commitlint/read": "^11.0.0", - "chalk": "4.1.0", - "core-js": "^3.6.1", + "@commitlint/format": "^12.0.1", + "@commitlint/lint": "^12.0.1", + "@commitlint/load": "^12.0.1", + "@commitlint/read": "^12.0.1", + "@commitlint/types": "^12.0.1", "get-stdin": "8.0.0", "lodash": "^4.17.19", "resolve-from": "5.0.0", "resolve-global": "1.0.0", - "yargs": "^15.1.0" + "yargs": "^16.2.0" }, "bin": { "commitlint": "cli.js" }, "engines": { - "node": ">=v10.22.0" + "node": ">=v10" + } + }, + "node_modules/@commitlint/cli/node_modules/@commitlint/execute-rule": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-12.0.1.tgz", + "integrity": "sha512-JzyweYfZlFLtXpgP+btzSY3YAkGPg61TqUSYQqBr4+5IaVf1FruMm5v4D5eLu9dAJuNKUfHbM3AEfuEPiZ79pg==", + "dev": true, + "engines": { + "node": ">=v10" + } + }, + "node_modules/@commitlint/cli/node_modules/@commitlint/load": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-12.0.1.tgz", + "integrity": "sha512-dX8KdCWn7w0bTkkk3zKQpe9X8vsTRa5EM+1ffF313wCX9b6tGa9vujhEHCkSzKAbbE2tFV64CHZygE7rtlHdIA==", + "dev": true, + "dependencies": { + "@commitlint/execute-rule": "^12.0.1", + "@commitlint/resolve-extends": "^12.0.1", + "@commitlint/types": "^12.0.1", + "chalk": "^4.0.0", + "cosmiconfig": "^7.0.0", + "lodash": "^4.17.19", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=v10" + } + }, + "node_modules/@commitlint/cli/node_modules/@commitlint/resolve-extends": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-12.0.1.tgz", + "integrity": "sha512-Mvg0GDi/68Cqw893ha8uhxE8myHfPmiSSSi7d1x4VJNR4hoS37lBdX89kyx4i9NPmLfviY2cUJKTyK8ZrFznZw==", + "dev": true, + "dependencies": { + "import-fresh": "^3.0.0", + "lodash": "^4.17.19", + "resolve-from": "^5.0.0", + "resolve-global": "^1.0.0" + }, + "engines": { + "node": ">=v10" + } + }, + "node_modules/@commitlint/cli/node_modules/@commitlint/types": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-12.0.1.tgz", + "integrity": "sha512-FsNDMV0W7D19/ZbR412klpqAilXASx75Neqh7jPtK278IEwdukOg3vth1r5kTm+BjDScM7wMUEOwIW3NNfAtwg==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0" + }, + "engines": { + "node": ">=v10" + } + }, + "node_modules/@commitlint/cli/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/@commitlint/cli/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/@commitlint/cli/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@commitlint/cli/node_modules/y18n": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", + "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@commitlint/cli/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" } }, "node_modules/@commitlint/config-conventional": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-11.0.0.tgz", - "integrity": "sha512-SNDRsb5gLuDd2PL83yCOQX6pE7gevC79UPFx+GLbLfw6jGnnbO9/tlL76MLD8MOViqGbo7ZicjChO9Gn+7tHhA==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-12.0.1.tgz", + "integrity": "sha512-1ZhB135lh47zVmf1orwcjxuKuam11fJIH/bdVxW9XiQv8XPwC6iIp19knfl8FcOT78AVBnes1z6EVxgUeP2/4Q==", "dev": true, "dependencies": { "conventional-changelog-conventionalcommits": "^4.3.1" }, "engines": { - "node": ">=v10.22.0" + "node": ">=v10" } }, "node_modules/@commitlint/ensure": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-11.0.0.tgz", - "integrity": "sha512-/T4tjseSwlirKZdnx4AuICMNNlFvRyPQimbZIOYujp9DSO6XRtOy9NrmvWujwHsq9F5Wb80QWi4WMW6HMaENug==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-12.0.1.tgz", + "integrity": "sha512-XdBq+q1YBBDxWIAEjE3Y1YMbzhUnUuSLAEWD8SU1xsvEpQXWRYwDlMBRkjO7funNWTdL0ZQSkZDzme70imYjbw==", "dev": true, "dependencies": { - "@commitlint/types": "^11.0.0", + "@commitlint/types": "^12.0.1", "lodash": "^4.17.19" }, "engines": { - "node": ">=v10.22.0" + "node": ">=v10" + } + }, + "node_modules/@commitlint/ensure/node_modules/@commitlint/types": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-12.0.1.tgz", + "integrity": "sha512-FsNDMV0W7D19/ZbR412klpqAilXASx75Neqh7jPtK278IEwdukOg3vth1r5kTm+BjDScM7wMUEOwIW3NNfAtwg==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0" + }, + "engines": { + "node": ">=v10" } }, "node_modules/@commitlint/execute-rule": { @@ -1356,61 +1488,86 @@ "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-11.0.0.tgz", "integrity": "sha512-g01p1g4BmYlZ2+tdotCavrMunnPFPhTzG1ZiLKTCYrooHRbmvqo42ZZn4QMStUEIcn+jfLb6BRZX3JzIwA1ezQ==", "dev": true, + "optional": true, "engines": { "node": ">=v10.22.0" } }, "node_modules/@commitlint/format": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-11.0.0.tgz", - "integrity": "sha512-bpBLWmG0wfZH/svzqD1hsGTpm79TKJWcf6EXZllh2J/LSSYKxGlv967lpw0hNojme0sZd4a/97R3qA2QHWWSLg==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-12.0.1.tgz", + "integrity": "sha512-rF79ipAxR8yFzPzG5tRoEZ//MRkyxCXj4JhpEjtdaCMBAXMssI8uazn3e5D8z4UFgSDe9qOnL0OmQvql7HTMoA==", "dev": true, "dependencies": { - "@commitlint/types": "^11.0.0", + "@commitlint/types": "^12.0.1", "chalk": "^4.0.0" }, "engines": { - "node": ">=v10.22.0" + "node": ">=v10" + } + }, + "node_modules/@commitlint/format/node_modules/@commitlint/types": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-12.0.1.tgz", + "integrity": "sha512-FsNDMV0W7D19/ZbR412klpqAilXASx75Neqh7jPtK278IEwdukOg3vth1r5kTm+BjDScM7wMUEOwIW3NNfAtwg==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0" + }, + "engines": { + "node": ">=v10" } }, "node_modules/@commitlint/is-ignored": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-11.0.0.tgz", - "integrity": "sha512-VLHOUBN+sOlkYC4tGuzE41yNPO2w09sQnOpfS+pSPnBFkNUUHawEuA44PLHtDvQgVuYrMAmSWFQpWabMoP5/Xg==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-12.0.1.tgz", + "integrity": "sha512-AplfLn5mX/kWTIiSolcOhTYcgphuGLX8FUr+HmyHBEqUkO36jt0z9caysH47fqU71ePtH63v1DWm+RYQ5RPDjg==", "dev": true, "dependencies": { - "@commitlint/types": "^11.0.0", - "semver": "7.3.2" + "@commitlint/types": "^12.0.1", + "semver": "7.3.4" }, "engines": { - "node": ">=v10.22.0" + "node": ">=v10" } }, - "node_modules/@commitlint/is-ignored/node_modules/semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "node_modules/@commitlint/is-ignored/node_modules/@commitlint/types": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-12.0.1.tgz", + "integrity": "sha512-FsNDMV0W7D19/ZbR412klpqAilXASx75Neqh7jPtK278IEwdukOg3vth1r5kTm+BjDScM7wMUEOwIW3NNfAtwg==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "chalk": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=v10" } }, "node_modules/@commitlint/lint": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-11.0.0.tgz", - "integrity": "sha512-Q8IIqGIHfwKr8ecVZyYh6NtXFmKw4YSEWEr2GJTB/fTZXgaOGtGFZDWOesCZllQ63f1s/oWJYtVv5RAEuwN8BQ==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-12.0.1.tgz", + "integrity": "sha512-1lKyRCq4ahJrY+Xxo8LsqCbALeJkodtEfpmYHeA5HpPMnK7lRSplLqOLcTCjoPfd4vO+gl6aDEZN+ow3YGQBOg==", "dev": true, "dependencies": { - "@commitlint/is-ignored": "^11.0.0", - "@commitlint/parse": "^11.0.0", - "@commitlint/rules": "^11.0.0", - "@commitlint/types": "^11.0.0" + "@commitlint/is-ignored": "^12.0.1", + "@commitlint/parse": "^12.0.1", + "@commitlint/rules": "^12.0.1", + "@commitlint/types": "^12.0.1" }, "engines": { - "node": ">=v10.22.0" + "node": ">=v10" + } + }, + "node_modules/@commitlint/lint/node_modules/@commitlint/types": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-12.0.1.tgz", + "integrity": "sha512-FsNDMV0W7D19/ZbR412klpqAilXASx75Neqh7jPtK278IEwdukOg3vth1r5kTm+BjDScM7wMUEOwIW3NNfAtwg==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0" + }, + "engines": { + "node": ">=v10" } }, "node_modules/@commitlint/load": { @@ -1418,6 +1575,7 @@ "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-11.0.0.tgz", "integrity": "sha512-t5ZBrtgvgCwPfxmG811FCp39/o3SJ7L+SNsxFL92OR4WQxPcu6c8taD0CG2lzOHGuRyuMxZ7ps3EbngT2WpiCg==", "dev": true, + "optional": true, "dependencies": { "@commitlint/execute-rule": "^11.0.0", "@commitlint/resolve-extends": "^11.0.0", @@ -1432,39 +1590,65 @@ } }, "node_modules/@commitlint/message": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-11.0.0.tgz", - "integrity": "sha512-01ObK/18JL7PEIE3dBRtoMmU6S3ecPYDTQWWhcO+ErA3Ai0KDYqV5VWWEijdcVafNpdeUNrEMigRkxXHQLbyJA==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-12.0.1.tgz", + "integrity": "sha512-fXuoxRC+NT1wEQi6p8oHfT7wvWIRgTk+udlRJnWTjmMpiYzVnMmmZfasdShirWr4TtxQtMyL+5DVgh7Y98kURw==", "dev": true, "engines": { - "node": ">=v10.22.0" + "node": ">=v10" } }, "node_modules/@commitlint/parse": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-11.0.0.tgz", - "integrity": "sha512-DekKQAIYWAXIcyAZ6/PDBJylWJ1BROTfDIzr9PMVxZRxBPc1gW2TG8fLgjZfBP5mc0cuthPkVi91KQQKGri/7A==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-12.0.1.tgz", + "integrity": "sha512-7oEGASmzBnHir5jSIR7KephXrKh7rIi9a6RpH1tOT+CIENYvhe8EDtIy29qMt+RLa2LlaPF7YrAgaJRfzG0YDQ==", "dev": true, "dependencies": { - "conventional-changelog-angular": "^5.0.0", + "@commitlint/types": "^12.0.1", + "conventional-changelog-angular": "^5.0.11", "conventional-commits-parser": "^3.0.0" }, "engines": { - "node": ">=v10.22.0" + "node": ">=v10" + } + }, + "node_modules/@commitlint/parse/node_modules/@commitlint/types": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-12.0.1.tgz", + "integrity": "sha512-FsNDMV0W7D19/ZbR412klpqAilXASx75Neqh7jPtK278IEwdukOg3vth1r5kTm+BjDScM7wMUEOwIW3NNfAtwg==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0" + }, + "engines": { + "node": ">=v10" } }, "node_modules/@commitlint/read": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-11.0.0.tgz", - "integrity": "sha512-37V0V91GSv0aDzMzJioKpCoZw6l0shk7+tRG8RkW1GfZzUIytdg3XqJmM+IaIYpaop0m6BbZtfq+idzUwJnw7g==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-12.0.1.tgz", + "integrity": "sha512-baa0YeD4QOctEuthLpExQSi9xPiw0kDPfUVHqp8I88iuIXJECeS8S1+1GBiz89e8dLN9zmEE+sN9vtJHdAp9YA==", "dev": true, "dependencies": { - "@commitlint/top-level": "^11.0.0", + "@commitlint/top-level": "^12.0.1", + "@commitlint/types": "^12.0.1", "fs-extra": "^9.0.0", "git-raw-commits": "^2.0.0" }, "engines": { - "node": ">=v10.22.0" + "node": ">=v10" + } + }, + "node_modules/@commitlint/read/node_modules/@commitlint/types": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-12.0.1.tgz", + "integrity": "sha512-FsNDMV0W7D19/ZbR412klpqAilXASx75Neqh7jPtK278IEwdukOg3vth1r5kTm+BjDScM7wMUEOwIW3NNfAtwg==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0" + }, + "engines": { + "node": ">=v10" } }, "node_modules/@commitlint/resolve-extends": { @@ -1472,6 +1656,7 @@ "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-11.0.0.tgz", "integrity": "sha512-WinU6Uv6L7HDGLqn/To13KM1CWvZ09VHZqryqxXa1OY+EvJkfU734CwnOEeNlSCK7FVLrB4kmodLJtL1dkEpXw==", "dev": true, + "optional": true, "dependencies": { "import-fresh": "^3.0.0", "lodash": "^4.17.19", @@ -1483,39 +1668,51 @@ } }, "node_modules/@commitlint/rules": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-11.0.0.tgz", - "integrity": "sha512-2hD9y9Ep5ZfoNxDDPkQadd2jJeocrwC4vJ98I0g8pNYn/W8hS9+/FuNpolREHN8PhmexXbkjrwyQrWbuC0DVaA==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-12.0.1.tgz", + "integrity": "sha512-A5O0ubNGugZR9WWxk5IVOLo07lpdUwhG5WkAW2lYpgZ7Z/2U4PLob9b4Ih1eHbQu+gnVeFr91k7F0DrpM7B8EQ==", "dev": true, "dependencies": { - "@commitlint/ensure": "^11.0.0", - "@commitlint/message": "^11.0.0", - "@commitlint/to-lines": "^11.0.0", - "@commitlint/types": "^11.0.0" + "@commitlint/ensure": "^12.0.1", + "@commitlint/message": "^12.0.1", + "@commitlint/to-lines": "^12.0.1", + "@commitlint/types": "^12.0.1" }, "engines": { - "node": ">=v10.22.0" + "node": ">=v10" + } + }, + "node_modules/@commitlint/rules/node_modules/@commitlint/types": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-12.0.1.tgz", + "integrity": "sha512-FsNDMV0W7D19/ZbR412klpqAilXASx75Neqh7jPtK278IEwdukOg3vth1r5kTm+BjDScM7wMUEOwIW3NNfAtwg==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0" + }, + "engines": { + "node": ">=v10" } }, "node_modules/@commitlint/to-lines": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-11.0.0.tgz", - "integrity": "sha512-TIDTB0Y23jlCNubDROUVokbJk6860idYB5cZkLWcRS9tlb6YSoeLn1NLafPlrhhkkkZzTYnlKYzCVrBNVes1iw==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-12.0.1.tgz", + "integrity": "sha512-XwcJ1jY7x2fhudzbGMpNQkTSMVrxWrI8bRMbVe3Abuu7RfYpFf7VXAlhtnLfxBoagaK7RxjC2+eRidp/3txQBg==", "dev": true, "engines": { - "node": ">=v10.22.0" + "node": ">=v10" } }, "node_modules/@commitlint/top-level": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-11.0.0.tgz", - "integrity": "sha512-O0nFU8o+Ws+py5pfMQIuyxOtfR/kwtr5ybqTvR+C2lUPer2x6lnQU+OnfD7hPM+A+COIUZWx10mYQvkR3MmtAA==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-12.0.1.tgz", + "integrity": "sha512-rHdgt7U24GEau2/9i2vEAbksxkBRiVjHj5ECFL5dd0AJOIvaK++vMg4EF/ME0X/1yd9qVTHTNOl2Q4tTFK7VBQ==", "dev": true, "dependencies": { "find-up": "^5.0.0" }, "engines": { - "node": ">=v10.22.0" + "node": ">=v10" } }, "node_modules/@commitlint/types": { @@ -1523,6 +1720,7 @@ "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-11.0.0.tgz", "integrity": "sha512-VoNqai1vR5anRF5Tuh/+SWDFk7xi7oMwHrHrbm1BprYXjB2RJsWLhUrStMssDxEl5lW/z3EUdg8RvH/IUBccSQ==", "dev": true, + "optional": true, "engines": { "node": ">=v10.22.0" } @@ -2395,6 +2593,12 @@ "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", "dev": true }, + "node_modules/@types/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-XknqsI3sxtVduA/zP475wjMPH/qaZB6teY+AGvZkNUPhwxAac/QuKt6fpJCY9iO6ZpDhBmu9iOHgLXK78hoEDA==", + "dev": true + }, "node_modules/@types/yargs": { "version": "15.0.13", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.13.tgz", @@ -5972,9 +6176,9 @@ "dev": true }, "node_modules/colorette": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", - "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", "dev": true }, "node_modules/colors": { @@ -7123,6 +7327,18 @@ "urix": "^0.1.0" } }, + "node_modules/css-b64-images": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/css-b64-images/-/css-b64-images-0.2.5.tgz", + "integrity": "sha1-QgBdgyBLK0pdk7axpWRBM7WSegI=", + "dev": true, + "bin": { + "css-b64-images": "bin/css-b64-images" + }, + "engines": { + "node": "*" + } + }, "node_modules/css-color-names": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", @@ -7482,6 +7698,9 @@ }, "engines": { "node": ">= 10" + }, + "optionalDependencies": { + "@commitlint/load": ">6.1.1" } }, "node_modules/cz-conventional-changelog/node_modules/ansi-styles": { @@ -7546,6 +7765,341 @@ "node": ">=4" } }, + "node_modules/d3": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-5.16.0.tgz", + "integrity": "sha512-4PL5hHaHwX4m7Zr1UapXW23apo6pexCgdetdJ5kTmADpG/7T9Gkxw0M0tf/pjoB63ezCCm0u5UaFYy2aMt0Mcw==", + "dev": true, + "dependencies": { + "d3-array": "1", + "d3-axis": "1", + "d3-brush": "1", + "d3-chord": "1", + "d3-collection": "1", + "d3-color": "1", + "d3-contour": "1", + "d3-dispatch": "1", + "d3-drag": "1", + "d3-dsv": "1", + "d3-ease": "1", + "d3-fetch": "1", + "d3-force": "1", + "d3-format": "1", + "d3-geo": "1", + "d3-hierarchy": "1", + "d3-interpolate": "1", + "d3-path": "1", + "d3-polygon": "1", + "d3-quadtree": "1", + "d3-random": "1", + "d3-scale": "2", + "d3-scale-chromatic": "1", + "d3-selection": "1", + "d3-shape": "1", + "d3-time": "1", + "d3-time-format": "2", + "d3-timer": "1", + "d3-transition": "1", + "d3-voronoi": "1", + "d3-zoom": "1" + } + }, + "node_modules/d3-array": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", + "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==", + "dev": true + }, + "node_modules/d3-axis": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.12.tgz", + "integrity": "sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ==", + "dev": true + }, + "node_modules/d3-brush": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.6.tgz", + "integrity": "sha512-7RW+w7HfMCPyZLifTz/UnJmI5kdkXtpCbombUSs8xniAyo0vIbrDzDwUJB6eJOgl9u5DQOt2TQlYumxzD1SvYA==", + "dev": true, + "dependencies": { + "d3-dispatch": "1", + "d3-drag": "1", + "d3-interpolate": "1", + "d3-selection": "1", + "d3-transition": "1" + } + }, + "node_modules/d3-chord": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.6.tgz", + "integrity": "sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA==", + "dev": true, + "dependencies": { + "d3-array": "1", + "d3-path": "1" + } + }, + "node_modules/d3-collection": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz", + "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==", + "dev": true + }, + "node_modules/d3-color": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz", + "integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==", + "dev": true + }, + "node_modules/d3-contour": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-1.3.2.tgz", + "integrity": "sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==", + "dev": true, + "dependencies": { + "d3-array": "^1.1.1" + } + }, + "node_modules/d3-dispatch": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz", + "integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA==", + "dev": true + }, + "node_modules/d3-drag": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.5.tgz", + "integrity": "sha512-rD1ohlkKQwMZYkQlYVCrSFxsWPzI97+W+PaEIBNTMxRuxz9RF0Hi5nJWHGVJ3Om9d2fRTe1yOBINJyy/ahV95w==", + "dev": true, + "dependencies": { + "d3-dispatch": "1", + "d3-selection": "1" + } + }, + "node_modules/d3-dsv": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz", + "integrity": "sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==", + "dev": true, + "dependencies": { + "commander": "2", + "iconv-lite": "0.4", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json", + "csv2tsv": "bin/dsv2dsv", + "dsv2dsv": "bin/dsv2dsv", + "dsv2json": "bin/dsv2json", + "json2csv": "bin/json2dsv", + "json2dsv": "bin/json2dsv", + "json2tsv": "bin/json2dsv", + "tsv2csv": "bin/dsv2dsv", + "tsv2json": "bin/dsv2json" + } + }, + "node_modules/d3-dsv/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/d3-ease": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz", + "integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ==", + "dev": true + }, + "node_modules/d3-fetch": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.2.0.tgz", + "integrity": "sha512-yC78NBVcd2zFAyR/HnUiBS7Lf6inSCoWcSxFfw8FYL7ydiqe80SazNwoffcqOfs95XaLo7yebsmQqDKSsXUtvA==", + "dev": true, + "dependencies": { + "d3-dsv": "1" + } + }, + "node_modules/d3-force": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz", + "integrity": "sha512-HHvehyaiUlVo5CxBJ0yF/xny4xoaxFxDnBXNvNcfW9adORGZfyNF1dj6DGLKyk4Yh3brP/1h3rnDzdIAwL08zg==", + "dev": true, + "dependencies": { + "d3-collection": "1", + "d3-dispatch": "1", + "d3-quadtree": "1", + "d3-timer": "1" + } + }, + "node_modules/d3-format": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz", + "integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==", + "dev": true + }, + "node_modules/d3-geo": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.1.tgz", + "integrity": "sha512-XG4d1c/UJSEX9NfU02KwBL6BYPj8YKHxgBEw5om2ZnTRSbIcego6dhHwcxuSR3clxh0EpE38os1DVPOmnYtTPg==", + "dev": true, + "dependencies": { + "d3-array": "1" + } + }, + "node_modules/d3-hierarchy": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz", + "integrity": "sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ==", + "dev": true + }, + "node_modules/d3-interpolate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz", + "integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==", + "dev": true, + "dependencies": { + "d3-color": "1" + } + }, + "node_modules/d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "dev": true + }, + "node_modules/d3-polygon": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.6.tgz", + "integrity": "sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ==", + "dev": true + }, + "node_modules/d3-quadtree": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz", + "integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA==", + "dev": true + }, + "node_modules/d3-random": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.2.tgz", + "integrity": "sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ==", + "dev": true + }, + "node_modules/d3-scale": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz", + "integrity": "sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==", + "dev": true, + "dependencies": { + "d3-array": "^1.2.0", + "d3-collection": "1", + "d3-format": "1", + "d3-interpolate": "1", + "d3-time": "1", + "d3-time-format": "2" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz", + "integrity": "sha512-ACcL46DYImpRFMBcpk9HhtIyC7bTBR4fNOPxwVSl0LfulDAwyiHyPOTqcDG1+t5d4P9W7t/2NAuWu59aKko/cg==", + "dev": true, + "dependencies": { + "d3-color": "1", + "d3-interpolate": "1" + } + }, + "node_modules/d3-selection": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.2.tgz", + "integrity": "sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg==", + "dev": true + }, + "node_modules/d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "dev": true, + "dependencies": { + "d3-path": "1" + } + }, + "node_modules/d3-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz", + "integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==", + "dev": true + }, + "node_modules/d3-time-format": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz", + "integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==", + "dev": true, + "dependencies": { + "d3-time": "1" + } + }, + "node_modules/d3-timer": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz", + "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==", + "dev": true + }, + "node_modules/d3-transition": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.3.2.tgz", + "integrity": "sha512-sc0gRU4PFqZ47lPVHloMn9tlPcv8jxgOQg+0zjhfZXMQuvppjG6YuwdMBE0TuqCZjeJkLecku/l9R0JPcRhaDA==", + "dev": true, + "dependencies": { + "d3-color": "1", + "d3-dispatch": "1", + "d3-ease": "1", + "d3-interpolate": "1", + "d3-selection": "^1.1.0", + "d3-timer": "1" + } + }, + "node_modules/d3-voronoi": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz", + "integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==", + "dev": true + }, + "node_modules/d3-zoom": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.8.3.tgz", + "integrity": "sha512-VoLXTK4wvy1a0JpH2Il+F2CiOhVu7VRXWF5M/LroMIh3/zBAC3WAt7QoIvPibOavVo20hN6/37vwAsdBejLyKQ==", + "dev": true, + "dependencies": { + "d3-dispatch": "1", + "d3-drag": "1", + "d3-interpolate": "1", + "d3-selection": "1", + "d3-transition": "1" + } + }, + "node_modules/dagre": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz", + "integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==", + "dev": true, + "dependencies": { + "graphlib": "^2.1.8", + "lodash": "^4.17.15" + } + }, + "node_modules/dagre-d3": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/dagre-d3/-/dagre-d3-0.6.4.tgz", + "integrity": "sha512-e/6jXeCP7/ptlAM48clmX4xTZc5Ek6T6kagS7Oz2HrYSdqcLZFLqpAfh7ldbZRFfxCZVyh61NEPR08UQRVxJzQ==", + "dev": true, + "dependencies": { + "d3": "^5.14", + "dagre": "^0.8.5", + "graphlib": "^2.1.8", + "lodash": "^4.17.15" + } + }, "node_modules/dargs": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", @@ -7567,6 +8121,14 @@ "node": ">=0.10" } }, + "node_modules/dashify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dashify/-/dashify-2.0.0.tgz", + "integrity": "sha512-hpA5C/YrPjucXypHPPc0oJ1l9Hf6wWbiOL7Ik42cxnsUOhWiCB/fylKbKqqJalW9FgkNQCw16YO8uW9Hs0Iy1A==", + "engines": { + "node": ">=4" + } + }, "node_modules/data-urls": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", @@ -8680,6 +9242,15 @@ "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", "dev": true }, + "node_modules/entity-decode": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/entity-decode/-/entity-decode-2.0.2.tgz", + "integrity": "sha512-5CCY/3ci4MC1m2jlumNjWd7VBFt4VfFnmSqSNmVcXq4gxM3Vmarxtt+SvmBnzwLS669MWdVuXboNVj1qN2esVg==", + "dev": true, + "dependencies": { + "he": "^1.1.1" + } + }, "node_modules/envify": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/envify/-/envify-4.1.0.tgz", @@ -8939,9 +9510,9 @@ } }, "node_modules/eslint-config-prettier": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz", - "integrity": "sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.1.0.tgz", + "integrity": "sha512-oKMhGv3ihGbCIimCAjqkdzx2Q+jthoqnXSP+d86M9tptwugycmTFdVR4IpLgq2c4SHifbwO90z2fQ8/Aio73yw==", "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" @@ -10712,6 +11283,15 @@ "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", "dev": true }, + "node_modules/graphlib": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", + "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15" + } + }, "node_modules/gray-matter": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.2.tgz", @@ -10757,9 +11337,6 @@ }, "engines": { "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" } }, "node_modules/har-schema": { @@ -13483,6 +14060,12 @@ "json-buffer": "3.0.0" } }, + "node_modules/khroma": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-1.2.0.tgz", + "integrity": "sha512-DlKk5y243dujy8fOH02aRnnewLfiHJV0s8aXaVrCohgBf3s7fEAn6gc6LLQ21agODlFZS8ufrn+juu70uCA9Tw==", + "dev": true + }, "node_modules/killable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", @@ -14476,15 +15059,16 @@ } }, "node_modules/meow-helper": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/meow-helper/-/meow-helper-1.6.0.tgz", - "integrity": "sha512-nsqk9iv/tdzFrjYEr9Ysob9NvXJv2dy2n3Oq+uie02JKdFBzoKe7I4lDygKcmUaHkX7zih7ec3kH6HOexNtYkA==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/meow-helper/-/meow-helper-1.6.2.tgz", + "integrity": "sha512-k8FPXKOxg/YvrvtFbGr1tspGkUth9pcNVmi5GuTm2i75GUTOIJb31zt8phD4qfaL9mGTqkXvT+S6y8OC2Ts6kw==", "dependencies": { "chalk": "^4.1.0", - "cliui": "^7.0.4" + "cliui": "^7.0.4", + "dashify": "^2.0.0" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 14.0.0" } }, "node_modules/meow-helper/node_modules/cliui": { @@ -14688,6 +15272,25 @@ "node": ">= 8" } }, + "node_modules/mermaid": { + "version": "8.9.1", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-8.9.1.tgz", + "integrity": "sha512-0XFtH3TazlWQ6hKqBDeOfXglPBAfNDreC63NKjrmgzLG+aIY3yJZNdkl22JH4LniqQDx+7oZFmD7t0PnEymkew==", + "dev": true, + "dependencies": { + "@braintree/sanitize-url": "^3.1.0", + "d3": "^5.7.0", + "dagre": "^0.8.4", + "dagre-d3": "^0.6.4", + "entity-decode": "^2.0.2", + "graphlib": "^2.1.7", + "he": "^1.2.0", + "khroma": "^1.1.0", + "minify": "^4.1.1", + "moment-mini": "^2.22.1", + "stylis": "^3.5.2" + } + }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -14837,6 +15440,94 @@ "node": ">= 4" } }, + "node_modules/minify": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/minify/-/minify-4.1.3.tgz", + "integrity": "sha512-ykuscavxivSmVpcCzsXmsVTukWYLUUtPhHj0w2ILvHDGqC+hsuTCihBn9+PJBd58JNvWTNg9132J9nrrI2anzA==", + "dev": true, + "dependencies": { + "clean-css": "^4.1.6", + "css-b64-images": "~0.2.5", + "debug": "^4.1.0", + "html-minifier": "^4.0.0", + "terser": "^4.0.0", + "try-catch": "^2.0.0", + "try-to-catch": "^1.0.2" + }, + "bin": { + "minify": "bin/minify.js" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/minify/node_modules/camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "dev": true, + "dependencies": { + "no-case": "^2.2.0", + "upper-case": "^1.1.1" + } + }, + "node_modules/minify/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/minify/node_modules/html-minifier": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz", + "integrity": "sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==", + "dev": true, + "dependencies": { + "camel-case": "^3.0.0", + "clean-css": "^4.2.1", + "commander": "^2.19.0", + "he": "^1.2.0", + "param-case": "^2.1.1", + "relateurl": "^0.2.7", + "uglify-js": "^3.5.1" + }, + "bin": { + "html-minifier": "cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/minify/node_modules/lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", + "dev": true + }, + "node_modules/minify/node_modules/no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "dev": true, + "dependencies": { + "lower-case": "^1.1.1" + } + }, + "node_modules/minify/node_modules/param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "dev": true, + "dependencies": { + "no-case": "^2.2.0" + } + }, + "node_modules/minify/node_modules/upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", + "dev": true + }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -14935,6 +15626,12 @@ "node": ">=10" } }, + "node_modules/moment-mini": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment-mini/-/moment-mini-2.24.0.tgz", + "integrity": "sha512-9ARkWHBs+6YJIvrIp0Ik5tyTTtP9PoV0Ssu2Ocq5y9v8+NOOpWiRshAp8c4rZVWTOe+157on/5G+zj5pwIQFEQ==", + "dev": true + }, "node_modules/move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -21928,9 +22625,9 @@ "integrity": "sha512-El+aXWcwG/8wuFICMQjM5ZSAm6OWiJicFdNYo+VY3QP+8vI4SvLIWVe51PppTzMhikUJR+PsyIFKqfdXPz/yxA==" }, "node_modules/pg-structure": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/pg-structure/-/pg-structure-7.7.0.tgz", - "integrity": "sha512-DNCP8noKsmei7UwsE6HPNi3Yft04/6/3kbv9l4oio+wVfbX8jMbFmOMLNs2+SPA4eM8CM0y9lmaGLvkeFcOyHw==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/pg-structure/-/pg-structure-7.12.1.tgz", + "integrity": "sha512-9Xc8hvdi/GnKM7B5+i3sAikMdwqeX3edv/e+OvGyQjfk/v/MhuC4e3hi/GYwy+wD26D3Sqh7apk3ehRFJHMg0w==", "dependencies": { "@typescript-plus/fast-memoize-decorator": "^0.1.0", "dotenv": "^8.2.0", @@ -21943,7 +22640,7 @@ "pg-connection-string": "^2.2.1" }, "engines": { - "node": ">= 12.0.0" + "node": ">= 14.0.0" } }, "node_modules/pg-types": { @@ -23016,7 +23713,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", - "dev": true, "bin": { "prettier": "bin-prettier.js" }, @@ -24426,6 +25122,12 @@ "aproba": "^1.1.1" } }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=", + "dev": true + }, "node_modules/rxjs": { "version": "6.6.3", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", @@ -26005,6 +26707,12 @@ "node": ">=8" } }, + "node_modules/stylis": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz", + "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==", + "dev": true + }, "node_modules/stylus": { "version": "0.54.8", "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.8.tgz", @@ -26982,6 +27690,21 @@ "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", "dev": true }, + "node_modules/try-catch": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/try-catch/-/try-catch-2.0.1.tgz", + "integrity": "sha512-LsOrmObN/2WdM+y2xG+t16vhYrQsnV8wftXIcIOWZhQcBJvKGYuamJGwnU98A7Jxs2oZNkJztXlphEOoA0DWqg==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/try-to-catch": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/try-to-catch/-/try-to-catch-1.1.1.tgz", + "integrity": "sha512-ikUlS+/BcImLhNYyIgZcEmq4byc31QpC+46/6Jm5ECWkVFhf8SM2Fp/0pMVXPX6vk45SMCwrP4Taxucne8I0VA==", + "dev": true + }, "node_modules/ts-jest": { "version": "26.5.1", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.1.tgz", @@ -27292,9 +28015,9 @@ } }, "node_modules/typedoc-plugin-markdown": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.5.0.tgz", - "integrity": "sha512-UzSTK5RpQVbIrcxV1ypHt3Pqr4O3DObYZIhcAXBazitHnpdl500cggXFHmxH7F/j3P3P2IBvPKpfnU6lzRdk8w==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.6.0.tgz", + "integrity": "sha512-fg4xby3awJVVxB8TdhHNsZQfiTC5x1XmauVwhKXc6hGeu1bzTnqrkmDT8NCjxfUgw64si8cUX1jBfBjAHthWpQ==", "dev": true, "dependencies": { "handlebars": "^4.7.6" @@ -27336,7 +28059,6 @@ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.12.8.tgz", "integrity": "sha512-fvBeuXOsvqjecUtF/l1dwsrrf5y2BCUk9AOJGzGcm6tE7vegku5u/YvqjyDaAGr422PLoLnrxg3EnRvTqsdC1w==", "dev": true, - "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" }, @@ -28274,6 +28996,15 @@ "markdown-it-container": "^2.0.0" } }, + "node_modules/vuepress-plugin-mermaidjs": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/vuepress-plugin-mermaidjs/-/vuepress-plugin-mermaidjs-1.8.1.tgz", + "integrity": "sha512-gVnl2t2cbTd0ZWqikZzPPIjBvvcSKzAcuiON96Fi6RQo0QzIpjzXxuIp9bZ+tFUHn6UZp6hqqPtOdbsgcajilg==", + "dev": true, + "dependencies": { + "mermaid": "^8.8.3" + } + }, "node_modules/vuepress-plugin-smooth-scroll": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/vuepress-plugin-smooth-scroll/-/vuepress-plugin-smooth-scroll-0.0.3.tgz", @@ -29506,8 +30237,7 @@ "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" }, "node_modules/workbox-background-sync": { "version": "4.3.1", @@ -31173,6 +31903,12 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "@braintree/sanitize-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-3.1.0.tgz", + "integrity": "sha512-GcIY79elgB+azP74j8vqkiXz8xLFfIzbQJdlwOPisgbKT00tviJQuEghOXSMVxJ00HoYJbGswr4kcllUc4xCcg==", + "dev": true + }, "@cnakazawa/watch": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz", @@ -31184,88 +31920,216 @@ } }, "@commitlint/cli": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-11.0.0.tgz", - "integrity": "sha512-YWZWg1DuqqO5Zjh7vUOeSX76vm0FFyz4y0cpGMFhrhvUi5unc4IVfCXZ6337R9zxuBtmveiRuuhQqnRRer+13g==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-12.0.1.tgz", + "integrity": "sha512-V+cMYNHJOr40XT9Kvz3Vrz1Eh7QE1rjQrUbifawDAqcOrBJFuoXwU2SAcRtYFCSqFy9EhbreQGhZFs8dYb90KA==", "dev": true, "requires": { - "@babel/runtime": "^7.11.2", - "@commitlint/format": "^11.0.0", - "@commitlint/lint": "^11.0.0", - "@commitlint/load": "^11.0.0", - "@commitlint/read": "^11.0.0", - "chalk": "4.1.0", - "core-js": "^3.6.1", + "@commitlint/format": "^12.0.1", + "@commitlint/lint": "^12.0.1", + "@commitlint/load": "^12.0.1", + "@commitlint/read": "^12.0.1", + "@commitlint/types": "^12.0.1", "get-stdin": "8.0.0", "lodash": "^4.17.19", "resolve-from": "5.0.0", "resolve-global": "1.0.0", - "yargs": "^15.1.0" + "yargs": "^16.2.0" + }, + "dependencies": { + "@commitlint/execute-rule": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-12.0.1.tgz", + "integrity": "sha512-JzyweYfZlFLtXpgP+btzSY3YAkGPg61TqUSYQqBr4+5IaVf1FruMm5v4D5eLu9dAJuNKUfHbM3AEfuEPiZ79pg==", + "dev": true + }, + "@commitlint/load": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-12.0.1.tgz", + "integrity": "sha512-dX8KdCWn7w0bTkkk3zKQpe9X8vsTRa5EM+1ffF313wCX9b6tGa9vujhEHCkSzKAbbE2tFV64CHZygE7rtlHdIA==", + "dev": true, + "requires": { + "@commitlint/execute-rule": "^12.0.1", + "@commitlint/resolve-extends": "^12.0.1", + "@commitlint/types": "^12.0.1", + "chalk": "^4.0.0", + "cosmiconfig": "^7.0.0", + "lodash": "^4.17.19", + "resolve-from": "^5.0.0" + } + }, + "@commitlint/resolve-extends": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-12.0.1.tgz", + "integrity": "sha512-Mvg0GDi/68Cqw893ha8uhxE8myHfPmiSSSi7d1x4VJNR4hoS37lBdX89kyx4i9NPmLfviY2cUJKTyK8ZrFznZw==", + "dev": true, + "requires": { + "import-fresh": "^3.0.0", + "lodash": "^4.17.19", + "resolve-from": "^5.0.0", + "resolve-global": "^1.0.0" + } + }, + "@commitlint/types": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-12.0.1.tgz", + "integrity": "sha512-FsNDMV0W7D19/ZbR412klpqAilXASx75Neqh7jPtK278IEwdukOg3vth1r5kTm+BjDScM7wMUEOwIW3NNfAtwg==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", + "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + } } }, "@commitlint/config-conventional": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-11.0.0.tgz", - "integrity": "sha512-SNDRsb5gLuDd2PL83yCOQX6pE7gevC79UPFx+GLbLfw6jGnnbO9/tlL76MLD8MOViqGbo7ZicjChO9Gn+7tHhA==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-12.0.1.tgz", + "integrity": "sha512-1ZhB135lh47zVmf1orwcjxuKuam11fJIH/bdVxW9XiQv8XPwC6iIp19knfl8FcOT78AVBnes1z6EVxgUeP2/4Q==", "dev": true, "requires": { "conventional-changelog-conventionalcommits": "^4.3.1" } }, "@commitlint/ensure": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-11.0.0.tgz", - "integrity": "sha512-/T4tjseSwlirKZdnx4AuICMNNlFvRyPQimbZIOYujp9DSO6XRtOy9NrmvWujwHsq9F5Wb80QWi4WMW6HMaENug==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-12.0.1.tgz", + "integrity": "sha512-XdBq+q1YBBDxWIAEjE3Y1YMbzhUnUuSLAEWD8SU1xsvEpQXWRYwDlMBRkjO7funNWTdL0ZQSkZDzme70imYjbw==", "dev": true, "requires": { - "@commitlint/types": "^11.0.0", + "@commitlint/types": "^12.0.1", "lodash": "^4.17.19" + }, + "dependencies": { + "@commitlint/types": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-12.0.1.tgz", + "integrity": "sha512-FsNDMV0W7D19/ZbR412klpqAilXASx75Neqh7jPtK278IEwdukOg3vth1r5kTm+BjDScM7wMUEOwIW3NNfAtwg==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + } + } } }, "@commitlint/execute-rule": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-11.0.0.tgz", "integrity": "sha512-g01p1g4BmYlZ2+tdotCavrMunnPFPhTzG1ZiLKTCYrooHRbmvqo42ZZn4QMStUEIcn+jfLb6BRZX3JzIwA1ezQ==", - "dev": true + "dev": true, + "optional": true }, "@commitlint/format": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-11.0.0.tgz", - "integrity": "sha512-bpBLWmG0wfZH/svzqD1hsGTpm79TKJWcf6EXZllh2J/LSSYKxGlv967lpw0hNojme0sZd4a/97R3qA2QHWWSLg==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-12.0.1.tgz", + "integrity": "sha512-rF79ipAxR8yFzPzG5tRoEZ//MRkyxCXj4JhpEjtdaCMBAXMssI8uazn3e5D8z4UFgSDe9qOnL0OmQvql7HTMoA==", "dev": true, "requires": { - "@commitlint/types": "^11.0.0", + "@commitlint/types": "^12.0.1", "chalk": "^4.0.0" + }, + "dependencies": { + "@commitlint/types": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-12.0.1.tgz", + "integrity": "sha512-FsNDMV0W7D19/ZbR412klpqAilXASx75Neqh7jPtK278IEwdukOg3vth1r5kTm+BjDScM7wMUEOwIW3NNfAtwg==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + } + } } }, "@commitlint/is-ignored": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-11.0.0.tgz", - "integrity": "sha512-VLHOUBN+sOlkYC4tGuzE41yNPO2w09sQnOpfS+pSPnBFkNUUHawEuA44PLHtDvQgVuYrMAmSWFQpWabMoP5/Xg==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-12.0.1.tgz", + "integrity": "sha512-AplfLn5mX/kWTIiSolcOhTYcgphuGLX8FUr+HmyHBEqUkO36jt0z9caysH47fqU71ePtH63v1DWm+RYQ5RPDjg==", "dev": true, "requires": { - "@commitlint/types": "^11.0.0", - "semver": "7.3.2" + "@commitlint/types": "^12.0.1", + "semver": "7.3.4" }, "dependencies": { - "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "dev": true + "@commitlint/types": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-12.0.1.tgz", + "integrity": "sha512-FsNDMV0W7D19/ZbR412klpqAilXASx75Neqh7jPtK278IEwdukOg3vth1r5kTm+BjDScM7wMUEOwIW3NNfAtwg==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + } } } }, "@commitlint/lint": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-11.0.0.tgz", - "integrity": "sha512-Q8IIqGIHfwKr8ecVZyYh6NtXFmKw4YSEWEr2GJTB/fTZXgaOGtGFZDWOesCZllQ63f1s/oWJYtVv5RAEuwN8BQ==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-12.0.1.tgz", + "integrity": "sha512-1lKyRCq4ahJrY+Xxo8LsqCbALeJkodtEfpmYHeA5HpPMnK7lRSplLqOLcTCjoPfd4vO+gl6aDEZN+ow3YGQBOg==", "dev": true, "requires": { - "@commitlint/is-ignored": "^11.0.0", - "@commitlint/parse": "^11.0.0", - "@commitlint/rules": "^11.0.0", - "@commitlint/types": "^11.0.0" + "@commitlint/is-ignored": "^12.0.1", + "@commitlint/parse": "^12.0.1", + "@commitlint/rules": "^12.0.1", + "@commitlint/types": "^12.0.1" + }, + "dependencies": { + "@commitlint/types": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-12.0.1.tgz", + "integrity": "sha512-FsNDMV0W7D19/ZbR412klpqAilXASx75Neqh7jPtK278IEwdukOg3vth1r5kTm+BjDScM7wMUEOwIW3NNfAtwg==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + } + } } }, "@commitlint/load": { @@ -31273,6 +32137,7 @@ "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-11.0.0.tgz", "integrity": "sha512-t5ZBrtgvgCwPfxmG811FCp39/o3SJ7L+SNsxFL92OR4WQxPcu6c8taD0CG2lzOHGuRyuMxZ7ps3EbngT2WpiCg==", "dev": true, + "optional": true, "requires": { "@commitlint/execute-rule": "^11.0.0", "@commitlint/resolve-extends": "^11.0.0", @@ -31284,30 +32149,54 @@ } }, "@commitlint/message": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-11.0.0.tgz", - "integrity": "sha512-01ObK/18JL7PEIE3dBRtoMmU6S3ecPYDTQWWhcO+ErA3Ai0KDYqV5VWWEijdcVafNpdeUNrEMigRkxXHQLbyJA==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-12.0.1.tgz", + "integrity": "sha512-fXuoxRC+NT1wEQi6p8oHfT7wvWIRgTk+udlRJnWTjmMpiYzVnMmmZfasdShirWr4TtxQtMyL+5DVgh7Y98kURw==", "dev": true }, "@commitlint/parse": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-11.0.0.tgz", - "integrity": "sha512-DekKQAIYWAXIcyAZ6/PDBJylWJ1BROTfDIzr9PMVxZRxBPc1gW2TG8fLgjZfBP5mc0cuthPkVi91KQQKGri/7A==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-12.0.1.tgz", + "integrity": "sha512-7oEGASmzBnHir5jSIR7KephXrKh7rIi9a6RpH1tOT+CIENYvhe8EDtIy29qMt+RLa2LlaPF7YrAgaJRfzG0YDQ==", "dev": true, "requires": { - "conventional-changelog-angular": "^5.0.0", + "@commitlint/types": "^12.0.1", + "conventional-changelog-angular": "^5.0.11", "conventional-commits-parser": "^3.0.0" + }, + "dependencies": { + "@commitlint/types": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-12.0.1.tgz", + "integrity": "sha512-FsNDMV0W7D19/ZbR412klpqAilXASx75Neqh7jPtK278IEwdukOg3vth1r5kTm+BjDScM7wMUEOwIW3NNfAtwg==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + } + } } }, "@commitlint/read": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-11.0.0.tgz", - "integrity": "sha512-37V0V91GSv0aDzMzJioKpCoZw6l0shk7+tRG8RkW1GfZzUIytdg3XqJmM+IaIYpaop0m6BbZtfq+idzUwJnw7g==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-12.0.1.tgz", + "integrity": "sha512-baa0YeD4QOctEuthLpExQSi9xPiw0kDPfUVHqp8I88iuIXJECeS8S1+1GBiz89e8dLN9zmEE+sN9vtJHdAp9YA==", "dev": true, "requires": { - "@commitlint/top-level": "^11.0.0", + "@commitlint/top-level": "^12.0.1", + "@commitlint/types": "^12.0.1", "fs-extra": "^9.0.0", "git-raw-commits": "^2.0.0" + }, + "dependencies": { + "@commitlint/types": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-12.0.1.tgz", + "integrity": "sha512-FsNDMV0W7D19/ZbR412klpqAilXASx75Neqh7jPtK278IEwdukOg3vth1r5kTm+BjDScM7wMUEOwIW3NNfAtwg==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + } + } } }, "@commitlint/resolve-extends": { @@ -31315,6 +32204,7 @@ "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-11.0.0.tgz", "integrity": "sha512-WinU6Uv6L7HDGLqn/To13KM1CWvZ09VHZqryqxXa1OY+EvJkfU734CwnOEeNlSCK7FVLrB4kmodLJtL1dkEpXw==", "dev": true, + "optional": true, "requires": { "import-fresh": "^3.0.0", "lodash": "^4.17.19", @@ -31323,27 +32213,38 @@ } }, "@commitlint/rules": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-11.0.0.tgz", - "integrity": "sha512-2hD9y9Ep5ZfoNxDDPkQadd2jJeocrwC4vJ98I0g8pNYn/W8hS9+/FuNpolREHN8PhmexXbkjrwyQrWbuC0DVaA==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-12.0.1.tgz", + "integrity": "sha512-A5O0ubNGugZR9WWxk5IVOLo07lpdUwhG5WkAW2lYpgZ7Z/2U4PLob9b4Ih1eHbQu+gnVeFr91k7F0DrpM7B8EQ==", "dev": true, "requires": { - "@commitlint/ensure": "^11.0.0", - "@commitlint/message": "^11.0.0", - "@commitlint/to-lines": "^11.0.0", - "@commitlint/types": "^11.0.0" + "@commitlint/ensure": "^12.0.1", + "@commitlint/message": "^12.0.1", + "@commitlint/to-lines": "^12.0.1", + "@commitlint/types": "^12.0.1" + }, + "dependencies": { + "@commitlint/types": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-12.0.1.tgz", + "integrity": "sha512-FsNDMV0W7D19/ZbR412klpqAilXASx75Neqh7jPtK278IEwdukOg3vth1r5kTm+BjDScM7wMUEOwIW3NNfAtwg==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + } + } } }, "@commitlint/to-lines": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-11.0.0.tgz", - "integrity": "sha512-TIDTB0Y23jlCNubDROUVokbJk6860idYB5cZkLWcRS9tlb6YSoeLn1NLafPlrhhkkkZzTYnlKYzCVrBNVes1iw==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-12.0.1.tgz", + "integrity": "sha512-XwcJ1jY7x2fhudzbGMpNQkTSMVrxWrI8bRMbVe3Abuu7RfYpFf7VXAlhtnLfxBoagaK7RxjC2+eRidp/3txQBg==", "dev": true }, "@commitlint/top-level": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-11.0.0.tgz", - "integrity": "sha512-O0nFU8o+Ws+py5pfMQIuyxOtfR/kwtr5ybqTvR+C2lUPer2x6lnQU+OnfD7hPM+A+COIUZWx10mYQvkR3MmtAA==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-12.0.1.tgz", + "integrity": "sha512-rHdgt7U24GEau2/9i2vEAbksxkBRiVjHj5ECFL5dd0AJOIvaK++vMg4EF/ME0X/1yd9qVTHTNOl2Q4tTFK7VBQ==", "dev": true, "requires": { "find-up": "^5.0.0" @@ -31353,7 +32254,8 @@ "version": "11.0.0", "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-11.0.0.tgz", "integrity": "sha512-VoNqai1vR5anRF5Tuh/+SWDFk7xi7oMwHrHrbm1BprYXjB2RJsWLhUrStMssDxEl5lW/z3EUdg8RvH/IUBccSQ==", - "dev": true + "dev": true, + "optional": true }, "@eslint/eslintrc": { "version": "0.3.0", @@ -32113,6 +33015,12 @@ "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", "dev": true }, + "@types/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-XknqsI3sxtVduA/zP475wjMPH/qaZB6teY+AGvZkNUPhwxAac/QuKt6fpJCY9iO6ZpDhBmu9iOHgLXK78hoEDA==", + "dev": true + }, "@types/yargs": { "version": "15.0.13", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.13.tgz", @@ -35226,9 +36134,9 @@ } }, "colorette": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", - "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", "dev": true }, "colors": { @@ -36184,6 +37092,12 @@ "urix": "^0.1.0" } }, + "css-b64-images": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/css-b64-images/-/css-b64-images-0.2.5.tgz", + "integrity": "sha1-QgBdgyBLK0pdk7axpWRBM7WSegI=", + "dev": true + }, "css-color-names": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", @@ -36536,6 +37450,332 @@ } } }, + "d3": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-5.16.0.tgz", + "integrity": "sha512-4PL5hHaHwX4m7Zr1UapXW23apo6pexCgdetdJ5kTmADpG/7T9Gkxw0M0tf/pjoB63ezCCm0u5UaFYy2aMt0Mcw==", + "dev": true, + "requires": { + "d3-array": "1", + "d3-axis": "1", + "d3-brush": "1", + "d3-chord": "1", + "d3-collection": "1", + "d3-color": "1", + "d3-contour": "1", + "d3-dispatch": "1", + "d3-drag": "1", + "d3-dsv": "1", + "d3-ease": "1", + "d3-fetch": "1", + "d3-force": "1", + "d3-format": "1", + "d3-geo": "1", + "d3-hierarchy": "1", + "d3-interpolate": "1", + "d3-path": "1", + "d3-polygon": "1", + "d3-quadtree": "1", + "d3-random": "1", + "d3-scale": "2", + "d3-scale-chromatic": "1", + "d3-selection": "1", + "d3-shape": "1", + "d3-time": "1", + "d3-time-format": "2", + "d3-timer": "1", + "d3-transition": "1", + "d3-voronoi": "1", + "d3-zoom": "1" + } + }, + "d3-array": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", + "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==", + "dev": true + }, + "d3-axis": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.12.tgz", + "integrity": "sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ==", + "dev": true + }, + "d3-brush": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.6.tgz", + "integrity": "sha512-7RW+w7HfMCPyZLifTz/UnJmI5kdkXtpCbombUSs8xniAyo0vIbrDzDwUJB6eJOgl9u5DQOt2TQlYumxzD1SvYA==", + "dev": true, + "requires": { + "d3-dispatch": "1", + "d3-drag": "1", + "d3-interpolate": "1", + "d3-selection": "1", + "d3-transition": "1" + } + }, + "d3-chord": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.6.tgz", + "integrity": "sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA==", + "dev": true, + "requires": { + "d3-array": "1", + "d3-path": "1" + } + }, + "d3-collection": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz", + "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==", + "dev": true + }, + "d3-color": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz", + "integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==", + "dev": true + }, + "d3-contour": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-1.3.2.tgz", + "integrity": "sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==", + "dev": true, + "requires": { + "d3-array": "^1.1.1" + } + }, + "d3-dispatch": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz", + "integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA==", + "dev": true + }, + "d3-drag": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.5.tgz", + "integrity": "sha512-rD1ohlkKQwMZYkQlYVCrSFxsWPzI97+W+PaEIBNTMxRuxz9RF0Hi5nJWHGVJ3Om9d2fRTe1yOBINJyy/ahV95w==", + "dev": true, + "requires": { + "d3-dispatch": "1", + "d3-selection": "1" + } + }, + "d3-dsv": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz", + "integrity": "sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==", + "dev": true, + "requires": { + "commander": "2", + "iconv-lite": "0.4", + "rw": "1" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + }, + "d3-ease": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz", + "integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ==", + "dev": true + }, + "d3-fetch": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.2.0.tgz", + "integrity": "sha512-yC78NBVcd2zFAyR/HnUiBS7Lf6inSCoWcSxFfw8FYL7ydiqe80SazNwoffcqOfs95XaLo7yebsmQqDKSsXUtvA==", + "dev": true, + "requires": { + "d3-dsv": "1" + } + }, + "d3-force": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz", + "integrity": "sha512-HHvehyaiUlVo5CxBJ0yF/xny4xoaxFxDnBXNvNcfW9adORGZfyNF1dj6DGLKyk4Yh3brP/1h3rnDzdIAwL08zg==", + "dev": true, + "requires": { + "d3-collection": "1", + "d3-dispatch": "1", + "d3-quadtree": "1", + "d3-timer": "1" + } + }, + "d3-format": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz", + "integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==", + "dev": true + }, + "d3-geo": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.1.tgz", + "integrity": "sha512-XG4d1c/UJSEX9NfU02KwBL6BYPj8YKHxgBEw5om2ZnTRSbIcego6dhHwcxuSR3clxh0EpE38os1DVPOmnYtTPg==", + "dev": true, + "requires": { + "d3-array": "1" + } + }, + "d3-hierarchy": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz", + "integrity": "sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ==", + "dev": true + }, + "d3-interpolate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz", + "integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==", + "dev": true, + "requires": { + "d3-color": "1" + } + }, + "d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "dev": true + }, + "d3-polygon": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.6.tgz", + "integrity": "sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ==", + "dev": true + }, + "d3-quadtree": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz", + "integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA==", + "dev": true + }, + "d3-random": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.2.tgz", + "integrity": "sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ==", + "dev": true + }, + "d3-scale": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz", + "integrity": "sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==", + "dev": true, + "requires": { + "d3-array": "^1.2.0", + "d3-collection": "1", + "d3-format": "1", + "d3-interpolate": "1", + "d3-time": "1", + "d3-time-format": "2" + } + }, + "d3-scale-chromatic": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz", + "integrity": "sha512-ACcL46DYImpRFMBcpk9HhtIyC7bTBR4fNOPxwVSl0LfulDAwyiHyPOTqcDG1+t5d4P9W7t/2NAuWu59aKko/cg==", + "dev": true, + "requires": { + "d3-color": "1", + "d3-interpolate": "1" + } + }, + "d3-selection": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.2.tgz", + "integrity": "sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg==", + "dev": true + }, + "d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "dev": true, + "requires": { + "d3-path": "1" + } + }, + "d3-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz", + "integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==", + "dev": true + }, + "d3-time-format": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz", + "integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==", + "dev": true, + "requires": { + "d3-time": "1" + } + }, + "d3-timer": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz", + "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==", + "dev": true + }, + "d3-transition": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.3.2.tgz", + "integrity": "sha512-sc0gRU4PFqZ47lPVHloMn9tlPcv8jxgOQg+0zjhfZXMQuvppjG6YuwdMBE0TuqCZjeJkLecku/l9R0JPcRhaDA==", + "dev": true, + "requires": { + "d3-color": "1", + "d3-dispatch": "1", + "d3-ease": "1", + "d3-interpolate": "1", + "d3-selection": "^1.1.0", + "d3-timer": "1" + } + }, + "d3-voronoi": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz", + "integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==", + "dev": true + }, + "d3-zoom": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.8.3.tgz", + "integrity": "sha512-VoLXTK4wvy1a0JpH2Il+F2CiOhVu7VRXWF5M/LroMIh3/zBAC3WAt7QoIvPibOavVo20hN6/37vwAsdBejLyKQ==", + "dev": true, + "requires": { + "d3-dispatch": "1", + "d3-drag": "1", + "d3-interpolate": "1", + "d3-selection": "1", + "d3-transition": "1" + } + }, + "dagre": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz", + "integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==", + "dev": true, + "requires": { + "graphlib": "^2.1.8", + "lodash": "^4.17.15" + } + }, + "dagre-d3": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/dagre-d3/-/dagre-d3-0.6.4.tgz", + "integrity": "sha512-e/6jXeCP7/ptlAM48clmX4xTZc5Ek6T6kagS7Oz2HrYSdqcLZFLqpAfh7ldbZRFfxCZVyh61NEPR08UQRVxJzQ==", + "dev": true, + "requires": { + "d3": "^5.14", + "dagre": "^0.8.5", + "graphlib": "^2.1.8", + "lodash": "^4.17.15" + } + }, "dargs": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", @@ -36551,6 +37791,11 @@ "assert-plus": "^1.0.0" } }, + "dashify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dashify/-/dashify-2.0.0.tgz", + "integrity": "sha512-hpA5C/YrPjucXypHPPc0oJ1l9Hf6wWbiOL7Ik42cxnsUOhWiCB/fylKbKqqJalW9FgkNQCw16YO8uW9Hs0Iy1A==" + }, "data-urls": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", @@ -37463,6 +38708,15 @@ "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", "dev": true }, + "entity-decode": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/entity-decode/-/entity-decode-2.0.2.tgz", + "integrity": "sha512-5CCY/3ci4MC1m2jlumNjWd7VBFt4VfFnmSqSNmVcXq4gxM3Vmarxtt+SvmBnzwLS669MWdVuXboNVj1qN2esVg==", + "dev": true, + "requires": { + "he": "^1.1.1" + } + }, "envify": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/envify/-/envify-4.1.0.tgz", @@ -37686,9 +38940,9 @@ } }, "eslint-config-prettier": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz", - "integrity": "sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.1.0.tgz", + "integrity": "sha512-oKMhGv3ihGbCIimCAjqkdzx2Q+jthoqnXSP+d86M9tptwugycmTFdVR4IpLgq2c4SHifbwO90z2fQ8/Aio73yw==", "dev": true }, "eslint-import-resolver-node": { @@ -39149,6 +40403,15 @@ "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", "dev": true }, + "graphlib": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", + "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, "gray-matter": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.2.tgz", @@ -41396,6 +42659,12 @@ "json-buffer": "3.0.0" } }, + "khroma": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-1.2.0.tgz", + "integrity": "sha512-DlKk5y243dujy8fOH02aRnnewLfiHJV0s8aXaVrCohgBf3s7fEAn6gc6LLQ21agODlFZS8ufrn+juu70uCA9Tw==", + "dev": true + }, "killable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", @@ -42336,12 +43605,13 @@ } }, "meow-helper": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/meow-helper/-/meow-helper-1.6.0.tgz", - "integrity": "sha512-nsqk9iv/tdzFrjYEr9Ysob9NvXJv2dy2n3Oq+uie02JKdFBzoKe7I4lDygKcmUaHkX7zih7ec3kH6HOexNtYkA==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/meow-helper/-/meow-helper-1.6.2.tgz", + "integrity": "sha512-k8FPXKOxg/YvrvtFbGr1tspGkUth9pcNVmi5GuTm2i75GUTOIJb31zt8phD4qfaL9mGTqkXvT+S6y8OC2Ts6kw==", "requires": { "chalk": "^4.1.0", - "cliui": "^7.0.4" + "cliui": "^7.0.4", + "dashify": "^2.0.0" }, "dependencies": { "cliui": { @@ -42404,6 +43674,25 @@ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true }, + "mermaid": { + "version": "8.9.1", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-8.9.1.tgz", + "integrity": "sha512-0XFtH3TazlWQ6hKqBDeOfXglPBAfNDreC63NKjrmgzLG+aIY3yJZNdkl22JH4LniqQDx+7oZFmD7t0PnEymkew==", + "dev": true, + "requires": { + "@braintree/sanitize-url": "^3.1.0", + "d3": "^5.7.0", + "dagre": "^0.8.4", + "dagre-d3": "^0.6.4", + "entity-decode": "^2.0.2", + "graphlib": "^2.1.7", + "he": "^1.2.0", + "khroma": "^1.1.0", + "minify": "^4.1.1", + "moment-mini": "^2.22.1", + "stylis": "^3.5.2" + } + }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -42521,6 +43810,84 @@ } } }, + "minify": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/minify/-/minify-4.1.3.tgz", + "integrity": "sha512-ykuscavxivSmVpcCzsXmsVTukWYLUUtPhHj0w2ILvHDGqC+hsuTCihBn9+PJBd58JNvWTNg9132J9nrrI2anzA==", + "dev": true, + "requires": { + "clean-css": "^4.1.6", + "css-b64-images": "~0.2.5", + "debug": "^4.1.0", + "html-minifier": "^4.0.0", + "terser": "^4.0.0", + "try-catch": "^2.0.0", + "try-to-catch": "^1.0.2" + }, + "dependencies": { + "camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "dev": true, + "requires": { + "no-case": "^2.2.0", + "upper-case": "^1.1.1" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "html-minifier": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz", + "integrity": "sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==", + "dev": true, + "requires": { + "camel-case": "^3.0.0", + "clean-css": "^4.2.1", + "commander": "^2.19.0", + "he": "^1.2.0", + "param-case": "^2.1.1", + "relateurl": "^0.2.7", + "uglify-js": "^3.5.1" + } + }, + "lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", + "dev": true + }, + "no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "dev": true, + "requires": { + "lower-case": "^1.1.1" + } + }, + "param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "dev": true, + "requires": { + "no-case": "^2.2.0" + } + }, + "upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", + "dev": true + } + } + }, "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -42603,6 +43970,12 @@ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true }, + "moment-mini": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment-mini/-/moment-mini-2.24.0.tgz", + "integrity": "sha512-9ARkWHBs+6YJIvrIp0Ik5tyTTtP9PoV0Ssu2Ocq5y9v8+NOOpWiRshAp8c4rZVWTOe+157on/5G+zj5pwIQFEQ==", + "dev": true + }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -48052,9 +49425,9 @@ "integrity": "sha512-El+aXWcwG/8wuFICMQjM5ZSAm6OWiJicFdNYo+VY3QP+8vI4SvLIWVe51PppTzMhikUJR+PsyIFKqfdXPz/yxA==" }, "pg-structure": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/pg-structure/-/pg-structure-7.7.0.tgz", - "integrity": "sha512-DNCP8noKsmei7UwsE6HPNi3Yft04/6/3kbv9l4oio+wVfbX8jMbFmOMLNs2+SPA4eM8CM0y9lmaGLvkeFcOyHw==", + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/pg-structure/-/pg-structure-7.12.1.tgz", + "integrity": "sha512-9Xc8hvdi/GnKM7B5+i3sAikMdwqeX3edv/e+OvGyQjfk/v/MhuC4e3hi/GYwy+wD26D3Sqh7apk3ehRFJHMg0w==", "requires": { "@typescript-plus/fast-memoize-decorator": "^0.1.0", "dotenv": "^8.2.0", @@ -48972,8 +50345,7 @@ "prettier": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", - "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", - "dev": true + "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==" }, "prettier-linter-helpers": { "version": "1.0.0", @@ -50127,6 +51499,12 @@ "aproba": "^1.1.1" } }, + "rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=", + "dev": true + }, "rxjs": { "version": "6.6.3", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", @@ -51471,6 +52849,12 @@ } } }, + "stylis": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz", + "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==", + "dev": true + }, "stylus": { "version": "0.54.8", "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.8.tgz", @@ -52269,6 +53653,18 @@ "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", "dev": true }, + "try-catch": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/try-catch/-/try-catch-2.0.1.tgz", + "integrity": "sha512-LsOrmObN/2WdM+y2xG+t16vhYrQsnV8wftXIcIOWZhQcBJvKGYuamJGwnU98A7Jxs2oZNkJztXlphEOoA0DWqg==", + "dev": true + }, + "try-to-catch": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/try-to-catch/-/try-to-catch-1.1.1.tgz", + "integrity": "sha512-ikUlS+/BcImLhNYyIgZcEmq4byc31QpC+46/6Jm5ECWkVFhf8SM2Fp/0pMVXPX6vk45SMCwrP4Taxucne8I0VA==", + "dev": true + }, "ts-jest": { "version": "26.5.1", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.1.tgz", @@ -52520,9 +53916,9 @@ } }, "typedoc-plugin-markdown": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.5.0.tgz", - "integrity": "sha512-UzSTK5RpQVbIrcxV1ypHt3Pqr4O3DObYZIhcAXBazitHnpdl500cggXFHmxH7F/j3P3P2IBvPKpfnU6lzRdk8w==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.6.0.tgz", + "integrity": "sha512-fg4xby3awJVVxB8TdhHNsZQfiTC5x1XmauVwhKXc6hGeu1bzTnqrkmDT8NCjxfUgw64si8cUX1jBfBjAHthWpQ==", "dev": true, "requires": { "handlebars": "^4.7.6" @@ -52550,8 +53946,7 @@ "version": "3.12.8", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.12.8.tgz", "integrity": "sha512-fvBeuXOsvqjecUtF/l1dwsrrf5y2BCUk9AOJGzGcm6tE7vegku5u/YvqjyDaAGr422PLoLnrxg3EnRvTqsdC1w==", - "dev": true, - "optional": true + "dev": true }, "underscore": { "version": "1.8.3", @@ -53377,6 +54772,15 @@ "markdown-it-container": "^2.0.0" } }, + "vuepress-plugin-mermaidjs": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/vuepress-plugin-mermaidjs/-/vuepress-plugin-mermaidjs-1.8.1.tgz", + "integrity": "sha512-gVnl2t2cbTd0ZWqikZzPPIjBvvcSKzAcuiON96Fi6RQo0QzIpjzXxuIp9bZ+tFUHn6UZp6hqqPtOdbsgcajilg==", + "dev": true, + "requires": { + "mermaid": "^8.8.3" + } + }, "vuepress-plugin-smooth-scroll": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/vuepress-plugin-smooth-scroll/-/vuepress-plugin-smooth-scroll-0.0.3.tgz", @@ -54390,8 +55794,7 @@ "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" }, "workbox-background-sync": { "version": "4.3.1", diff --git a/package.json b/package.json index 49efe1d..acc863b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-generator", - "version": "1.0.0", + "version": "0.0.0", "description": "Template based scaffolding tool for PostgreSQL.", "author": { "name": "Özüm Eldoğan", @@ -20,7 +20,7 @@ "scaffold" ], "engines": { - "node": ">= 12.0.0" + "node": ">= 14.0.0" }, "main": "dist/index.js", "types": "dist/index.d.ts", @@ -55,7 +55,9 @@ "postpublish": "pinst --enable", "tsmod": "node module-files/scripts/tsmod.js", "yo:update": "yo tsmod:uninstall --no-install --force && yo 'tsmod' '--vuepress' '--no-coverage'", - "local-link": "ln -s ../../pg-generator-example-sequelize node_modules/pg-generator-example-sequelize" + "local-link": "ln -s ../../pg-generator-example node_modules/pg-generator-example", + "local-link-x": "ln -s ../../pg-generator-example node_modules/pg-generator-example && ln -s ../../pg-structure node_modules/pg-structure", + "pgen": "./dist/bin/pgen.js example:schwifty5 --out-dir ../sil/models --clear --relation-name-functions optimal" }, "vuepress": { "google-analytics-id": "" @@ -70,12 +72,14 @@ "lodash.get": "^4.4.2", "lodash.merge": "^4.6.2", "meow": "^9.0.0", - "meow-helper": "^1.6.0", - "pg-structure": "^7.7.0" + "meow-helper": "^1.6.2", + "pg-structure": "^7.12.1", + "prettier": "^2.2.1", + "wordwrap": "^1.0.0" }, "devDependencies": { - "@commitlint/cli": "^11.0.0", - "@commitlint/config-conventional": "^11.0.0", + "@commitlint/cli": "^12.0.1", + "@commitlint/config-conventional": "^12.0.1", "@ozum/pinst": "^2.1.4", "@types/inflection": "^1.5.28", "@types/jest": "^26.0.20", @@ -83,6 +87,7 @@ "@types/lodash.merge": "^4.6.6", "@types/node": "^14.14.31", "@types/pg": "^7.14.10", + "@types/wordwrap": "^1.0.0", "@typescript-eslint/eslint-plugin": "^4.15.1", "@typescript-eslint/parser": "^4.15.1", "@vuepress/plugin-active-header-links": "^1.8.2", @@ -92,7 +97,7 @@ "concat-md": "^0.3.5", "eslint": "^7.20.0", "eslint-config-airbnb-base": "^14.1.0", - "eslint-config-prettier": "^7.2.0", + "eslint-config-prettier": "^8.1.0", "eslint-plugin-import": "^2.22.0", "eslint-plugin-jest": "^24.1.5", "eslint-plugin-prettier": "^3.3.1", @@ -106,14 +111,15 @@ "readmeasy": "^0.2.7", "ts-jest": "^26.5.1", "ts-node-dev": "^1.1.1", - "typedoc": "^0.20.27", + "typedoc": "^0.20.28", "typedoc-neo-theme": "^1.1.0", "typedoc-plugin-example-tag": "^1.0.2", - "typedoc-plugin-markdown": "^3.5.0", + "typedoc-plugin-markdown": "^3.6.0", "typedoc-plugin-param-names": "^2.0.0", "typescript": "^4.1.5", "vuepress": "^1.8.2", "vuepress-bar": "^0.3.5", + "vuepress-plugin-mermaidjs": "^1.8.1", "walkdir": "^0.4.1" } } diff --git a/src/bin/meow.ts b/src/bin/meow.ts index 280e65a..7ec2296 100644 --- a/src/bin/meow.ts +++ b/src/bin/meow.ts @@ -89,5 +89,6 @@ const examples = [ ]; export default function getCLI(): meow.Result { - return meow(getHelp({ flags, args, pkg, groups, examples, command }), { flags, pkg, allowUnknownFlags: false }); + const help = getHelp({ lineLength: 140, flags, args, pkg, groups, examples, command }); + return meow(help, { flags, pkg, allowUnknownFlags: false }); } diff --git a/src/bin/pgen.ts b/src/bin/pgen.ts index 3536092..3452c04 100644 --- a/src/bin/pgen.ts +++ b/src/bin/pgen.ts @@ -1,26 +1,41 @@ #!/usr/bin/env node + +/* eslint-disable no-console */ import { EOL } from "os"; import { chalk } from "meow-helper"; +import { PgenError } from "../utils/pgen-error"; import getCLI from "./meow"; import { generate } from "../generate"; +import { readGenerators } from "../utils"; -function logError(message: string, code = 1): void { - console.log(chalk.red(`${message}${EOL}`)); // eslint-disable-line no-console +function showError(message: string, code = 1): any { + console.log(chalk.red(`${message}${EOL}`)); process.exit(code); } +function getSubGeneratorsMessage(generator: string, subGenerators?: string[]): string { + const available = subGenerators?.map((name: string) => `${generator}:${name}`).join(`${EOL} ● `); + return available ? ` Available sub-generators of "${generator}" are:${EOL} ● ${available}` : ""; +} + +async function logHelp(cli: any, generator: string): Promise { + const subGenerators = (await readGenerators(generator))?.generators; + console.log(cli.help); + console.log(getSubGeneratorsMessage(generator, subGenerators), EOL); +} + async function executeCommand(): Promise { const cli = getCLI(); - if (cli.input[0] === undefined) logError("GENERATOR is required."); + if (cli.input[0] === undefined) showError("GENERATOR is required."); const [generator, subGenerator] = cli.input[0].split(":"); + if (cli.flags.help) return logHelp(cli, generator); + try { return await generate(generator, subGenerator, cli.flags); } catch (error) { - const available = error?.subGenerators?.map((name: string) => `${generator}:${name}`).join(`${EOL} ● `); - const availableLog = available ? ` Available sub-generators are:${EOL} ● ${available}` : ""; - - return logError(`${error.message}${availableLog}`); + if (!(error instanceof PgenError)) throw error; + return showError(`${error.message}${getSubGeneratorsMessage(generator, error?.subGenerators)}`); } } -executeCommand(); +executeCommand().catch(console.log); diff --git a/src/converters/mermaid-to-svg.ts b/src/converters/mermaid-to-svg.ts index 9826d96..f17194f 100644 --- a/src/converters/mermaid-to-svg.ts +++ b/src/converters/mermaid-to-svg.ts @@ -42,26 +42,3 @@ export function mermaidToSVG(data: string, { link = false } = {}): string { return changeMd; } - -// export function SVGToMermaid(data: string): string { -// const matchData = data.match(/\[?!\[\]\(https:\/\/mermaid\.ink\/svg\/(.|\n)*?\)\n/gm); -// if (matchData === null) return data; -// const encodedURIs = matchData.map((item: string) => { -// item = item.replace("[![](https://mermaid.ink/img/", ""); -// // return item.substr(0, item.indexOf(")](https://mermaid-js.github.io/mermaid-live-editor/#/")); -// return item.substr(0, item.indexOf(")]")); -// }); - -// let originMd = data; - -// matchData.forEach((item: any, index: string | number) => { -// // Workaround for classdiagram about assignment let -// let { code } = JSON.parse(Base64.decode(encodedURIs[index as any])); -// // Workaround for classdiagram -// if (code.startsWith("class") || code.startsWith("gantt") || code.startsWith("erDiagram") || code.startsWith("journey")) -// code = `\n${code}`; -// originMd = originMd.replace(item, `\`\`\`mermaid${code}\`\`\`\n`); -// }); - -// return originMd; -// } diff --git a/src/index.ts b/src/index.ts index b047e8e..09659b8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,4 +6,4 @@ export * as filterFunctions from "./utils/filter-functions"; export * as converters from "./converters"; // Types -export type { Context, GeneratorOptions, Options } from "./types/index"; +export type { Context, GeneratorOptions, ClientOptions, Options } from "./types/index"; diff --git a/src/pg-generator.ts b/src/pg-generator.ts index 3bb4fc9..b6cbc64 100644 --- a/src/pg-generator.ts +++ b/src/pg-generator.ts @@ -1,12 +1,13 @@ /* eslint-disable class-methods-use-this */ -import { extname, join, relative, dirname, resolve } from "path"; +import { extname, join, dirname, resolve } from "path"; import { promises as fs } from "fs"; import { chalk } from "meow-helper"; -import { fdir as Fdir } from "fdir"; import merge from "lodash.merge"; import JSON5 from "json5"; +import prettier from "prettier"; +import { PgenError } from "./utils/pgen-error"; import type { Context, GeneratorOptions, InternalOptions } from "./types/index"; -import { getDbObjects, getTemplatePaths, resolvePath, augmentContext, composeWith } from "./utils"; +import { getDbObjects, resolvePath, augmentContext, composeWith, parseTemplatePath, scanTemplateDir } from "./utils"; const COLORS: Record = { default: "green", @@ -29,7 +30,10 @@ export abstract class PgGenerator * @param internalOptions are added by `pg-generator` functions and not for user. */ public constructor(options: O, internalOptions: InternalOptions) { - if (options.clear && !options.outDir) throw new Error("As a precaution, 'clear' option cannot be used without 'outDir' option."); + if (options.clear && !options.outDir) throw new PgenError("As a precaution, 'clear' option cannot be used without 'outDir' option."); + const collisions = internalOptions.db.relationNameCollisions; + if (collisions) throw PgenError.collisionError(collisions); + this.options = { envPrefix: "DB", copy: true, context: {}, ...options }; this.#internalOptions = internalOptions; this.#destinationRoot = resolve(internalOptions.cwd, this.options.outDir || ""); @@ -46,22 +50,24 @@ export abstract class PgGenerator */ public async generate(): Promise { if (this.options.clear) await this.clear(); + await this.init(); - const templatePaths = await getTemplatePaths(this.#internalOptions.templateDir); + const { templates, files } = await scanTemplateDir(this.#internalOptions.templateDir); const context = await this.fetchContext(); // Generate templates. Provide absolute outdir. Don't copy files, because you should use Yeoman's `mem-fs-editor` API. - await Promise.all( - templatePaths.flatMap((path) => - getDbObjects(this.#internalOptions.db, path).map(async (dbObject) => { - const destinationPath = resolvePath(path, dbObject); // e.g. {name#dashcase}.js -> member-option.js - const content = await this.render(path, augmentContext(dbObject, context)); + const processTemplates = Promise.all( + templates.flatMap((path) => { + const { className, accessor, targetPath } = parseTemplatePath(path); + return getDbObjects(this.#internalOptions.db, className, accessor, path).map(async (dbObject) => { + const destinationPath = resolvePath(targetPath, dbObject); // e.g. {name#dashcase}.js -> member-option.js + const content = await this.format(destinationPath, await this.render(path, augmentContext(dbObject, context))); if (content !== undefined && content.replace(/\s/g, "") !== "") await this.process(destinationPath, content); - }) - ) + }); + }) ); - - await this.copyDir("files"); + const copyFiles = Promise.all(files.map((file) => this.copyTemplate(file, file))); + await Promise.all([processTemplates, copyFiles]); } // @@ -71,17 +77,24 @@ export abstract class PgGenerator // // Methods below are lifecycle methods and most probably would be extended // by child classes for custom behavior. Providing `render` is mandatory. - // Flow: clear -> context -> render -> process + // Flow: clear -> init --> context -> render -> format -> process /** * If clear option is true, this method is called. It deletes destination path. * User may override this method to tailor clear operation according to generator's * purposes. */ - protected async clear(): Promise { + protected async clear(): Promise { await this.deleteDestination(); } + /** + * Executed after clear operation. + */ + protected init(): Promise | any { + return undefined; + } + /** * Provides generator specific extra context to templates. This data is deeply merged with * context provided by user. @@ -99,7 +112,22 @@ export abstract class PgGenerator * @param context is the data to be used for generating content. * @returns generated content. */ - protected abstract render(templatePath: string, context: Context): Promise | void | string; + protected render(templatePath: string, context: Context): Promise | undefined | string { + const stub = templatePath ?? context; // eslint-disable-line @typescript-eslint/no-unused-vars + return undefined; + } + + /** + * Formats given content. By default `prettier` is used. Plase note that at this stage file is not written to disk yet. + * + * @param destination is the path of the destination file to be created. + * @param content is the content to format. + * @returns formatted code. + */ + protected format(destination: string, content?: string): Promise | undefined | string { + if (content === undefined || content === null || content === "") return content; + return prettier.format(content, { filepath: destination }); + } /** * Writes generated content from [[render]] to the destination file. @@ -181,7 +209,9 @@ export abstract class PgGenerator */ protected async composeWith(generator: string, options?: GeneratorOptions): Promise; /** - * Executes a sub-generator from a generator. If options are provided, they are combined with current options. + * Executes a sub-generator from a generator. If options are provided, they are merged with current options. Also some of the options + * are changed to sensible default values for sub-generators (e.g. `clear` is changed to `false`), but they can be overridden by + * newly provided options. * * @param generator is the name or path of the generator. If it is a local path, use `require.resolve` or provide an absolute path. * @param subGeneratorName is the name of the sub-generator to be executed. @@ -195,8 +225,9 @@ export abstract class PgGenerator */ protected async composeWith(generator: string, subGeneratorName?: string, options?: GeneratorOptions): Promise; protected async composeWith(generator: string, subOrOptions?: string | GeneratorOptions, maybeOptions?: GeneratorOptions): Promise { - const [options = {}, generatorName = "app"] = typeof subOrOptions === "string" ? [maybeOptions, subOrOptions] : [maybeOptions]; - return composeWith(generator, generatorName, { ...this.options, ...options }, this.#internalOptions.db, this.#destinationRoot); + const [options = {}, generatorName] = typeof subOrOptions === "string" ? [maybeOptions, subOrOptions] : [maybeOptions]; + const newOptions = { ...this.options, clear: false, ...options }; + return composeWith(generator, generatorName, newOptions, this.#internalOptions.db, this.#internalOptions.cwd); } /** @@ -224,19 +255,6 @@ export abstract class PgGenerator this.log("create", { destination }); } - /** - * If source directory exists, copies all files recursively from the source directory to the destination directory. - * Also creates the destination directory if it does not exist. - * - * @param source is the source directory to copy files from. - * @param destination is the destination directory to copy files to. - */ - private async copyDir(source = "", destination = ""): Promise { - const absSource = this.templatePath(source); - const paths = ((await new Fdir().withBasePath().crawl(absSource).withPromise()) as string[]).map((p) => relative(absSource, p)); - return Promise.all(paths.map((path) => this.copyTemplate(join(source, path), join(destination, path)))); - } - /** * Removes file or directory (and it's contents() from destination. If destination is equal to `cwd()` * it throws error and aborts operation for a safety measure. Most probably `cwd()` contains other files too. @@ -246,7 +264,7 @@ export abstract class PgGenerator private async deleteDestination(path = ""): Promise { const destination = this.destinationPath(path); const isRoot = resolve(this.#internalOptions.cwd) === resolve(destination); - if (isRoot) throw new Error("Root is not deleted, because it may be a mistake. Probably it would contain other files."); + if (isRoot) throw new PgenError("Root is not deleted, because it may be a mistake. Probably it would contain other files."); try { await fs.rmdir(this.destinationPath(path), { recursive: true }); diff --git a/src/types/index.ts b/src/types/index.ts index 570123b..4975cb6 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -50,4 +50,4 @@ export interface InternalOptions { export type Options = GeneratorOptions & ClientOptions; /** Context provided to render function. */ -export type Context = { o: Db | DbObject; x: Record }; +export type Context = { o: Db | DbObject; c: Record }; diff --git a/src/utils/augment-context.ts b/src/utils/augment-context.ts index c0a8207..7e1f301 100644 --- a/src/utils/augment-context.ts +++ b/src/utils/augment-context.ts @@ -8,7 +8,6 @@ import { Context } from "../types/index"; * Adds extra data to context. More spesific data overrides generic one: * * - Adds global data. (Key: `global`). - * - Adds global data of type. (e.g. `typeGlobal.tables`, `typeGlobal.schemas` etc.) * - Adds related data of the database object. (e.g. `tables."public.member"`, `schemas.public` etc.) * * @param dbObject is the context data. @@ -16,17 +15,15 @@ import { Context } from "../types/index"; * @returns combined data. * * @example - * const context = { name: "member", columns: [] }; // context: Table * const extraContext = { * "global": { a: 1 }, - * "typeGlobal": { tables: { b: 2, skip: false } } , * "tables": { "public.member": { skip: true } } * }; - * augmentContext(context, extraContext); // { name: "member", columns: [], extra: { a:1, b:2, skip: true } } + * augmentContext(dbObject, extraContext); // { table: { name: "member", columns: [...] }, a:1, skip: true } */ export function augmentContext(dbObject: Db | DbObject, extra: Record): Context { const type = plural(camelCase(dbObject.constructor.name)); // e.g. tables const name = dbObject instanceof Db ? dbObject.name : (dbObject as DbObject).fullName; - // return { o: dbObject, x: { ...extra?.global, ...extra?.typeGlobal?.[type], ...extra?.[type]?.[name] } }; - return { o: dbObject, x: merge(extra?.global, extra?.typeGlobal?.[type], extra?.[type]?.[name]) }; + const instanceVariable = camelCase(dbObject.constructor.name); // "db", "table", "materializedView" + return { o: dbObject, [instanceVariable]: dbObject, ...merge(extra?.global, extra?.[type]?.[name]) }; } diff --git a/src/utils/compose-with.ts b/src/utils/compose-with.ts index a14bd97..0897268 100644 --- a/src/utils/compose-with.ts +++ b/src/utils/compose-with.ts @@ -7,6 +7,7 @@ import type { GeneratorOptions } from "../types"; import { PgenError } from "./pgen-error"; const SUBDIRS = ["generators", "dist/generators", "lib/generators", "dist", "lib", "."]; +const SPECIAL_DIRS = ["partials", "utils"]; /** * Checks whether given path exists. @@ -19,6 +20,17 @@ async function exists(path?: string): Promise { return (await fs.lstat(path).catch(ignoreCode("ENOENT"))) !== undefined; } +/** + * If given id does not have prefix, adds prefix to it. + * + * @param id is the id to add prefix. + * @param prefix is the prefix to add. + * @returns id with prefix. + * + * @example + * getAlternativeId("example", "pg-generator"); // "pg-generator-example" + * getAlternativeId("@user/example", "pg-generator"); // "@user/pg-generator-example" + */ function getAlternativeId(id?: string, prefix?: string): string | undefined { if (!id || !prefix) return undefined; const { dir, name, ext } = parse(id); @@ -40,44 +52,18 @@ function getAlternativeId(id?: string, prefix?: string): string | undefined { * resolveModule("./my-module"); // /path/to/my-module */ function resolvePath(id?: string, prefix?: string): string | undefined { + let result: string | undefined; if (id === undefined) return undefined; - if (/^\.\.?[\\/]/.test(id)) return resolve(id); // Test relative path. Matches "./", "../", "..\", "..\" - if (isAbsolute(id)) return id; - const alternativeId = getAlternativeId(id, prefix); - let result = ignoreCode("MODULE_NOT_FOUND", () => require.resolve(id)); + // Test relative path. Matches "./", "../", "..\", "..\" + if (/^\.\.?[\\/]/.test(id)) result = resolve(id); + else if (isAbsolute(id)) result = id; + else result = ignoreCode("MODULE_NOT_FOUND", () => require.resolve(id)); + if (result === undefined && alternativeId !== undefined) result = ignoreCode("MODULE_NOT_FOUND", () => require.resolve(alternativeId)); return result !== undefined ? dirname(result) : undefined; } -/** - * Gets absolute path of a module. If module is an npm package returns it's root directory (not path of the file written in `package.main`). - * If module name is given without a prefix, also searches for prefixed module name. - * - * @param moduleName is the module to get path of. - * @param prefix is the string added at the beginning of the module name. - * @return path of the module. - * - * @throws error if module cannot be found. - * - * @example - * getModulePath("my-module", "pg-generator-"); // Tries to get `pg-generator-my-module`. If it is not available, tries to get `my-module`. - */ -// async function getModulePath(id: string, prefix?: string): Promise { -// const path = resolvePath(id); -// if (await exists(path)) return path as string; -// const { root, dir, name, ext } = parse(id); - -// if (prefix && !name.startsWith(prefix)) { -// const alternativeId = format({ root, dir, name: `${prefix}-${name}`, ext }); -// const alternativePath = resolvePath(alternativeId); -// if (await exists(alternativePath)) return alternativePath as string; -// console.log(path, alternativePath); -// } - -// throw new Error(`Cannot find generator: '${id}'`); -// } - /** * Reads directories of first available sub-plugin path. * @@ -94,18 +80,19 @@ function resolvePath(id?: string, prefix?: string): string | undefined { export async function readGenerators(id: string): Promise<{ path: string; generatorsPath: string; generators: string[] } | undefined> { const path = await resolvePath(id, "pg-generator"); if (path === undefined || !(await exists(path))) return undefined; - for (const generatorsPath of SUBDIRS) { const fullPath = join(path, generatorsPath); + if ((await Promise.all([exists(join(fullPath, "index.js")), exists(join(fullPath, "templates"))])).every((result) => result)) return { path, generatorsPath, generators: [""] }; const entries = await fs.readdir(fullPath, { withFileTypes: true }).catch(ignoreCode(["ENOTDIR", "ENOENT"])); - const generators = entries && entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name); + const generators = + entries && entries.filter((entry) => entry.isDirectory() && !SPECIAL_DIRS.includes(entry.name)).map((entry) => entry.name); if (generators !== undefined) return { path, generatorsPath, generators }; } - throw new PgenError("NOEXP", id); + throw PgenError.composerError("NOEXP", id); } /** @@ -131,18 +118,18 @@ export async function composeWith( cwd: string ): Promise { const module = await readGenerators(generator); - if (module === undefined) throw new PgenError("NOGEN", generator, subGenerator); - + if (module === undefined) throw PgenError.composerError("NOGEN", generator, subGenerator); subGenerator = subGenerator ?? module.generators.find((g) => g === "" || g === "app"); // eslint-disable-line no-param-reassign if (subGenerator === undefined || !module.generators.includes(subGenerator)) - throw new PgenError("NOSUB", generator, subGenerator, module.generators); + throw PgenError.composerError("NOSUB", generator, subGenerator, module.generators); const generatorPath = join(module.path, module.generatorsPath, subGenerator); const GeneratorModule = await import(generatorPath); const Generator = GeneratorModule.default ?? GeneratorModule[subGenerator]; - if (!(typeof Generator?.prototype.generate === "function")) throw new PgenError("NOTAGEN", generator, subGenerator, module.generators); + if (!(typeof Generator?.prototype.generate === "function")) + throw PgenError.composerError("NOTAGEN", generator, subGenerator, module.generators); const internalOptions = { templateDir: join(generatorPath, "templates"), cwd, db }; diff --git a/src/utils/filter-functions.ts b/src/utils/filter-functions.ts index 087d202..655e055 100644 --- a/src/utils/filter-functions.ts +++ b/src/utils/filter-functions.ts @@ -1,9 +1,10 @@ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ -import type { DbObject } from "pg-structure"; import { EOL } from "os"; import { inspect } from "util"; -import inflection from "inflection"; import { Column } from "pg-structure"; +import type { DbObject } from "pg-structure"; +import wordWrapper from "wordwrap"; +import inflection from "inflection"; // // ──────────────────────────────────────────────────────────────────── I ────────── @@ -45,7 +46,7 @@ export function clearDefault(input?: string): string | undefined { * @example * camelCase("user-name"); // userName */ -export function camelCase(input: string): string { +export function camelCase(input = ""): string { return inflection.camelize(input.replace("-", "_"), true); } @@ -58,7 +59,7 @@ export function camelCase(input: string): string { * @example * pascalCase("user-name"); // UserName */ -export function pascalCase(input: string): string { +export function pascalCase(input = ""): string { return inflection.camelize(input.replace("-", "_"), false); } @@ -71,7 +72,7 @@ export function pascalCase(input: string): string { * @example * classCase("user-name"); // UserName */ -export function classCase(input: string): string { +export function classCase(input = ""): string { return inflection.classify(input.replace("-", "_")); } @@ -84,7 +85,7 @@ export function classCase(input: string): string { * @example * snakeCase("userName"); // user_name */ -export function snakeCase(input: string): string { +export function snakeCase(input = ""): string { return inflection.underscore(input.replace("-", "_")); } @@ -97,10 +98,23 @@ export function snakeCase(input: string): string { * @example * dashCase("User Name"); // user-name */ -export function dashCase(input: string): string { +export function dashCase(input = ""): string { return inflection.transform(input, ["underscore", "dasherize"]); } +/** + * Converts the given input to the title case. + * + * @param input is the input string to convert. + * @returns string as title case. + * + * @example + * titleCase("user_name"); // User Name + */ +export function titleCase(input = ""): string { + return inflection.titleize(input); +} + /** * Converts the given input to the singular form. * @@ -110,7 +124,7 @@ export function dashCase(input: string): string { * @example * singular("user_names"); // user_name */ -export function singular(input: string): string { +export function singular(input = ""): string { return inflection.singularize(input); } @@ -123,10 +137,25 @@ export function singular(input: string): string { * @example * plural("user_name"); // user_names */ -export function plural(input: string): string { +export function plural(input = ""): string { return inflection.pluralize(input); } +/** + * Converts text to natural language. + * + * @param input is the input string to convert. + * @param lowFirstLetter is whther to use small letter in first word. + * @returns string in human readable form. + * + * @example + * human("message_properties"); // "Message properties" + * human("message_properties", true); // "message properties" + */ +export function human(input = "", lowFirstLetter?: boolean): string { + return inflection.humanize(input, lowFirstLetter); +} + /** * Converts the given input's first letter to the lower case. * @@ -136,7 +165,7 @@ export function plural(input: string): string { * @example * plural("User_name"); // User_name */ -export function lcFirst(input: string): string { +export function lcFirst(input = ""): string { return input[0].toLowerCase() + input.slice(1); } @@ -149,21 +178,34 @@ export function lcFirst(input: string): string { * @example * plural("user_name"); // "user_name" */ -export function quote(input: string): string { - return JSON.stringify(input); +export function quote(input?: string): string { + return input !== undefined ? JSON.stringify(input) : ""; } /** * Wraps the given string with single quotes. * - * @param input is the input string to wrap with quotes. + * @param input is the input string to wrap with single quotes. * @returns string with quotes. * * @example * plural("Some 'example' text"); // 'some \'example\' text' */ -export function singleQuote(input: string): string { - return `'${input.replace(/'/g, "\\'")}'`; +export function singleQuote(input?: string): string { + return input !== undefined ? `'${input.replace(/'/g, "\\'")}'` : ""; +} + +/** + * Wraps the given string with double quotes. + * + * @param input is the input string to wrap with double quotes. + * @returns string with quotes. + * + * @example + * plural("Some "example" text"); // "some \"example\" text" + */ +export function doubleQuote(input?: string): string { + return input !== undefined ? `"${input.replace(/"/g, '\\"')}"` : ""; } /** @@ -173,7 +215,8 @@ export function singleQuote(input: string): string { * @param removeList is the list of strings or objects to remove from input. * @returns converted string. */ -export function stripPrefix(input: string, ...removeList: Array): string { +export function stripPrefix(input: string | undefined, ...removeList: Array): string { + if (input === undefined) return ""; return removeList .map((item) => (typeof item === "object" ? item.name : item)) .reduce((result, item) => result.replace(new RegExp(`^${item}[_\\s-]*`), ""), input); @@ -186,7 +229,8 @@ export function stripPrefix(input: string, ...removeList: Array): string { +export function stripSuffix(input: string | undefined, ...removeList: Array): string { + if (input === undefined) return ""; return removeList .map((item) => (typeof item === "object" ? item.name : item)) .reduce((result, item) => result.replace(new RegExp(`[_\\s-]*${item}$`), ""), input); @@ -199,7 +243,8 @@ export function stripSuffix(input: string, ...removeList: Array): string { +export function strip(input: string | undefined, ...removeList: Array): string { + if (input === undefined) return ""; return removeList .map((item) => (typeof item === "object" ? item.name : item)) .reduce((result, item) => result.replace(new RegExp(`${item}[_\\s-]*`), ""), input); @@ -213,30 +258,105 @@ export function strip(input: string, ...removeList: Array= totalLength) return input; +export function padRight(input: string | undefined, totalLength: number, paddingString = " "): string { + if (input === undefined) return ""; + if (paddingString === undefined || input.length >= totalLength) return input; const count = Math.floor((totalLength - input.length) / paddingString.length); return input + paddingString.repeat(count); } /** - * Converts given string to JSOC lines by adding "*" at the start of each line. + * Cuts the text after given number of characters. * - * @param input is the input string to convert. + * @param input is the text to shorten. + * @param length is the maximum length allowed. + * @returns cut text + * + * @example + * maxLength("some example text", 7); // "some ex..."; + */ +export function maxLength(input = "", length = 50): string { + return input.substring(0, length).replace(/\n/g, " ") + (input.length > length ? "..." : ""); +} + +/** + * Completes given input's length using with given character (by default space). It may be used to align + * strings in JSDoc etc. + * + * @param input is the input to complete length of. + * @param length is the length of the finel string. + * @param char is the character to be used for filling. + * + * @example + * completeWithChar("member", "10"); // "member " + * completeWithChar("member", "10", "-"); // "member----" + */ +export function fill(input = "", length = 20, char = " "): string { + const fillString = char.repeat(Math.max(0, length - input.length)); + return `${input}${fillString}`; +} + +/** + * Wraps given text with start and end characters. By default it wraps with curly braces. + * + * @param input is the text to warp. + * @param start is the starting string. + * @param end is the ending string. + * @returns wrapped text. + * + * @example + * wrap("hello"); // "{hello}" + * wrap("hello", "~"); // "~hello~" + * wrap("hello", "[]"); // "[hello]" + */ +export function wrap(input?: string, wrapper = "{}"): string { + if (input === undefined) return ""; + const start = wrapper.length === 1 ? wrapper : wrapper.substring(0, wrapper.length / 2); + const end = wrapper.length === 1 ? wrapper : wrapper.slice(-(wrapper.length / 2)); + return `${start}${input}${end}`; +} + +/** + * Wraps given text with start and end characters if given condition is truthy. + * By default it wraps with curly braces. + * + * @param input is the text to warp. + * @param start is the starting string. + * @param end is the ending string. + * @param condition is the condition or value to test. + * @returns wrapped text. + * + * @example + * wrapIf("hello", "x"); // "{hello}" + * wrapIf("hello", true); // "{hello}" + * wrapIf("hello", false); // "hello" + * wrapIf("hello", true, "~"); // "~hello~" + * wrapIf("hello", true, "[]"); // "[hello]" + */ +export function wrapIf(input: string | undefined, condition: any, wrapper = "{}"): string { + if (input === undefined) return ""; + return condition ? wrap(input, wrapper) : input; +} + +/** + * Adds given prefix each of the lines of given text. + * + * @param input is the input string. + * @param prefix is the prefix to add each of the lines. * @returs the result string. * * @example - * makeJsDoc(` + * linePrefix(` * Text line 1 * Text line 2 - * `); + * `, "// "); * - * // * Text line 1 - * // * Text line 1 + * // Text line 1 + * // Text line 2 */ -export function makeJsDoc(input = ""): string { - const result = input.replace(new RegExp(`(\n|${EOL})`, "g"), "$1 * "); - return ` * ${result}`; +export function linePrefix(input = "", prefix: string): string { + const result = input.replace(new RegExp(`(\n|${EOL})`, "g"), `$1${prefix}`); + return `${prefix}${result}`; } /** @@ -263,20 +383,22 @@ function _convertNullToUndef | any[]>(inp * 2. Uses `util.inspect()`; * * @param input is the input to convert. - * @param raw if true, does not add quotes around values. - * @param nullToUndef if true, converts all null values to undefined. + * @param options are the options. + * @param options.raw if true, does not add quotes around values. + * @param options.nullToUndef if true, converts all null values to undefined. + * @param options.indent is size of the indentation of each level. * @returns converted value. */ -export function stringify(input: any, options: { nullToUndef?: boolean; raw?: boolean } = {}): string { +export function stringify(input: any, options: { nullToUndef?: boolean; raw?: boolean; indent?: number } = {}): string { const result = options.nullToUndef ? _convertNullToUndef(input) : input; - if (typeof result !== "object") return JSON.stringify(result) ?? "undefined"; + if (typeof result !== "object") return JSON.stringify(result, undefined, options.indent) ?? "undefined"; if (options.raw) { return Array.isArray(result) ? result.join(", ") : Object.entries(result) - .reduce((reducedResult, [key, value]) => `${reducedResult}${key}: ${value},\n`, "") + .reduce((reducedResult, [key, value]) => `${reducedResult}${key}: ${value},\n${" ".repeat(options.indent ?? 0)}`, "") .replace(/,\n$/, ""); } @@ -285,12 +407,12 @@ export function stringify(input: any, options: { nullToUndef?: boolean; raw?: bo } /** - * If given data is a multi line string replcaes new lines with escape characters. May be used to prevent JS multi line errors. + * If given data is a multi line string replaces new lines with escape characters. May be used to prevent JS multi line errors. * * @param input is the input to convert. * @returns the string with escape characters. */ -export function singleLine(input: string): string { +export function singleLine(input = ""): string { return input.replace(/\r\n/g, "\\r\\n").replace(/\n/g, "\\n"); } @@ -300,10 +422,62 @@ export function singleLine(input: string): string { * @param input is the input array to eliminate duplicates from. * @returns the array with unique values. */ -export function uniqueArray(input: T[]): T[] { +export function uniqueArray(input?: T[]): T[] { return [...new Set(input)]; } +/** + * Returns an attribute of each objects as a CSV (comma separated values) + * + * @param objects are the array of objects to get attribute of. + * @param attribute is the attribute to get for each object. + * @param options are the options. + * @param options.quote is whether to add quotes around attributes. + * @param options.join is the character to join list. + * @param options.wrap is the characters to wrap the list if length is greater than 1. + * @returns the list as a string. + * + * @example + * const objects = [{ name: "a" }, { name: "b" }, { name: "c" }] + * + * listAttribute(objects, "name"); // a, b, c + * listAttribute(objects, "name", { quote: "json" }); // "a", "b", "c" + * listAttribute(objects, "name", { quote: "single" }); // 'a', 'b', 'c' + * listAttribute(objects, "name", { quote: "json", wrap: "[]" }); // ["a", "b", "c"] + * listAttribute(objects, "name", { quote: "json", wrap: "[]" }); // "a" + */ +export function listAttribute( + objects: T[], + attribute: keyof T = "name" as any, + options: { quote?: "single" | "double" | "json"; join?: string; wrap?: string } = {} +): string { + const quoters: Record = { single: singleQuote, double: doubleQuote, json: JSON.stringify }; + const quoter = quoters[options.quote as string]; + const list = objects.map((o) => (quoter ? quoter(o[attribute] as any) : o[attribute])).join(options.join ?? ", "); + return options.wrap ? wrapIf(list, objects.length > 1, options.wrap) : list; +} + +/** + * Word wraps given text. + * + * @param input is the text to word wrap. + * @param startOrStop is the start or the stop position of each line. (The stop position if this is single option.) + * @param stop is the stop position of each line. + * @return word wrapped text. + * + * @example + * wordWrap("The quick fox", 10); // "The quick\nfox" + * wordWrap("The quick fox", 2, 10); // " The quick\n fox" + */ +export function wordWrap(input?: string, startOrStop = 80, stop?: number): string { + if (input === undefined) return ""; + return wordWrapper(startOrStop, stop as any)(input); +} + +export function concat(input: Record, ...objects: Record[]): Record { + return input.concat(...objects); +} + // // ──────────────────────────────────────────────────────────────────────── I ────────── // :::::: D A T A B A S E F I L T E R S : : : : : : : : @@ -316,7 +490,8 @@ export function uniqueArray(input: T[]): T[] { * @param object is the object to get the name as a class name. * @param schema is whether to include schema name. */ -export function dboClassName(object: DbObject, schema = false): string { +export function dboClassName(object?: DbObject, schema = false): string { + if (object === undefined) return ""; return classCase(schema ? object.fullName.replace(".", "_") : object.name); } @@ -330,7 +505,8 @@ export function dboClassName(object: DbObject, schema = false): string { * columnTypeModifier(price); // (10,4) * columnTypeModifier(name); // (20) */ -export function dboColumnTypeModifier(column: Column): string { +export function dboColumnTypeModifier(column?: Column): string { + if (column === undefined) return ""; if (column.length !== undefined) return `(${column.length})`; const result = []; if (column.precision !== undefined) result.push(column.precision); diff --git a/src/utils/get-class-name.ts b/src/utils/get-class-name.ts deleted file mode 100644 index f34887a..0000000 --- a/src/utils/get-class-name.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { sep } from "path"; -import { Db, Schema } from "pg-structure"; -import { classCase, plural, camelCase } from "./filter-functions"; - -/** - * Returns the pg-structure class name and the accessor to access all instances of the class in a schema to be used in the context - * for given template path. - * - * @param db is the `pg-structure` `Db` instance. - * @param templatePath is the template path to get the class name and the accessor. - * @throws Error if there is no array-returning accessor in the Schema for given path. - * - * @example - * getClassName(db, "table/{name}.js.njk"); // { className: "Table", accessor: "tables" }; - */ -export function getClassName(db: Db, templatePath: string): { className: string; accessor: keyof Schema } { - const sepIndex = templatePath.indexOf(sep); - const className = classCase(templatePath.substring(0, sepIndex)); - if (className === "Db") return { className: "Db", accessor: "db" }; - const accessor = plural(camelCase(className)) as keyof Schema; - if (!Array.isArray(db.schemas[0][accessor])) throw new Error(`${className} is not a database object type: ${templatePath}`); - return { className, accessor }; -} diff --git a/src/utils/get-db-objects.ts b/src/utils/get-db-objects.ts index 1a89331..90c189e 100644 --- a/src/utils/get-db-objects.ts +++ b/src/utils/get-db-objects.ts @@ -1,17 +1,23 @@ -import { DbObject, Db } from "pg-structure"; -import { getClassName } from "./get-class-name"; +import { DbObject, Db, Schema } from "pg-structure"; +import { PgenError } from "./pgen-error"; + +const isSchemaAttribute = (db: Db, accessor: any): accessor is keyof Schema => Array.isArray(db.schemas[0][accessor as keyof Schema]); +const isDbAttribute = (db: Db, accessor: any): accessor is keyof Db => Array.isArray(db[accessor as keyof Db]); /** - * Gets all database objects from all schemas to be used as context for the given template path. + * Gets all database objects from all schemas to be used as context for the given className and accessor. * * @param db is the `pg-structure` `Db` instance. + * @param className is the pg-structure class name to return instances of. + * @param accessor is the pg-structure accessor name to access database objects collection. * @param templatePath is the template path to get database objects for. * * @example - * getDbObjects(db, "table/{name}.js.njk"); // Table[]; + * getDbObjects(db, "table", "tables", "x/y/[table]{name}.js.njk"); // Table[]; */ -export function getDbObjects(db: Db, templatePath: string): Array { - const { className, accessor } = getClassName(db, templatePath); +export function getDbObjects(db: Db, className: string, accessor: string, templatePath: string): Array { if (className === "Db") return [db]; - return db.schemas.flatMap((schema) => schema[accessor] as DbObject[]); + if (isSchemaAttribute(db, accessor)) return db.schemas.flatMap((schema) => schema[accessor] as DbObject[]); + if (isDbAttribute(db, accessor)) return db[accessor] as DbObject[]; + throw new PgenError(`${className} is not a known database object type: ${templatePath}`); } diff --git a/src/utils/get-template-paths.ts b/src/utils/get-template-paths.ts deleted file mode 100644 index 2c280d0..0000000 --- a/src/utils/get-template-paths.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { relative, basename } from "path"; -import { fdir as Fdir } from "fdir"; -import junk from "junk"; - -/** - * Scans the template directory recursively and gets all template file paths. - * - * @param templateRoot is the root directory of the templates. - * @returns all template files. - */ -export async function getTemplatePaths(templateRoot: string): Promise { - const pathsWithBase = (await new Fdir() - .exclude((dirname) => ["files", "partials"].includes(dirname)) - .withBasePath() - .crawl(templateRoot) - .withPromise()) as string[]; - - // Convert to relative paths and filter junk files such as `.DS_Store` and `Thumbs.db` - return pathsWithBase.map((path) => relative(templateRoot, path)).filter((path) => junk.not(basename(path))); -} diff --git a/src/utils/index.ts b/src/utils/index.ts index 1e5ea41..1191ee5 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,8 +1,9 @@ export * from "./augment-context"; export * from "./compose-with"; export * from "./filter-functions"; -export * from "./get-class-name"; export * from "./get-db-objects"; export * from "./get-db"; -export * from "./get-template-paths"; +export * from "./parse-template-path"; +export * from "./pgen-error"; export * from "./resolve-path"; +export * from "./scan-template-dir"; diff --git a/src/utils/parse-template-path.ts b/src/utils/parse-template-path.ts new file mode 100644 index 0000000..c39b46e --- /dev/null +++ b/src/utils/parse-template-path.ts @@ -0,0 +1,21 @@ +import { basename, join, dirname } from "path"; +import { PgenError } from "./pgen-error"; +import { classCase, plural, camelCase } from "./filter-functions"; + +/** + * Parses given template path and returns pg-structure class name, accessor name to get collection of instances + * and target path for the given template path. Allows an optional single space after type. + * + * @param templatePath is the template path to get the class name and the accessor. + * @throws if template path does not contain a class type. + * + * @example + * getClassName("x/y/[table]{name}.js.njk"); // { className: "Table", accessor: "tables", targetPath: "x/y/{name}.js.njk" }; + * getClassName("x/y/[table] {name}.js.njk"); // { className: "Table", accessor: "tables", targetPath: "x/y/{name}.js.njk" }; + */ +export function parseTemplatePath(templatePath: string): { className: string; accessor: string; targetPath: string } { + // Capture characters between "[]" at the beginning and rest of the string. x/y/[table]{name}.js.njk -> ["[table]", "table", "{name}.js.njk"] + const found = basename(templatePath).match(/^\[([-\w]+?)\] ?(.+)$/); + if (!found) throw new PgenError("Template error. Template path does not contain a type."); + return { className: classCase(found[1]), accessor: plural(camelCase(found[1])), targetPath: join(dirname(templatePath), found[2]) }; +} diff --git a/src/utils/pgen-error.ts b/src/utils/pgen-error.ts index 571003a..5d22f08 100644 --- a/src/utils/pgen-error.ts +++ b/src/utils/pgen-error.ts @@ -1,5 +1,7 @@ /* eslint-disable @typescript-eslint/explicit-function-return-type */ -type ErrorCode = "NOGEN" | "NOSUB" | "NOTAGEN" | "NOEXP"; +import { EOL } from "os"; +import { inspect } from "util"; +import type { CollisionsByTable } from "pg-structure"; const messages: Record string> = { NOGEN: (n = "") => `You don't seem to have a generator with the name '${n}' installed.`, @@ -8,12 +10,34 @@ const messages: Record string> = { NOEXP: (n = "") => `${n} exists, but does not have any sub-generators.`, }; +type ErrorCode = keyof typeof messages | "RELCOL" | "GENERAL"; + export class PgenError extends Error { public code: ErrorCode; public subGenerators?: string[]; - public constructor(code: ErrorCode, name: string, subGenerator?: string, subGenerators?: string[]) { - super(messages[code](name, subGenerator === "" || subGenerator === undefined ? "index.js or app" : subGenerator)); - this.code = code; - this.subGenerators = subGenerators; + + public constructor(message: string) { + super(message); + this.code = "GENERAL"; + } + + public static withCode(code: ErrorCode, message: string): PgenError { + const error = new PgenError(message); + error.code = code; + return error; + } + + public static collisionError(reportObject: CollisionsByTable): PgenError { + const report = inspect(reportObject, { depth: null }); + const message = `Some relations have same names. Use '{ relationNameFunctions: "descriptive" }' option or proivde your own naming functions.${EOL}${report}`; + const error = this.withCode("RELCOL", message); + return error; + } + + public static composerError(code: ErrorCode, id: string, subGenerator?: string, subGenerators?: string[]): PgenError { + const message = messages[code](id, subGenerator === "" || subGenerator === undefined ? "index.js or app" : subGenerator); + const error = this.withCode(code, message); + error.subGenerators = subGenerators; + return error; } } diff --git a/src/utils/resolve-path.ts b/src/utils/resolve-path.ts index 09d79ed..466feb1 100644 --- a/src/utils/resolve-path.ts +++ b/src/utils/resolve-path.ts @@ -1,6 +1,7 @@ -import { sep, extname } from "path"; +import { extname } from "path"; import type { Db, DbObject } from "pg-structure"; import get from "lodash.get"; +import { PgenError } from "./pgen-error"; import * as filterFunctions from "./filter-functions"; type LowerCaseName = string; @@ -27,7 +28,7 @@ Object.entries(filterFunctions).forEach(([name, fn]) => (LC_FILTER_FUNCTIONS[nam */ function applyFilter(input: string, filterName: string, templatePath: string): string { const filterFunction = LC_FILTER_FUNCTIONS[filterFunctions.camelCase(filterName).toLowerCase()]; - if (!filterFunction) throw new Error(`There is no '${filterName}' filter: ${templatePath}`); + if (!filterFunction) throw new PgenError(`There is no '${filterName}' filter: ${templatePath}`); return filterFunction(input); } @@ -57,21 +58,35 @@ function applyFilters(input: string, filterNames: string[], templatePath: string * * @hidden * @example - * resolvePath("table/my-{schema.name}{name#dash-case#plural}.js.njk", table); // my-public-member-options.js + * resolvePath("x/y/my-{schema.name}{name#dash-case#plural}.js.njk", table); // x/y/my-public-member-options.js */ export function resolvePath(path: string, dbObject: Db | DbObject): string { - const pattern = /\{(.+?)\}/g; // Match text between curly braces e.g. 'table/{name#dash-case}' captures 'name#dash-case'. - const sepIndex = path.indexOf(sep); // get first '/' position. + const pattern = /\{\s*(.+?)\s*\}/g; // Match text between curly braces e.g. 'table/{name#dash-case}' captures 'name#dash-case'. return path - .substring(sepIndex + 1) // remove db object part: "table/{name#dash-case}.js.njk" -> "{name#dash-case}.js.njk" .replace(extname(path), "") // remove extension: "{name#dash-case}.js.njk" -> "{name#dash-case}.js" .replace(pattern, (_, p) => { // resolve variables: "{name#dash-case}.js" -> "member-option.js" const [templateVar, ...filterNames] = p.split(/\s*#\s*/); const value = get(dbObject, templateVar); if (value === undefined || value === null) - throw new Error(`'${templateVar}' cannot be found or is undefined in '${dbObject.constructor.name}'. Path is '${path}'.`); + throw new PgenError(`'${templateVar}' cannot be found or is undefined in '${dbObject.constructor.name}'. Path is '${path}'.`); return applyFilters(value, filterNames, path); }); } +// export function resolvePath(path: string, dbObject: Db | DbObject): string { +// const pattern = /\{\s*(.+?)\s*\}/g; // Match text between curly braces e.g. 'table/{name#dash-case}' captures 'name#dash-case'. +// const sepIndex = path.indexOf(sep); // get first '/' position. + +// return path +// .substring(sepIndex + 1) // remove db object part: "table/{name#dash-case}.js.njk" -> "{name#dash-case}.js.njk" +// .replace(extname(path), "") // remove extension: "{name#dash-case}.js.njk" -> "{name#dash-case}.js" +// .replace(pattern, (_, p) => { +// // resolve variables: "{name#dash-case}.js" -> "member-option.js" +// const [templateVar, ...filterNames] = p.split(/\s*#\s*/); +// const value = get(dbObject, templateVar); +// if (value === undefined || value === null) +// throw new PgenError(`'${templateVar}' cannot be found or is undefined in '${dbObject.constructor.name}'. Path is '${path}'.`); +// return applyFilters(value, filterNames, path); +// }); +// } diff --git a/src/utils/scan-template-dir.ts b/src/utils/scan-template-dir.ts new file mode 100644 index 0000000..88f1225 --- /dev/null +++ b/src/utils/scan-template-dir.ts @@ -0,0 +1,28 @@ +import { relative, basename, dirname } from "path"; +import { fdir as Fdir } from "fdir"; +import junk from "junk"; + +/** + * Scans the template directory recursively and gets all template file paths. + * + * @param templateRoot is the root directory of the templates. + * @returns all template files and files to copy. + */ +export async function scanTemplateDir(templateRoot: string): Promise<{ templates: string[]; files: string[] }> { + const filePaths = { templates: [] as string[], files: [] as string[] }; + + // Scan template root and filter partials and junk files such as `.DS_Store` and `Thumbs.db` + const pathsWithBase = (await new Fdir() + .filter((path) => junk.not(basename(path)) && basename(dirname(path)) !== "partials") + .withBasePath() + .crawl(templateRoot) + .withPromise()) as string[]; + + // Group template files and non-template files and convert to relative files. + pathsWithBase.forEach((path) => { + const type = basename(path).startsWith("[") ? "templates" : "files"; + filePaths[type].push(relative(templateRoot, path)); + }); + + return filePaths; +}