diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 342d15d9f..cae97e586 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -38,6 +38,10 @@ module.exports = { 'lodash', 'unicorn', ], + ignorePatterns: [ + // this file is automatically generated by `pnpm run --filter mermaid types:build-config` + 'packages/mermaid/src/config.type.ts', + ], rules: { curly: 'error', 'no-console': 'error', diff --git a/.prettierignore b/.prettierignore index b50a94e84..6f2d55369 100644 --- a/.prettierignore +++ b/.prettierignore @@ -7,3 +7,5 @@ pnpm-lock.yaml stats packages/mermaid/src/docs/.vitepress/components.d.ts .nyc_output +# Autogenerated by `pnpm run --filter mermaid types:build-config` +packages/mermaid/src/config.type.ts diff --git a/packages/mermaid/.lintstagedrc.mjs b/packages/mermaid/.lintstagedrc.mjs index fe79ad254..955000e20 100644 --- a/packages/mermaid/.lintstagedrc.mjs +++ b/packages/mermaid/.lintstagedrc.mjs @@ -4,4 +4,5 @@ export default { 'src/docs/**': ['pnpm --filter mermaid run docs:build --git'], 'src/docs.mts': ['pnpm --filter mermaid run docs:build --git'], 'src/(defaultConfig|config|mermaidAPI).ts': ['pnpm --filter mermaid run docs:build --git'], + 'src/schemas/config.schema.yaml': ['pnpm --filter mermaid run types:build-config --git'], }; diff --git a/packages/mermaid/package.json b/packages/mermaid/package.json index cd193f8a5..66bac897f 100644 --- a/packages/mermaid/package.json +++ b/packages/mermaid/package.json @@ -32,6 +32,8 @@ "docs:dev": "pnpm docs:pre:vitepress && concurrently \"pnpm --filter ./src/vitepress dev\" \"ts-node-esm src/docs.mts --watch --vitepress\"", "docs:serve": "pnpm docs:build:vitepress && vitepress serve src/vitepress", "docs:spellcheck": "cspell --config ../../cSpell.json \"src/docs/**/*.md\"", + "types:build-config": "ts-node-esm --transpileOnly scripts/create-types-from-json-schema.mts", + "types:verify-config": "ts-node-esm scripts/create-types-from-json-schema.mts --verify", "release": "pnpm build", "prepublishOnly": "cpy '../../README.*' ./ --cwd=. && pnpm -w run build" }, @@ -88,6 +90,7 @@ "@types/uuid": "^9.0.1", "@typescript-eslint/eslint-plugin": "^5.59.0", "@typescript-eslint/parser": "^5.59.0", + "ajv": "^8.11.2", "chokidar": "^3.5.3", "concurrently": "^8.0.1", "coveralls": "^3.1.1", @@ -98,6 +101,7 @@ "jison": "^0.4.18", "js-base64": "^3.7.5", "jsdom": "^22.0.0", + "json-schema-to-typescript": "^11.0.3", "micromatch": "^4.0.5", "path-browserify": "^1.0.1", "prettier": "^2.8.8", diff --git a/packages/mermaid/scripts/create-types-from-json-schema.mts b/packages/mermaid/scripts/create-types-from-json-schema.mts new file mode 100644 index 000000000..e81ea70ff --- /dev/null +++ b/packages/mermaid/scripts/create-types-from-json-schema.mts @@ -0,0 +1,252 @@ +/** + * Script to load Mermaid Config JSON Schema from YAML and to: + * + * - Validate JSON Schema + * + * Then to generate: + * + * - config.types.ts TypeScript file + */ + +/* eslint-disable no-console */ + +import { readFile, writeFile } from 'node:fs/promises'; +import { join } from 'node:path'; +import assert from 'node:assert'; +import { execFile } from 'node:child_process'; +import { promisify } from 'node:util'; + +import { load, JSON_SCHEMA } from 'js-yaml'; +import { compile, type JSONSchema } from 'json-schema-to-typescript'; + +import _Ajv2019, { type JSONSchemaType } from 'ajv/dist/2019.js'; + +// Workaround for wrong AJV types, see +// https://github.com/ajv-validator/ajv/issues/2132#issuecomment-1290409907 +const Ajv2019 = _Ajv2019 as unknown as typeof _Ajv2019.default; + +// !!! -- The config.type.js file is created by this script -- !!! +import type { MermaidConfig } from '../src/config.type.js'; + +// options for running the main command +const verifyOnly = process.argv.includes('--verify'); +/** If `true`, automatically `git add` any changes (i.e. during `pnpm run pre-commit`)*/ +const git = process.argv.includes('--git'); + +/** + * All of the keys in the mermaid config that have a mermaid diagram config. + */ +const MERMAID_CONFIG_DIAGRAM_KEYS = [ + 'flowchart', + 'sequence', + 'gantt', + 'journey', + 'class', + 'state', + 'er', + 'pie', + 'quadrantChart', + 'requirement', + 'mindmap', + 'timeline', + 'gitGraph', + 'c4', + 'sankey', +]; + +/** + * Loads the MermaidConfig JSON schema YAML file. + * + * @returns The loaded JSON Schema, use {@link validateSchema} to confirm it is a valid JSON Schema. + */ +async function loadJsonSchemaFromYaml() { + const configSchemaFile = join('src', 'schemas', 'config.schema.yaml'); + const contentsYaml = await readFile(configSchemaFile, { encoding: 'utf8' }); + const jsonSchema = load(contentsYaml, { + filename: configSchemaFile, + // only allow JSON types in our YAML doc (will probably be default in YAML 1.3) + // e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`. + schema: JSON_SCHEMA, + }); + return jsonSchema; +} + +/** + * Asserts that the given value is a valid JSON Schema object. + * + * @param jsonSchema - The value to validate as JSON Schema 2019-09 + * @throws {Error} if the given object is invalid. + */ +function validateSchema(jsonSchema: unknown): asserts jsonSchema is JSONSchemaType { + if (typeof jsonSchema !== 'object') { + throw new Error(`jsonSchema param is not an object: actual type is ${typeof jsonSchema}`); + } + if (jsonSchema === null) { + throw new Error('jsonSchema param must not be null'); + } + const ajv = new Ajv2019({ + allErrors: true, + allowUnionTypes: true, + strict: true, + }); + + ajv.addKeyword({ + keyword: 'meta:enum', // used by jsonschema2md (in docs.mts script) + errors: false, + }); + ajv.addKeyword({ + keyword: 'tsType', // used by json-schema-to-typescript + errors: false, + }); + + ajv.compile(jsonSchema); +} + +/** + * Generate a typescript definition from a JSON Schema using json-schema-to-typescript. + * + * @param mermaidConfigSchema - The input JSON Schema. + */ +async function generateTypescript(mermaidConfigSchema: JSONSchemaType) { + /** + * Replace all usages of `allOf` with `extends`. + * + * `extends` is only valid JSON Schema in very old versions of JSON Schema. + * However, json-schema-to-typescript creates much nicer types when using + * `extends`, so we should use them instead when possible. + * + * @param schema - The input schema. + * @returns The schema with `allOf` replaced with `extends`. + */ + function replaceAllOfWithExtends(schema: JSONSchemaType>) { + if (schema['allOf']) { + const { allOf, ...schemaWithoutAllOf } = schema; + return { + ...schemaWithoutAllOf, + extends: allOf, + }; + } + return schema; + } + + /** + * For backwards compatibility with older Mermaid Typescript defs, + * we need to make all value optional instead of required. + * + * This is because the `MermaidConfig` type is used as an input, and everything is optional, + * since all the required values have default values.s + * + * In the future, we should make make the input to Mermaid `Partial`. + * + * @todo TODO: Remove this function when Mermaid releases a new breaking change. + * @param schema - The input schema. + * @returns The schema with all required values removed. + */ + function removeRequired(schema: JSONSchemaType>) { + return { ...schema, required: [] }; + } + + /** + * This is a temporary hack to control the order the types are generated in. + * + * By default, json-schema-to-typescript outputs the $defs in the order they + * are used, then any unused schemas at the end. + * + * **The only purpose of this function is to make the `git diff` simpler** + * **We should remove this later to simplify the code** + * + * @todo TODO: Remove this function in a future PR. + * @param schema - The input schema. + * @returns The schema with all `$ref`s removed. + */ + function unrefSubschemas(schema: JSONSchemaType>) { + return { + ...schema, + properties: Object.fromEntries( + Object.entries(schema.properties).map(([key, propertySchema]) => { + if (MERMAID_CONFIG_DIAGRAM_KEYS.includes(key)) { + const { $ref, ...propertySchemaWithoutRef } = propertySchema as JSONSchemaType; + if ($ref === undefined) { + throw Error( + `subSchema ${key} is in MERMAID_CONFIG_DIAGRAM_KEYS but does not have a $ref field` + ); + } + const [ + _root, // eslint-disable-line @typescript-eslint/no-unused-vars + _defs, // eslint-disable-line @typescript-eslint/no-unused-vars + defName, + ] = $ref.split('/'); + return [ + key, + { + ...propertySchemaWithoutRef, + tsType: defName, + }, + ]; + } + return [key, propertySchema]; + }) + ), + }; + } + + assert.ok(mermaidConfigSchema.$defs); + const modifiedSchema = { + ...unrefSubschemas(removeRequired(mermaidConfigSchema)), + + $defs: Object.fromEntries( + Object.entries(mermaidConfigSchema.$defs).map(([key, subSchema]) => { + return [key, removeRequired(replaceAllOfWithExtends(subSchema))]; + }) + ), + }; + + const typescriptFile = await compile( + modifiedSchema as JSONSchema, // json-schema-to-typescript only allows JSON Schema 4 as input type + 'MermaidConfig', + { + additionalProperties: false, // in JSON Schema 2019-09, these are called `unevaluatedProperties` + unreachableDefinitions: true, // definition for FontConfig is unreachable + } + ); + + // TODO, should we somehow use the functions from `docs.mts` instead? + if (verifyOnly) { + const originalFile = await readFile('./src/config.type.ts', { encoding: 'utf-8' }); + if (typescriptFile !== originalFile) { + console.error('❌ Error: ./src/config.type.ts will be changed.'); + console.error("Please run 'pnpm run --filter mermaid types:build-config' to update this"); + process.exitCode = 1; + } else { + console.log('✅ ./src/config.type.ts will be unchanged'); + } + } else { + console.log('Writing typescript file to ./src/config.type.ts'); + await writeFile('./src/config.type.ts', typescriptFile, { encoding: 'utf8' }); + if (git) { + console.log('📧 Git: Adding ./src/config.type.ts changed'); + await promisify(execFile)('git', ['add', './src/config.type.ts']); + } + } +} + +/** Main function */ +async function main() { + if (verifyOnly) { + console.log( + 'Verifying that ./src/config.type.ts is in sync with src/schemas/config.schema.yaml' + ); + } + + const configJsonSchema = await loadJsonSchemaFromYaml(); + + validateSchema(configJsonSchema); + + // Generate types from JSON Schema + await generateTypescript(configJsonSchema); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fad43866e..303985a31 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -297,6 +297,9 @@ importers: '@typescript-eslint/parser': specifier: ^5.59.0 version: 5.59.0(eslint@8.39.0)(typescript@5.0.4) + ajv: + specifier: ^8.11.2 + version: 8.12.0 chokidar: specifier: ^3.5.3 version: 3.5.3 @@ -327,6 +330,9 @@ importers: jsdom: specifier: ^22.0.0 version: 22.0.0 + json-schema-to-typescript: + specifier: ^11.0.3 + version: 11.0.3 micromatch: specifier: ^4.0.5 version: 4.0.5 @@ -2258,6 +2264,15 @@ packages: '@babel/helper-validator-identifier': 7.19.1 to-fast-properties: 2.0.0 + /@bcherny/json-schema-ref-parser@9.0.9: + resolution: {integrity: sha512-vmEmnJCfpkLdas++9OYg6riIezTYqTHpqUTODJzHLzs5UnXujbOJW9VwcVCnyo1mVRt32FRr23iXBx/sX8YbeQ==} + dependencies: + '@jsdevtools/ono': 7.1.3 + '@types/json-schema': 7.0.11 + call-me-maybe: 1.0.2 + js-yaml: 4.1.0 + dev: true + /@bcoe/v8-coverage@0.2.3: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} dev: true @@ -3857,6 +3872,10 @@ packages: '@jridgewell/resolve-uri': 3.1.0 '@jridgewell/sourcemap-codec': 1.4.14 + /@jsdevtools/ono@7.1.3: + resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} + dev: true + /@leichtgewicht/ip-codec@2.0.4: resolution: {integrity: sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==} dev: true @@ -4437,6 +4456,13 @@ packages: resolution: {integrity: sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==} dev: true + /@types/glob@7.2.0: + resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} + dependencies: + '@types/minimatch': 5.1.2 + '@types/node': 18.16.0 + dev: true + /@types/graceful-fs@4.1.5: resolution: {integrity: sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==} dependencies: @@ -4537,6 +4563,10 @@ packages: resolution: {integrity: sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==} dev: true + /@types/minimatch@5.1.2: + resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} + dev: true + /@types/minimist@1.2.2: resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} dev: true @@ -6004,7 +6034,6 @@ packages: /any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - dev: false /anymatch@3.1.2: resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} @@ -6525,6 +6554,10 @@ packages: get-intrinsic: 1.2.0 dev: true + /call-me-maybe@1.0.2: + resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==} + dev: true + /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -6752,6 +6785,17 @@ packages: engines: {node: '>=6'} dev: true + /cli-color@2.0.3: + resolution: {integrity: sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ==} + engines: {node: '>=0.10'} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + es6-iterator: 2.0.3 + memoizee: 0.4.15 + timers-ext: 0.1.7 + dev: true + /cli-cursor@3.1.0: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} engines: {node: '>=8'} @@ -7730,6 +7774,13 @@ packages: d3-zoom: 3.0.0 dev: false + /d@1.0.1: + resolution: {integrity: sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==} + dependencies: + es5-ext: 0.10.62 + type: 1.2.0 + dev: true + /dagre-d3-es@7.0.10: resolution: {integrity: sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A==} dependencies: @@ -8243,10 +8294,44 @@ packages: engines: {node: '>= 4.0.0'} dev: true + /es5-ext@0.10.62: + resolution: {integrity: sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==} + engines: {node: '>=0.10'} + requiresBuild: true + dependencies: + es6-iterator: 2.0.3 + es6-symbol: 3.1.3 + next-tick: 1.1.0 + dev: true + /es6-error@4.1.1: resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==} dev: true + /es6-iterator@2.0.3: + resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + es6-symbol: 3.1.3 + dev: true + + /es6-symbol@3.1.3: + resolution: {integrity: sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==} + dependencies: + d: 1.0.1 + ext: 1.7.0 + dev: true + + /es6-weak-map@2.0.3: + resolution: {integrity: sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + es6-iterator: 2.0.3 + es6-symbol: 3.1.3 + dev: true + /esbuild@0.17.18: resolution: {integrity: sha512-z1lix43jBs6UKjcZVKOw2xx69ffE2aG0PygLL5qJ9OS/gy0Ewd1gW/PUQIOIQGXBHWNywSc0floSKoMFF8aK2w==} engines: {node: '>=12'} @@ -8671,6 +8756,13 @@ packages: engines: {node: '>= 0.6'} dev: true + /event-emitter@0.3.5: + resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + dev: true + /event-stream@3.3.4: resolution: {integrity: sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==} dependencies: @@ -8819,6 +8911,12 @@ packages: - supports-color dev: true + /ext@1.7.0: + resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} + dependencies: + type: 2.7.2 + dev: true + /extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} dev: true @@ -9375,6 +9473,16 @@ packages: dependencies: is-glob: 4.0.3 + /glob-promise@4.2.2(glob@7.2.3): + resolution: {integrity: sha512-xcUzJ8NWN5bktoTIX7eOclO1Npxd/dyVqUJxlLIDasT4C7KZyqlPIwkdJ0Ypiy3p2ZKahTjK4M9uC3sNSfNMzw==} + engines: {node: '>=12'} + peerDependencies: + glob: ^7.1.6 + dependencies: + '@types/glob': 7.2.0 + glob: 7.2.3 + dev: true + /glob-to-regexp@0.4.1: resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} dev: true @@ -10164,6 +10272,10 @@ packages: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} dev: true + /is-promise@2.2.2: + resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} + dev: true + /is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} @@ -10993,6 +11105,27 @@ packages: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} dev: true + /json-schema-to-typescript@11.0.3: + resolution: {integrity: sha512-EaEE9Y4VZ8b9jW5zce5a9L3+p4C9AqgIRHbNVDJahfMnoKzcd4sDb98BLxLdQhJEuRAXyKLg4H66NKm80W8ilg==} + engines: {node: '>=12.0.0'} + hasBin: true + dependencies: + '@bcherny/json-schema-ref-parser': 9.0.9 + '@types/json-schema': 7.0.11 + '@types/lodash': 4.14.194 + '@types/prettier': 2.7.2 + cli-color: 2.0.3 + get-stdin: 8.0.0 + glob: 7.2.3 + glob-promise: 4.2.2(glob@7.2.3) + is-glob: 4.0.3 + lodash: 4.17.21 + minimist: 1.2.8 + mkdirp: 1.0.4 + mz: 2.7.0 + prettier: 2.8.8 + dev: true + /json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} dev: true @@ -11401,6 +11534,12 @@ packages: engines: {node: 14 || >=16.14} dev: true + /lru-queue@0.1.0: + resolution: {integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==} + dependencies: + es5-ext: 0.10.62 + dev: true + /lunr@2.3.9: resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} dev: true @@ -11629,6 +11768,19 @@ packages: fs-monkey: 1.0.3 dev: true + /memoizee@0.4.15: + resolution: {integrity: sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + es6-weak-map: 2.0.3 + event-emitter: 0.3.5 + is-promise: 2.2.2 + lru-queue: 0.1.0 + next-tick: 1.1.0 + timers-ext: 0.1.7 + dev: true + /meow@10.1.5: resolution: {integrity: sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -12043,6 +12195,12 @@ packages: minimist: 1.2.8 dev: true + /mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + dev: true + /mlly@1.2.0: resolution: {integrity: sha512-+c7A3CV0KGdKcylsI6khWyts/CYrGTrRVo4R/I7u/cUsy0Conxa6LUhiEzVKIw14lc2L5aiO4+SeVe4TeGRKww==} dependencies: @@ -12086,7 +12244,6 @@ packages: any-promise: 1.3.0 object-assign: 4.1.1 thenify-all: 1.6.0 - dev: false /nanoid@3.3.6: resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} @@ -12114,6 +12271,10 @@ packages: resolution: {integrity: sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==} dev: true + /next-tick@1.1.0: + resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} + dev: true + /nice-try@1.0.5: resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} dev: true @@ -14491,13 +14652,11 @@ packages: engines: {node: '>=0.8'} dependencies: thenify: 3.3.1 - dev: false /thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} dependencies: any-promise: 1.3.0 - dev: false /thread-stream@2.3.0: resolution: {integrity: sha512-kaDqm1DET9pp3NXwR8382WHbnpXnRkN9xGN9dQt3B2+dmXiW8X1SOwmFOxAErEQ47ObhZ96J6yhZNXuyCOL7KA==} @@ -14536,6 +14695,13 @@ packages: engines: {node: '>=4'} dev: true + /timers-ext@0.1.7: + resolution: {integrity: sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==} + dependencies: + es5-ext: 0.10.62 + next-tick: 1.1.0 + dev: true + /tiny-glob@0.2.9: resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} dependencies: @@ -14812,6 +14978,14 @@ packages: mime-types: 2.1.35 dev: true + /type@1.2.0: + resolution: {integrity: sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==} + dev: true + + /type@2.7.2: + resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==} + dev: true + /typed-array-length@1.0.4: resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} dependencies: