diff --git a/.gitignore b/.gitignore index d0e387936b6..68310b137ca 100644 --- a/.gitignore +++ b/.gitignore @@ -5,9 +5,9 @@ packages/web-features/index.d.ts packages/**/LICENSE.txt packages/web-features/data.json packages/web-features/data.schema.json -packages/web-features/types.ts +packages/web-features/types* +packages/web-features/index.js data.extended.json -index.js # Ignore files created & used by pages & 11ty /_site/** diff --git a/.prettierignore b/.prettierignore index 743a54d17e2..eb97a6eba00 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,7 +2,6 @@ /**/*.dist /**/dist - # Exclude the website includes since these are typically fragments, or include # things that makes Prettier unhappy. /gh-pages/src/_includes/** @@ -11,14 +10,12 @@ # TODO: Format all these files README.md index.ts -types.ts 2022-backgrounder.md towards-features.md /.github/** /docs !/docs/publishing.md /features/draft -/schemas /scripts/caniuse.ts /scripts/schema.ts /scripts/specs.ts diff --git a/assertions.test.ts b/assertions.test.ts new file mode 100644 index 00000000000..2ff81193779 --- /dev/null +++ b/assertions.test.ts @@ -0,0 +1,36 @@ +import assert from "node:assert/strict"; +import { assertValidFeatureReference } from "./assertions"; + +describe("assertValidReference()", function () { + it("throws if target ID is a move", function () { + assert.throws(() => { + assertValidFeatureReference("a", "some-moving-feature", { + "some-moving-feature": { kind: "moved" }, + }); + }); + }); + + it("throws if target ID is a split", function () { + assert.throws(() => { + assertValidFeatureReference("a", "some-split-feature", { + "some-split-feature": { kind: "split" }, + }); + }); + }); + + it("throws if target ID is not defined", function () { + assert.throws(() => { + assertValidFeatureReference( + "a", + "this-is-a-completely-invalid-feature", + {}, + ); + }); + }); + + it("does not throw if target ID is a feature", function () { + assert.doesNotThrow(() => { + assertValidFeatureReference("a", "dom", { dom: { kind: "feature" } }); + }); + }); +}); diff --git a/assertions.ts b/assertions.ts new file mode 100644 index 00000000000..90d7a546f16 --- /dev/null +++ b/assertions.ts @@ -0,0 +1,29 @@ +import { isOrdinaryFeatureData } from "./type-guards"; +import { WebFeaturesData } from "./types.quicktype"; + +/** + * Assert that a reference from one feature to another is an ordinary feature + * reference (i.e., it's defined and not some kind of redirect). + * + * @export + * @param {string} sourceId The feature that is referencing another feature + * @param {string} targetId The feature being referenced + * @param {WebFeaturesData["features"]} features Feature data + */ +export function assertValidFeatureReference( + sourceId: string, + targetId: string, + features: WebFeaturesData["features"], +) { + const target: unknown = features[targetId]; + if (target === undefined) { + throw new Error(`${sourceId} references a non-existent feature`); + } + if (!isOrdinaryFeatureData(target)) { + throw new Error( + `${sourceId} references a redirect "${targetId} instead of an ordinary feature ID`, + ); + } +} + +// TODO: assertValidSnapshotReference diff --git a/docs/guidelines.md b/docs/guidelines.md index 181feb12705..fae24d70be0 100644 --- a/docs/guidelines.md +++ b/docs/guidelines.md @@ -77,6 +77,81 @@ The identifier should match the name, with these additional guidelines: - 👍 Recommended: `user-pseudos` - 👎 Not recommended: `user-valid-and-user-invalid` +### Move a feature to a new ID + +It’s possible to change or substitute a feature’s ID by creating a redirect from the original ID pointing to a new ID. +You can do this when: + +* The original feature ID is misspelled. + For example, `numeric-seperators` (note spelling) data can be moved to `numeric-separators`. + +* The original feature ID breaks the identifier guidelines. + For example, `drones-initial-support` data can be moved to `drones`. + +* The original feature should not have existed as an independent feature. + For example, `single-color-gradients` was a poorly-conceived feature, where [a specification change](https://github.com/w3c/csswg-drafts/issues/10092) simplified the specification, implementation, and tools, but produced no novel browser behavior that developers could use in an application. + Instead, all the compatibility keys for the feature were reassigned to `gradients`. + +* Data consumers report that the original feature ID is confusing or misleading. + +You must not do this when the feature has been superseded, such that the feature's name has changed and the exposed behaviors or API surface have changed (in shipping browsers, up to and including unshipping). +Instead, use [`discouraged` data](#discouraged) with one or more `alternatives`. + +To move the feature: + +1. If applicable, move the existing YAML files for the feature to the target ID filename. + For example, rename `features/numeric-seperators.yml` to `features/numeric-separators.yml`. + + If the original feature is being replaced by another feature, then move on to the next step. + +2. Create a new YAML file for the original target ID filename. + For example, create an empty file `features/numeric-seperators.yml`. + +3. Populate the following data in the new YAML file: + + ```yaml + kind: moved + redirect_target: TARGET-ID + ``` + + where `TARGET-ID` is the target ID. + +4. Regenerate the dist files. + Run `npm run dist`. + +5. Commit your work and open a pull request. + +### Split a feature into two or more other features + +Some features may need to be split in two or more parts. +You can do this when the original feature should not have existed as an independent feature in the first place. +For example, similarly-named compat keys that ought to have been additions to existing features were erroneously combined and assigned to a new feature. + +To split the feature: + +1. If the feature to be split has any keys listed in `compat_features`, then reassign the keys to the target features. + + To get the list of keys, you may need to first run `npm run undist -- $feature` where `$feature` is the path to the YAML file of the feature to be split. + +2. Replace the contents of the original feature YAML file with the following data: + + ```yaml + kind: split + redirect_targets: + - target-id1 + - target-id2 + ``` + + Replace the `target-id` values with two or more target ID strings. + Order `redirect_targets` by the most widely-relevant features first. + For example, if the feature is split to separate a Baseline subset of a feature from a non-Baseline subset, then put the Baseline feature first. + If you must break a tie, use alphabetical order. + +3. Regenerate the dist files. + Run `npm run dist`. + +4. Commit your work and open a pull request. + ## Descriptions The `description` field contains a short description of the feature in Markdown-formatted text, which is converted to HTML in the published package. @@ -345,6 +420,6 @@ When you set a `discouraged` block in a feature file, do: If possible, use the single most broadly applicable reference, such as specification text. If a feature is removed from a specification, link to an issue, pull request, or commit showing the removal. -- Set one or more (optional) `alternative` feature IDs that are whole or partial substitutes for the discouraged feature. +- Set one or more (optional) `alternatives` feature IDs that are whole or partial substitutes for the discouraged feature. An alternative doesn't have to be a narrow drop-in replacement for the discouraged feature but it must handle some use case of the discouraged feature. Guide developers to the most relevant features that would help them stop using the discouraged feature. diff --git a/features/conic-gradients.yml b/features/conic-gradients.yml index 296df0f44ff..bbe65dfd98e 100644 --- a/features/conic-gradients.yml +++ b/features/conic-gradients.yml @@ -8,4 +8,5 @@ status: compat_features: - css.types.gradient.conic-gradient - css.types.gradient.conic-gradient.doubleposition + - css.types.gradient.conic-gradient.single_color_stop - css.types.gradient.repeating-conic-gradient diff --git a/features/conic-gradients.yml.dist b/features/conic-gradients.yml.dist index 9b55cfcd57f..ff1a7cb8638 100644 --- a/features/conic-gradients.yml.dist +++ b/features/conic-gradients.yml.dist @@ -41,3 +41,15 @@ compat_features: # safari: "12.1" # safari_ios: "12.2" - css.types.gradient.conic-gradient.doubleposition + + # baseline: low + # baseline_low_date: 2025-04-04 + # support: + # chrome: "135" + # chrome_android: "135" + # edge: "135" + # firefox: "136" + # firefox_android: "136" + # safari: "18.4" + # safari_ios: "18.4" + - css.types.gradient.conic-gradient.single_color_stop diff --git a/features/gradients.yml b/features/gradients.yml index fe513c4390c..e95ec8fb792 100644 --- a/features/gradients.yml +++ b/features/gradients.yml @@ -16,18 +16,22 @@ compat_features: - css.types.gradient.linear-gradient.interpolation_hints - css.types.gradient.linear-gradient.premultiplied_gradients - css.types.gradient.linear-gradient.to + - css.types.gradient.linear-gradient.single_color_stop - css.types.gradient.linear-gradient.unitless_0_angle - css.types.gradient.repeating-linear-gradient - css.types.gradient.repeating-linear-gradient.doubleposition - css.types.gradient.repeating-linear-gradient.interpolation_hints - css.types.gradient.repeating-linear-gradient.to + - css.types.gradient.repeating-linear-gradient.single_color_stop - css.types.gradient.repeating-linear-gradient.unitless_0_angle - css.types.gradient.radial-gradient - css.types.gradient.radial-gradient.at - css.types.gradient.radial-gradient.doubleposition - css.types.gradient.radial-gradient.interpolation_hints - css.types.gradient.radial-gradient.premultiplied_gradients + - css.types.gradient.radial-gradient.single_color_stop - css.types.gradient.repeating-radial-gradient - css.types.gradient.repeating-radial-gradient.at - css.types.gradient.repeating-radial-gradient.doubleposition - css.types.gradient.repeating-radial-gradient.interpolation_hints + - css.types.gradient.repeating-radial-gradient.single_color_stop diff --git a/features/gradients.yml.dist b/features/gradients.yml.dist index f5ac728b631..625d60b9b77 100644 --- a/features/gradients.yml.dist +++ b/features/gradients.yml.dist @@ -145,3 +145,18 @@ compat_features: # safari_ios: "15" - css.types.gradient.linear-gradient.premultiplied_gradients - css.types.gradient.radial-gradient.premultiplied_gradients + + # baseline: low + # baseline_low_date: 2025-04-04 + # support: + # chrome: "135" + # chrome_android: "135" + # edge: "135" + # firefox: "136" + # firefox_android: "136" + # safari: "18.4" + # safari_ios: "18.4" + - css.types.gradient.linear-gradient.single_color_stop + - css.types.gradient.radial-gradient.single_color_stop + - css.types.gradient.repeating-linear-gradient.single_color_stop + - css.types.gradient.repeating-radial-gradient.single_color_stop diff --git a/features/numeric-separators.yml b/features/numeric-separators.yml new file mode 100644 index 00000000000..85500442056 --- /dev/null +++ b/features/numeric-separators.yml @@ -0,0 +1,6 @@ +name: Numeric separators +description: To improve readability for numeric literals, underscores (`_`) can be used as separators. For example, `1_050.95` is equivalent to `1050.95`. +spec: https://tc39.es/ecma262/multipage/ecmascript-language-lexical-grammar.html#prod-NumericLiteralSeparator +group: javascript +compat_features: + - javascript.grammar.numeric_separators diff --git a/features/numeric-separators.yml.dist b/features/numeric-separators.yml.dist new file mode 100644 index 00000000000..996e1916346 --- /dev/null +++ b/features/numeric-separators.yml.dist @@ -0,0 +1,17 @@ +# Generated from: numeric-separators.yml +# Do not edit this file by hand. Edit the source file instead! + +status: + baseline: high + baseline_low_date: 2020-07-28 + baseline_high_date: 2023-01-28 + support: + chrome: "75" + chrome_android: "75" + edge: "79" + firefox: "70" + firefox_android: "79" + safari: "13" + safari_ios: "13" +compat_features: + - javascript.grammar.numeric_separators diff --git a/features/numeric-seperators.yml b/features/numeric-seperators.yml index 85500442056..04c6806c7fd 100644 --- a/features/numeric-seperators.yml +++ b/features/numeric-seperators.yml @@ -1,6 +1,2 @@ -name: Numeric separators -description: To improve readability for numeric literals, underscores (`_`) can be used as separators. For example, `1_050.95` is equivalent to `1050.95`. -spec: https://tc39.es/ecma262/multipage/ecmascript-language-lexical-grammar.html#prod-NumericLiteralSeparator -group: javascript -compat_features: - - javascript.grammar.numeric_separators +kind: moved +redirect_target: numeric-separators diff --git a/features/numeric-seperators.yml.dist b/features/numeric-seperators.yml.dist index eaa3c384275..9bda2b05ad1 100644 --- a/features/numeric-seperators.yml.dist +++ b/features/numeric-seperators.yml.dist @@ -1,17 +1,6 @@ # Generated from: numeric-seperators.yml -# Do not edit this file by hand. Edit the source file instead! +# This file intentionally left blank. +# Do not edit this file. +# The data for this feature has moved to numeric-separators.yml -status: - baseline: high - baseline_low_date: 2020-07-28 - baseline_high_date: 2023-01-28 - support: - chrome: "75" - chrome_android: "75" - edge: "79" - firefox: "70" - firefox_android: "79" - safari: "13" - safari_ios: "13" -compat_features: - - javascript.grammar.numeric_separators +{} diff --git a/features/single-color-gradients.yml b/features/single-color-gradients.yml index b8e1a4789ba..5d1e93a8ee5 100644 --- a/features/single-color-gradients.yml +++ b/features/single-color-gradients.yml @@ -1,11 +1,4 @@ -name: Single color stop gradients -description: A single color stop can be provided to the `linear-gradient()`, `radial-gradient()`, and `conic-gradient()` CSS functions, and their repeating counterparts, to create a solid color background. -spec: https://drafts.csswg.org/css-images-4/#color-stop-syntax -group: gradients -compat_features: - - css.types.gradient.conic-gradient.single_color_stop - - css.types.gradient.linear-gradient.single_color_stop - - css.types.gradient.radial-gradient.single_color_stop - - css.types.gradient.repeating-conic-gradient.single_color_stop - - css.types.gradient.repeating-linear-gradient.single_color_stop - - css.types.gradient.repeating-radial-gradient.single_color_stop +kind: split +redirect_targets: + - gradients + - conic-gradients diff --git a/features/single-color-gradients.yml.dist b/features/single-color-gradients.yml.dist index 38d174ab005..e7dfa57a3c0 100644 --- a/features/single-color-gradients.yml.dist +++ b/features/single-color-gradients.yml.dist @@ -1,21 +1,8 @@ # Generated from: single-color-gradients.yml -# Do not edit this file by hand. Edit the source file instead! +# This file intentionally left blank. +# Do not edit this file. +# The data for this feature has moved to: +# - gradients.yml +# - conic-gradients.yml -status: - baseline: low - baseline_low_date: 2025-04-04 - support: - chrome: "135" - chrome_android: "135" - edge: "135" - firefox: "136" - firefox_android: "136" - safari: "18.4" - safari_ios: "18.4" -compat_features: - - css.types.gradient.conic-gradient.single_color_stop - - css.types.gradient.linear-gradient.single_color_stop - - css.types.gradient.radial-gradient.single_color_stop - - css.types.gradient.repeating-conic-gradient.single_color_stop - - css.types.gradient.repeating-linear-gradient.single_color_stop - - css.types.gradient.repeating-radial-gradient.single_color_stop +{} diff --git a/index.ts b/index.ts index 3cefc981622..c9dfc28ca5a 100644 --- a/index.ts +++ b/index.ts @@ -5,10 +5,12 @@ import { Temporal } from '@js-temporal/polyfill'; import { fdir } from 'fdir'; import YAML from 'yaml'; import { convertMarkdown } from "./text"; -import { FeatureData, GroupData, SnapshotData, WebFeaturesData } from './types'; +import { GroupData, SnapshotData, WebFeaturesData } from './types'; import { BASELINE_LOW_TO_HIGH_DURATION, coreBrowserSet, parseRangedDateString } from 'compute-baseline'; import { Compat } from 'compute-baseline/browser-compat-data'; +import { assertValidFeatureReference } from './assertions'; +import { isMoved, isSplit } from './type-guards'; // The longest name allowed, to allow for compact display. const nameMaxLength = 80; @@ -120,7 +122,7 @@ function* identifiers(value) { // Map from BCD keys/paths to web-features identifiers. const bcdToFeatureId: Map = new Map(); -const features: { [key: string]: FeatureData } = {}; +const features: WebFeaturesData["features"] = {}; for (const [key, data] of yamlEntries('features')) { // Draft features reserve an identifier but aren't complete yet. Skip them. if (data[draft]) { @@ -130,6 +132,33 @@ for (const [key, data] of yamlEntries('features')) { continue; } + // Attach `kind: feature` to ordinary features + if (!isMoved(data) && !isSplit(data)) { + data.kind = "feature"; + } + + // Upgrade authored strings to arrays of 1 + const optionalArrays = [ + "spec", + "group", + "snapshot", + "caniuse", + "foo" + ]; + const stringToStringArray = (value: string | string[]) => typeof value === "string" ? [value] : value; + for (const optionalArray of optionalArrays) { + const value = data[optionalArray]; + if (value) { + data[optionalArray] = stringToStringArray(value); + } + } + if (data.discouraged) { + const value = data.discouraged.according_to; + if (value) { + data.discouraged.according_to = stringToStringArray(value); + } + } + // Convert markdown to text+HTML. if (data.description) { const { text, html } = convertMarkdown(data.description); @@ -185,12 +214,25 @@ for (const [key, data] of yamlEntries('features')) { features[key] = data; } -// Assert that discouraged feature's alternatives are valid for (const [id, feature] of Object.entries(features)) { - for (const alternative of feature.discouraged?.alternatives ?? []) { - if (!(alternative in features)) { - throw new Error(`${id}'s alternative "${alternative}" is not a valid feature ID`); - } + const { kind } = feature; + switch (kind) { + case "feature": + for (const alternative of feature.discouraged?.alternatives ?? []) { + assertValidFeatureReference(id, alternative, features) + } + break; + case "moved": + assertValidFeatureReference(id, feature.redirect_target, features); + break; + case "split": + for (const target of feature.redirect_targets) { + assertValidFeatureReference(id, target, features); + } + break; + default: + kind satisfies never; + throw new Error(`Unhandled feature kind ${kind}}`); } } diff --git a/package-lock.json b/package-lock.json index 2b754b684d9..97e4d3d16c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,7 +26,9 @@ "fast-json-stable-stringify": "^2.1.0", "fdir": "^6.5.0", "hast-util-to-string": "^3.0.1", + "mocha": "^11.7.2", "prettier": "^3.6.2", + "quicktype": "^23.2.6", "rehype-parse": "^9.0.1", "rehype-stringify": "^10.0.1", "remark-parse": "^11.0.0", @@ -63,79 +65,39 @@ "node": ">=0.1.90" } }, - "node_modules/@dabh/diagnostics": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", - "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, + "license": "MIT", "dependencies": { - "colorspace": "1.1.x", - "enabled": "2.0.x", - "kuler": "^2.0.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", - "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", - "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], + "@jridgewell/trace-mapping": "0.3.9" + }, "engines": { - "node": ">=18" + "node": ">=12" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", - "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", - "cpu": [ - "arm64" - ], + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", - "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", - "cpu": [ - "x64" - ], + "node_modules/@dabh/diagnostics": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" + "dependencies": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" } }, "node_modules/@esbuild/darwin-arm64": { @@ -154,326 +116,6 @@ "node": ">=18" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", - "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", - "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", - "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", - "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", - "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", - "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", - "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", - "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", - "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", - "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", - "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", - "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", - "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", - "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", - "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", - "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", - "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", - "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", - "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", - "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@eslint-community/eslint-utils": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", @@ -649,6 +291,13 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@glideapps/ts-necessities": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@glideapps/ts-necessities/-/ts-necessities-2.4.0.tgz", + "integrity": "sha512-mDC+qosuNa4lxR3ioMBb6CD0XLRsQBplU+zRPUYiMLXKeVPZ6UYphdNG/EGReig0YyfnVlBKZEXl1wzTotYmPA==", + "dev": true, + "license": "MIT" + }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -750,54 +399,224 @@ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": ">=12" + "node": ">=12" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@js-temporal/polyfill": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@js-temporal/polyfill/-/polyfill-0.5.1.tgz", + "integrity": "sha512-hloP58zRVCRSpgDxmqCWJNlizAlUgJFqG2ypq79DCvyv9tHjRYMDOcPFjzfl/A1/YxDvRCZz8wvZvmapQnKwFQ==", + "dependencies": { + "jsbi": "^4.3.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@mark.probst/typescript-json-schema": { + "version": "0.55.0", + "resolved": "https://registry.npmjs.org/@mark.probst/typescript-json-schema/-/typescript-json-schema-0.55.0.tgz", + "integrity": "sha512-jI48mSnRgFQxXiE/UTUCVCpX8lK3wCFKLF1Ss2aEreboKNuLQGt3e0/YFqWVHe/WENxOaqiJvwOz+L/SrN2+qQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@types/json-schema": "^7.0.9", + "@types/node": "^16.9.2", + "glob": "^7.1.7", + "path-equal": "^1.1.2", + "safe-stable-stringify": "^2.2.0", + "ts-node": "^10.9.1", + "typescript": "4.9.4", + "yargs": "^17.1.1" + }, + "bin": { + "typescript-json-schema": "bin/typescript-json-schema" + } + }, + "node_modules/@mark.probst/typescript-json-schema/node_modules/@types/node": { + "version": "16.18.126", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz", + "integrity": "sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@mark.probst/typescript-json-schema/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@mark.probst/typescript-json-schema/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@mark.probst/typescript-json-schema/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, + "license": "MIT" + }, + "node_modules/@mark.probst/typescript-json-schema/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@mark.probst/typescript-json-schema/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "node_modules/@mark.probst/typescript-json-schema/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, "engines": { "node": ">=8" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "node_modules/@mark.probst/typescript-json-schema/node_modules/typescript": { + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, "engines": { - "node": ">=6.0.0" + "node": ">=4.2.0" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "node_modules/@mark.probst/typescript-json-schema/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@js-temporal/polyfill": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@js-temporal/polyfill/-/polyfill-0.5.1.tgz", - "integrity": "sha512-hloP58zRVCRSpgDxmqCWJNlizAlUgJFqG2ypq79DCvyv9tHjRYMDOcPFjzfl/A1/YxDvRCZz8wvZvmapQnKwFQ==", + "node_modules/@mark.probst/typescript-json-schema/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", "dependencies": { - "jsbi": "^4.3.0" + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, "engines": { "node": ">=12" } }, + "node_modules/@mark.probst/typescript-json-schema/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/@mdn/browser-compat-data": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-7.1.6.tgz", @@ -1006,6 +825,34 @@ "node": ">=14" } }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/caniuse-lite": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/caniuse-lite/-/caniuse-lite-1.0.5.tgz", @@ -1381,12 +1228,24 @@ "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", "dev": true }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1404,6 +1263,19 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/ajv": { "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", @@ -1447,12 +1319,29 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/async": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", @@ -1475,6 +1364,27 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/before-after-hook": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-4.0.0.tgz", @@ -1492,7 +1402,6 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, - "peer": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1511,12 +1420,44 @@ "node": ">=8" } }, + "node_modules/browser-or-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-3.0.0.tgz", + "integrity": "sha512-iczIdVJzGEYhP5DqQxYM9Hh7Ztpqqi+CXZpSmX8ALFs9ecXkQIeqRyM6TfxEfMVpwhl3dSuDvxdzzo9sUOIVBQ==", + "dev": true, + "license": "MIT" + }, "node_modules/browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/c8": { "version": "10.1.3", "resolved": "https://registry.npmjs.org/c8/-/c8-10.1.3.tgz", @@ -1741,6 +1682,22 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chalk-template": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", + "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/chalk-template?sponsor=1" + } + }, "node_modules/character-entities": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", @@ -1895,6 +1852,13 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/collection-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/collection-utils/-/collection-utils-1.0.1.tgz", + "integrity": "sha512-LA2YTIlR7biSpXkKYwwuzGjwL5rjWEZVOSnvdUc7gObvWe4WkjxOpfrdhoP7Hs09YWDVfg0Mal9BpAqLfVEzQg==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/color": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", @@ -1968,6 +1932,58 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/command-line-args": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", + "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-back": "^3.1.0", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/command-line-usage": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-7.0.3.tgz", + "integrity": "sha512-PqMLy5+YGwhMh1wS04mVG44oqDsgyLRSKJBdOo1bnYhMKBW65gZF1dRp2OZRhiTjgUHljy99qkO7bsctLaw35Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-back": "^6.2.2", + "chalk-template": "^0.4.0", + "table-layout": "^4.1.0", + "typical": "^7.1.1" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/command-line-usage/node_modules/array-back": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", + "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.17" + } + }, + "node_modules/command-line-usage/node_modules/typical": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-7.3.0.tgz", + "integrity": "sha512-ya4mg/30vm+DOWfBg4YK3j2WD6TWtRkCbasOJr40CseYENzCUby/7rIvXA99JGsQHeNxLbnXdyLLxKSv3tauFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.17" + } + }, "node_modules/commander": { "version": "13.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", @@ -1990,8 +2006,7 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "peer": true + "dev": true }, "node_modules/convert-source-map": { "version": "2.0.0", @@ -1999,6 +2014,23 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-fetch": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.1.0.tgz", + "integrity": "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -2487,6 +2519,26 @@ "node": ">=0.10.0" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -2634,6 +2686,19 @@ "node": ">=8" } }, + "node_modules/find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-back": "^3.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -2702,6 +2767,13 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -2820,6 +2892,17 @@ "dev": true, "license": "MIT" }, + "node_modules/graphql": { + "version": "0.11.7", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-0.11.7.tgz", + "integrity": "sha512-x7uDjyz8Jx+QPbpCFCMQ8lltnQa4p4vSYHx6ADe8rVYRTdsyhCJbvSty5DAsLVmU6cGakl+r8HQYolKHxk/tiw==", + "deprecated": "No longer supported; please update to a newer version. Details: https://github.com/graphql/graphql-js#version-support", + "dev": true, + "license": "MIT", + "dependencies": { + "iterall": "1.1.3" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -3018,6 +3101,27 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -3055,6 +3159,18 @@ "node": ">=0.8.19" } }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -3143,6 +3259,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "dev": true, + "license": "MIT" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -3185,6 +3308,13 @@ "node": ">=8" } }, + "node_modules/iterall": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.1.3.tgz", + "integrity": "sha512-Cu/kb+4HiNSejAPhSaN1VukdNTTi/r4/e+yykqjlG/IW+1gZH5b4+Bq3whDX4tvbYugta3r8KTMUiqT3fIGxuQ==", + "dev": true, + "license": "MIT" + }, "node_modules/jackspeak": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", @@ -3465,6 +3595,13 @@ "node": ">=4" } }, + "node_modules/js-base64": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.7.tgz", + "integrity": "sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -3559,6 +3696,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -3629,6 +3780,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, "node_modules/mdast-util-from-markdown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", @@ -4171,7 +4329,6 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "peer": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -4449,6 +4606,16 @@ "node": ">=12" } }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -4461,6 +4628,27 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -4482,6 +4670,16 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, "node_modules/one-time": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", @@ -4545,6 +4743,13 @@ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "dev": true }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true, + "license": "(MIT AND Zlib)" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -4607,6 +4812,13 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/path-equal": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/path-equal/-/path-equal-1.2.5.tgz", + "integrity": "sha512-i73IctDr3F2W+bsOWDyyVm/lqsXO47aY9nsFZUjTT/aljSbkxHxxCoyZ9UUrM8jK0JVod+An+rl48RCsvWM+9g==", + "dev": true, + "license": "MIT" + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -4616,6 +4828,16 @@ "node": ">=8" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -4661,6 +4883,16 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -4732,6 +4964,16 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/property-information": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", @@ -4773,6 +5015,159 @@ ], "license": "MIT" }, + "node_modules/quicktype": { + "version": "23.2.6", + "resolved": "https://registry.npmjs.org/quicktype/-/quicktype-23.2.6.tgz", + "integrity": "sha512-rlD1jF71bOmDn6SQ/ToLuuRkMQ7maxo5oVTn5dPCl11ymqoJCFCvl7FzRfh+fkDFmWt2etl+JiIEdWImLxferA==", + "dev": true, + "license": "Apache-2.0", + "workspaces": [ + "./packages/quicktype-core", + "./packages/quicktype-graphql-input", + "./packages/quicktype-typescript-input", + "./packages/quicktype-vscode" + ], + "dependencies": { + "@glideapps/ts-necessities": "^2.2.3", + "chalk": "^4.1.2", + "collection-utils": "^1.0.1", + "command-line-args": "^5.2.1", + "command-line-usage": "^7.0.1", + "cross-fetch": "^4.0.0", + "graphql": "^0.11.7", + "lodash": "^4.17.21", + "moment": "^2.30.1", + "quicktype-core": "23.2.6", + "quicktype-graphql-input": "23.2.6", + "quicktype-typescript-input": "23.2.6", + "readable-stream": "^4.5.2", + "stream-json": "1.8.0", + "string-to-stream": "^3.0.1", + "typescript": "~5.8.3" + }, + "bin": { + "quicktype": "dist/index.js" + }, + "engines": { + "node": ">=18.12.0" + } + }, + "node_modules/quicktype-core": { + "version": "23.2.6", + "resolved": "https://registry.npmjs.org/quicktype-core/-/quicktype-core-23.2.6.tgz", + "integrity": "sha512-asfeSv7BKBNVb9WiYhFRBvBZHcRutPRBwJMxW0pefluK4kkKu4lv0IvZBwFKvw2XygLcL1Rl90zxWDHYgkwCmA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@glideapps/ts-necessities": "2.2.3", + "browser-or-node": "^3.0.0", + "collection-utils": "^1.0.1", + "cross-fetch": "^4.0.0", + "is-url": "^1.2.4", + "js-base64": "^3.7.7", + "lodash": "^4.17.21", + "pako": "^1.0.6", + "pluralize": "^8.0.0", + "readable-stream": "4.5.2", + "unicode-properties": "^1.4.1", + "urijs": "^1.19.1", + "wordwrap": "^1.0.0", + "yaml": "^2.4.1" + } + }, + "node_modules/quicktype-core/node_modules/@glideapps/ts-necessities": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@glideapps/ts-necessities/-/ts-necessities-2.2.3.tgz", + "integrity": "sha512-gXi0awOZLHk3TbW55GZLCPP6O+y/b5X1pBXKBVckFONSwF1z1E5ND2BGJsghQFah+pW7pkkyFb2VhUQI2qhL5w==", + "dev": true, + "license": "MIT" + }, + "node_modules/quicktype-core/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/quicktype-graphql-input": { + "version": "23.2.6", + "resolved": "https://registry.npmjs.org/quicktype-graphql-input/-/quicktype-graphql-input-23.2.6.tgz", + "integrity": "sha512-jHQ8XrEaccZnWA7h/xqUQhfl+0mR5o91T6k3I4QhlnZSLdVnbycrMq4FHa9EaIFcai783JKwSUl1+koAdJq4pg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "collection-utils": "^1.0.1", + "graphql": "^0.11.7", + "quicktype-core": "23.2.6" + } + }, + "node_modules/quicktype-typescript-input": { + "version": "23.2.6", + "resolved": "https://registry.npmjs.org/quicktype-typescript-input/-/quicktype-typescript-input-23.2.6.tgz", + "integrity": "sha512-dCNMxR+7PGs9/9Tsth9H6LOQV1G+Tv4sUGT8ZUfDRJ5Hq371qOYLma5BnLX6VxkPu8JT7mAMpQ9VFlxstX6Qaw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@mark.probst/typescript-json-schema": "0.55.0", + "quicktype-core": "23.2.6", + "typescript": "4.9.5" + } + }, + "node_modules/quicktype-typescript-input/node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/quicktype/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "dev": true, + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/quicktype/node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -5062,6 +5457,23 @@ "node": "*" } }, + "node_modules/stream-chain": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz", + "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/stream-json": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.8.0.tgz", + "integrity": "sha512-HZfXngYHUAr1exT4fxlbc1IOce1RYxp2ldeaf97LYCOPSoOqY/1Psp7iGvpb+6JIOgkra9zDYnPX01hGAHzEPw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "stream-chain": "^2.2.5" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -5071,6 +5483,16 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string-to-stream": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/string-to-stream/-/string-to-stream-3.0.1.tgz", + "integrity": "sha512-Hl092MV3USJuUCC6mfl9sPzGloA3K5VwdIeJjYIkXY/8K+mUvaeEabWJgArp+xXrsWxCajeT2pc4axbVhIZJyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "^3.4.0" + } + }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -5205,6 +5627,30 @@ "node": ">=8" } }, + "node_modules/table-layout": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-4.1.1.tgz", + "integrity": "sha512-iK5/YhZxq5GO5z8wb0bY1317uDF3Zjpha0QFFLA8/trAoiLbQD0HUbMesEaxyzUgDxi2QlcbM8IvqOlEjgoXBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-back": "^6.2.2", + "wordwrapjs": "^5.1.0" + }, + "engines": { + "node": ">=12.17" + } + }, + "node_modules/table-layout/node_modules/array-back": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", + "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.17" + } + }, "node_modules/test-exclude": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", @@ -5306,6 +5752,13 @@ "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", "dev": true }, + "node_modules/tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", + "dev": true, + "license": "MIT" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -5319,6 +5772,13 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" + }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -5383,6 +5843,60 @@ "node": ">=18.0.0" } }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -5460,6 +5974,16 @@ "typescript": ">=4.8.4 <6.0.0" } }, + "node_modules/typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/undici": { "version": "7.12.0", "resolved": "https://registry.npmjs.org/undici/-/undici-7.12.0.tgz", @@ -5476,6 +6000,35 @@ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true }, + "node_modules/unicode-properties": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", + "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.0", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/unicode-trie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", + "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + }, + "node_modules/unicode-trie/node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", + "dev": true, + "license": "MIT" + }, "node_modules/unified": { "version": "11.0.5", "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", @@ -5579,12 +6132,26 @@ "punycode": "^2.1.0" } }, + "node_modules/urijs": { + "version": "1.19.11", + "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz", + "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==", + "dev": true, + "license": "MIT" + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, "node_modules/v8-to-istanbul": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", @@ -5660,6 +6227,13 @@ "dev": true, "license": "CC0-1.0" }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, + "license": "BSD-2-Clause" + }, "node_modules/whatwg-encoding": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", @@ -5681,6 +6255,17 @@ "node": ">=18" } }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -5742,6 +6327,23 @@ "node": ">=0.10.0" } }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/wordwrapjs": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-5.1.0.tgz", + "integrity": "sha512-JNjcULU2e4KJwUNv6CHgI46UvDGitb6dGryHajXTDiLgg1/RiGoPSDw4kZfYnwGtEXf2ZMeIewDQgFGzkCB2Sg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.17" + } + }, "node_modules/workerpool": { "version": "9.3.2", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.2.tgz", @@ -5836,6 +6438,13 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -5931,6 +6540,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -5963,11 +6582,9 @@ "devDependencies": { "@types/chai": "^5.2.2", "@types/chai-jest-snapshot": "^1.3.8", - "@types/mocha": "^10.0.10", "c8": "^10.1.3", "chai": "^6.0.1", - "chai-jest-snapshot": "^2.0.0", - "mocha": "^11.7.2" + "chai-jest-snapshot": "^2.0.0" }, "peerDependencies": { "@mdn/browser-compat-data": "^7.0.0" diff --git a/package.json b/package.json index d80578438d0..d80f8aa59fb 100644 --- a/package.json +++ b/package.json @@ -23,17 +23,18 @@ "undist": "tsx scripts/undist.ts", "feature-init": "tsx scripts/feature-init.ts", "format": "npx prettier --write .", - "schema:write": "npm run schema -- --out ./schemas/data.schema.json", - "schema": "ts-json-schema-generator --tsconfig ./tsconfig.json --path ./types.ts --type=WebFeaturesData", + "schematypes": "sh -c \"npx quicktype --lang='typescript' --src-lang schema --src ./schemas/data.schema.json --just-types --prefer-unions --prefer-const-values --top-level=WebFeaturesData | prettier --stdin-filepath ./types.quicktype.ts\"", + "schematypes:write": "npm run --silent schematypes > ./types.quicktype.ts", "test:caniuse": "tsx scripts/caniuse.ts", "test:coverage": "npm run --workspaces test:coverage", "test:dist": "tsx scripts/dist.ts --check", "test:format": "prettier --check .", + "test:index": "mocha -r tsx './*.test.ts'", "test:lint": "npx eslint .", - "test:schema": "tsx scripts/schema.ts", + "test:schematypes": "tsx scripts/schema.ts", "test:specs": "tsx scripts/specs.ts", "test:types": "npm run --workspaces test:types && tsc", - "test": "npm run test:caniuse -- --quiet && npm run test:schema && npm run test:specs && npm run test:types && npm run test:format && npm run test:dist && npm run test --workspaces && npm run test:lint", + "test": "npm run test:caniuse -- --quiet && npm run test:schematypes && npm run test:specs && npm run test:types && npm run test:format && npm run test:index && npm run test:dist && npm test --workspaces && npm run test:lint", "update-drafts": "tsx scripts/update-drafts.ts", "remove-tagged-compat-features": "tsx scripts/remove-tagged-compat-features.ts && npm run format" }, @@ -53,7 +54,9 @@ "fast-json-stable-stringify": "^2.1.0", "fdir": "^6.5.0", "hast-util-to-string": "^3.0.1", + "mocha": "^11.7.2", "prettier": "^3.6.2", + "quicktype": "^23.2.6", "rehype-parse": "^9.0.1", "rehype-stringify": "^10.0.1", "remark-parse": "^11.0.0", diff --git a/packages/compute-baseline/package.json b/packages/compute-baseline/package.json index 8fcf340d2fb..fa1abe85965 100644 --- a/packages/compute-baseline/package.json +++ b/packages/compute-baseline/package.json @@ -28,11 +28,9 @@ "devDependencies": { "@types/chai": "^5.2.2", "@types/chai-jest-snapshot": "^1.3.8", - "@types/mocha": "^10.0.10", "c8": "^10.1.3", "chai": "^6.0.1", - "chai-jest-snapshot": "^2.0.0", - "mocha": "^11.7.2" + "chai-jest-snapshot": "^2.0.0" }, "peerDependencies": { "@mdn/browser-compat-data": "^7.0.0" diff --git a/packages/web-features/README.md b/packages/web-features/README.md index 929a6b82790..b62037daf97 100644 --- a/packages/web-features/README.md +++ b/packages/web-features/README.md @@ -52,3 +52,78 @@ For browser support iconography (that is, browser logos and checkmarks and Xs), If you wish to report browser version numbers, avoid showing version numbers alone. Developers and users often do not know whether a version number refers to a very recent or old release. If you must show a version number, consider contextualizing that number by showing a release date, a relative date (such as "Released … years ago"), an offset (such as "… releases ago"), or usage statistics relevant to your audience (such as "…% of your visitors in the last 90 days"). + +## Schema reference + +This part of the README summarizes the schema for feature data. +See `data.schema.json` for a canonical reference. + +## `features` + +The `features` object contains data for features. +Each key is a feature ID string and values describe the feature. +Most values are ordinary feature objects with names, descriptions, and other data. +Some features contain redirects to other features. +You can distinguish between ordinary feature objects and redirects by using the `kind` property: + +* `"feature"` — ordinary features +* `"moved"` — the feature has a redirect to a new key +* `"split"` — the feature has a redirect to two or more keys + +### Feature objects + +A feature with the `kind` set to `"feature"` is an ordinary feature. +It has the following properties: + +- `kind` (value: `"feature"`): A type discriminator +- `name` (type: `string`): A plain-text human-readable name for the feature +- `description` (type: `string`): A short plain-text description of the feature +- `description_html` (type: `string`): A short HTML-formatted description of the feature +- `spec` (type: `string[]`): A specification URL or an array of them +- `status`: Support status data. + It has the following properties: + + - `baseline` (type: `"high" | "low" | false`): Whether the feature Baseline widely available, Baseline newly available, or not Baseline + - `baseline_low_date` (optional, type: `string`): When the feature reached Baseline newly available status + - `baseline_high_date` (optional, type: `string`): When the feature reached Baseline widely available status + - `support`: An object representing per-browser support information, showing the version number where each browser first started to support that feature. + All keys are optional. + Keys are one of: `"chrome"`, `"chrome_android"`, `"edge"`, `"firefox"`, `"firefox"`, `"firefox_android"`, `"safari"`, `"safari_ios"`. + Each value is a `string` containing the version number. + +- `group` (optional, type: `string[]`): A `groups` key or an array of them +- `snapshot` (optional, type: `string[]`): A `snapshots` key or an array of them +- `caniuse` (optional, type: `string[]`): A caniuse feature ID that corresponds to the current feature, or an array of them. + Use it to look up caniuse data from a package like [`caniuse-lite`](https://www.npmjs.com/package/caniuse-lite) or construct a URL to a page on caniuse.com. +- `compat_features` (optional, type: `string[]`): An array of `@mdn/browser-compat-data` feature key strings. +- `discouraged` (optional): An object indicating that web developers should avoid using the feature. + It has the following properties: + + - `according_to` (type: `string[]`): One or more links to a formal discouragement notice, such as specification text or an intent-to-unship + - `alternatives` (optional, type: `string[]`): One or more feature IDs (as in `features[alternatives[0]]`) that substitute some or all of this feature's utility + +### Moved objects + +A feature with the `kind` set to `"moved"` is a redirect to another feature. +It says that this feature ID is actually best represented by the data given by another ID. +If you’re showing web-features data to developers, then treat this like an HTTP 301 redirect and go directly to the feature it points to. + +A moved feature has the following properties: + +- `kind` (value: `"moved"`): A type discriminator +- `redirect_target` (type: `string`): The ID of a feature (as in `features[redirect_target]`). + The ID is guaranteed to be an ordinary, non-redirecting feature. + Double redirects and cycles are forbidden. + +### Split objects + +A feature with the `kind` set to `"split"` is a redirect to multiple other features. +It says that this feature ID is actually best represented by the data given by multiple other features and you (or your users) will have to make a choice about what to do. +You can think of this kind of feature like a [Wikipedia disambiguation page](https://en.wikipedia.org/wiki/Joker). + +A split feature has the following properties: + +- `kind` (value: `"split"`): A type discriminator +- `redirect_targets` (type: `string[]`): An array of two or more feature IDs, in order of greatest relevance or importance (as judged by the web-features maintainers). + The IDs are guaranteed to be ordinary, non-redirecting features. + Double redirects and cycles are forbidden. diff --git a/packages/web-features/package.json b/packages/web-features/package.json index a88ce569d12..97b91a67135 100644 --- a/packages/web-features/package.json +++ b/packages/web-features/package.json @@ -18,12 +18,14 @@ "types": "./index.d.ts", "files": [ "index.d.ts", + "types.d.ts", + "types.quicktype.d.ts", "index.js", "data.json", "data.schema.json" ], "scripts": { - "prepare": "tsc && rm types.js && tsup ./index.ts --dts-only --format=esm --out-dir=." + "prepare": "tsc && rm types.js && rm types.quicktype.js" }, "devDependencies": { "@types/node": "^20.19.16", diff --git a/packages/web-features/tsconfig.json b/packages/web-features/tsconfig.json index 216634c4164..e483fa95943 100644 --- a/packages/web-features/tsconfig.json +++ b/packages/web-features/tsconfig.json @@ -3,6 +3,7 @@ "target": "ES2016", "module": "ESNext", "moduleResolution": "Bundler", - "typeRoots": ["./node_modules/@types"] + "typeRoots": ["./node_modules/@types"], + "declaration": true } } diff --git a/schemas/data.schema.json b/schemas/data.schema.json index 2d34661eed7..dcf66bcf8cc 100644 --- a/schemas/data.schema.json +++ b/schemas/data.schema.json @@ -1,53 +1,124 @@ { - "$ref": "#/definitions/WebFeaturesData", - "$schema": "http://json-schema.org/draft-07/schema#", + "$schema": "http://json-schema.org/draft-07/schema", + "description": "The top-level web-features data package", + "type": "object", + "properties": { + "browsers": { + "description": "Browsers and browser release data", + "type": "object", + "properties": { + "chrome": { + "$ref": "#/definitions/BrowserData" + }, + "chrome_android": { + "$ref": "#/definitions/BrowserData" + }, + "edge": { + "$ref": "#/definitions/BrowserData" + }, + "firefox": { + "$ref": "#/definitions/BrowserData" + }, + "firefox_android": { + "$ref": "#/definitions/BrowserData" + }, + "safari": { + "$ref": "#/definitions/BrowserData" + }, + "safari_ios": { + "$ref": "#/definitions/BrowserData" + } + }, + "required": [ + "chrome", + "chrome_android", + "edge", + "firefox", + "firefox_android", + "safari", + "safari_ios" + ], + "additionalProperties": false + }, + "features": { + "description": "Feature identifiers and data", + "type": "object", + "additionalProperties": { + "oneOf": [ + { + "$ref": "#/definitions/FeatureData" + }, + { + "$ref": "#/definitions/FeatureMovedData" + }, + { + "$ref": "#/definitions/FeatureSplitData" + } + ], + "$comment": "Use the `kind` property as a discriminator." + } + }, + "groups": { + "description": "Group identifiers and data", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/GroupData" + } + }, + "snapshots": { + "description": "Snapshot identifiers and data", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/SnapshotData" + } + } + }, + "required": ["browsers", "features", "groups", "snapshots"], + "additionalProperties": false, "definitions": { + "Discouraged": { + "type": "object", + "properties": { + "according_to": { + "description": "Links to a formal discouragement notice, such as specification text, intent-to-unship, etc.", + "$ref": "#/definitions/Strings" + }, + "alternatives": { + "description": "IDs for features that substitute some or all of this feature's utility", + "$ref": "#/definitions/Strings" + } + }, + "required": ["according_to"], + "additionalProperties": false + }, "BrowserData": { - "additionalProperties": false, "description": "Browser information", + "type": "object", "properties": { "name": { "description": "The name of the browser, as in \"Edge\" or \"Safari on iOS\"", "type": "string" }, "releases": { - "description": "The browser's releases", + "type": "array", "items": { "$ref": "#/definitions/Release" - }, - "type": "array" + } } }, - "required": [ - "name", - "releases" - ], - "type": "object" + "required": ["name", "releases"], + "additionalProperties": false }, "FeatureData": { - "additionalProperties": false, + "description": "A feature data entry", + "type": "object", "properties": { - "caniuse": { - "anyOf": [ - { - "type": "string" - }, - { - "items": { - "type": "string" - }, - "minItems": 2, - "type": "array" - } - ], - "description": "caniuse.com identifier(s)" + "kind": { + "const": "feature" }, - "compat_features": { - "description": "Sources of support data for this feature", - "items": { - "type": "string" - }, - "type": "array" + "name": { + "description": "Short name", + "type": "string" }, "description": { "description": "Short description of the feature, as a plain text string", @@ -57,212 +128,77 @@ "description": "Short description of the feature, as an HTML string", "type": "string" }, - "discouraged": { - "additionalProperties": false, - "description": "Whether developers are formally discouraged from using this feature", - "properties": { - "according_to": { - "description": "Links to a formal discouragement notice, such as specification text, intent-to-unship, etc.", - "items": { - "type": "string" - }, - "type": "array" - }, - "alternatives": { - "description": "IDs for features that substitute some or all of this feature's utility", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "according_to" - ], - "type": "object" + "spec": { + "description": "Specification URLs", + "$ref": "#/definitions/Strings" }, "group": { - "anyOf": [ - { - "type": "string" - }, - { - "items": { - "type": "string" - }, - "minItems": 2, - "type": "array" - } - ], - "description": "Group identifier(s)" - }, - "name": { - "description": "Short name", - "type": "string" + "description": "Group identifiers", + "$ref": "#/definitions/Strings" }, "snapshot": { - "anyOf": [ - { - "type": "string" - }, - { - "items": { - "type": "string" - }, - "minItems": 2, - "type": "array" - } - ], - "description": "Snapshot identifier(s)" + "description": "Snapshot identifiers", + "$ref": "#/definitions/Strings" }, - "spec": { - "anyOf": [ - { - "type": "string" - }, - { - "items": { - "type": "string" - }, - "minItems": 2, - "type": "array" - } - ], - "description": "Specification URL(s)" + "caniuse": { + "description": "caniuse.com identifiers", + "$ref": "#/definitions/Strings" + }, + "compat_features": { + "description": "Sources of support data for this feature", + "$ref": "#/definitions/Strings" }, "status": { - "additionalProperties": false, - "description": "Whether a feature is considered a \"baseline\" web platform feature and when it achieved that status", - "properties": { - "baseline": { - "description": "Whether the feature is Baseline (low substatus), Baseline (high substatus), or not (false)", - "enum": [ - "high", - "low", - false - ], - "type": [ - "string", - "boolean" - ] - }, - "baseline_high_date": { - "description": "Date the feature achieved Baseline high status", - "type": "string" - }, - "baseline_low_date": { - "description": "Date the feature achieved Baseline low status", - "type": "string" - }, - "by_compat_key": { - "additionalProperties": { - "additionalProperties": false, - "properties": { - "baseline": { - "description": "Whether the feature is Baseline (low substatus), Baseline (high substatus), or not (false)", - "enum": [ - "high", - "low", - false - ], - "type": [ - "string", - "boolean" - ] - }, - "baseline_high_date": { - "description": "Date the feature achieved Baseline high status", - "type": "string" - }, - "baseline_low_date": { - "description": "Date the feature achieved Baseline low status", - "type": "string" - }, - "support": { - "additionalProperties": false, - "description": "Browser versions that most-recently introduced the feature", - "properties": { - "chrome": { - "type": "string" - }, - "chrome_android": { - "type": "string" - }, - "edge": { - "type": "string" - }, - "firefox": { - "type": "string" - }, - "firefox_android": { - "type": "string" - }, - "safari": { - "type": "string" - }, - "safari_ios": { - "type": "string" - } - }, - "type": "object" - } - }, - "required": [ - "baseline", - "support" - ], - "type": "object" - }, - "description": "Statuses for each key in the feature's compat_features list, if applicable. Not available to the npm release of web-features.", - "type": "object" - }, - "support": { - "additionalProperties": false, - "description": "Browser versions that most-recently introduced the feature", - "properties": { - "chrome": { - "type": "string" - }, - "chrome_android": { - "type": "string" - }, - "edge": { - "type": "string" - }, - "firefox": { - "type": "string" - }, - "firefox_android": { - "type": "string" - }, - "safari": { - "type": "string" - }, - "safari_ios": { - "type": "string" - } - }, - "type": "object" - } - }, - "required": [ - "baseline", - "support" - ], - "type": "object" + "description": "Whether a feature is considered a \"Baseline\" web platform feature and when it achieved that status", + "$ref": "#/definitions/StatusHeadline" + }, + "discouraged": { + "description": "Whether developers are formally discouraged from using this feature", + "$ref": "#/definitions/Discouraged" } }, "required": [ + "kind", "name", "description", "description_html", "spec", "status" ], - "type": "object" + "additionalProperties": false + }, + "FeatureMovedData": { + "description": "A feature has permanently moved to exactly one other ID", + "type": "object", + "properties": { + "kind": { + "const": "moved" + }, + "redirect_target": { + "description": "The new ID for this feature", + "type": "string" + } + }, + "required": ["kind", "redirect_target"], + "additionalProperties": false + }, + "FeatureSplitData": { + "description": "A feature has split into two or more other features", + "type": "object", + "properties": { + "kind": { + "const": "split" + }, + "redirect_targets": { + "description": "The new IDs for this feature", + "$ref": "#/definitions/Strings" + } + }, + "required": ["kind", "redirect_targets"], + "additionalProperties": false }, "GroupData": { - "additionalProperties": false, + "type": "object", "properties": { "name": { "description": "Short name", @@ -273,32 +209,27 @@ "type": "string" } }, - "required": [ - "name" - ], - "type": "object" + "required": ["name"], + "additionalProperties": false }, "Release": { - "additionalProperties": false, "description": "Browser release information", + "type": "object", "properties": { - "date": { - "description": "The release date, as in \"2023-12-11\"", - "type": "string" - }, "version": { "description": "The version string, as in \"10\" or \"17.1\"", "type": "string" + }, + "date": { + "description": " The release date, as in \"2023-12-11\"", + "type": "string" } }, - "required": [ - "version", - "date" - ], - "type": "object" + "required": ["version", "date"], + "additionalProperties": false }, "SnapshotData": { - "additionalProperties": false, + "type": "object", "properties": { "name": { "description": "Short name", @@ -309,81 +240,80 @@ "type": "string" } }, - "required": [ - "name", - "spec" - ], - "type": "object" + "required": ["name", "spec"], + "additionalProperties": false }, - "WebFeaturesData": { - "additionalProperties": false, + "Status": { + "type": "object", "properties": { - "browsers": { - "additionalProperties": false, - "description": "Browsers and browser release data", + "baseline": { + "description": "Whether the feature is Baseline (low substatus), Baseline (high substatus), or not (false)", + "enum": ["high", "low", false] + }, + "baseline_high_date": { + "description": "Date the feature achieved Baseline high status", + "type": "string" + }, + "baseline_low_date": { + "description": "Date the feature achieved Baseline low status", + "type": "string" + }, + "support": { + "description": "Browser versions that most-recently introduced the feature", + "type": "object", "properties": { "chrome": { - "$ref": "#/definitions/BrowserData" + "type": "string" }, "chrome_android": { - "$ref": "#/definitions/BrowserData" + "type": "string" }, "edge": { - "$ref": "#/definitions/BrowserData" + "type": "string" }, "firefox": { - "$ref": "#/definitions/BrowserData" + "type": "string" }, "firefox_android": { - "$ref": "#/definitions/BrowserData" + "type": "string" }, "safari": { - "$ref": "#/definitions/BrowserData" + "type": "string" }, "safari_ios": { - "$ref": "#/definitions/BrowserData" + "type": "string" } }, - "required": [ - "chrome", - "chrome_android", - "edge", - "firefox", - "firefox_android", - "safari", - "safari_ios" - ], - "type": "object" - }, - "features": { - "additionalProperties": { - "$ref": "#/definitions/FeatureData" - }, - "description": "Feature identifiers and data", - "type": "object" - }, - "groups": { - "additionalProperties": { - "$ref": "#/definitions/GroupData" - }, - "description": "Group identifiers and data", - "type": "object" - }, - "snapshots": { + "additionalProperties": false + } + }, + "required": ["baseline", "support"] + }, + "StatusHeadline": { + "type": "object", + "allOf": [{ "$ref": "#/definitions/Status" }], + "properties": { + "baseline": {}, + "baseline_high_date": {}, + "baseline_low_date": {}, + "support": {}, + "by_compat_key": { + "description": "Statuses for each key in the feature's compat_features list, if applicable. Not available to the npm release of web-features.", + "type": "object", "additionalProperties": { - "$ref": "#/definitions/SnapshotData" - }, - "description": "Snapshot identifiers and data", - "type": "object" + "$ref": "#/definitions/Status" + } } }, - "required": [ - "browsers", - "features", - "groups", - "snapshots" - ], - "type": "object" + "required": ["baseline", "support"], + "additionalProperties": false + }, + "Strings": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1 } } -} \ No newline at end of file +} diff --git a/scripts/build.ts b/scripts/build.ts index 35f346481ce..04c4aa2a14e 100644 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -7,6 +7,7 @@ import { basename } from "node:path"; import winston from "winston"; import yargs from "yargs"; import * as data from "../index.js"; +import { isOrdinaryFeatureData } from "../type-guards.js"; import { validate } from "./validate.js"; const logger = winston.createLogger({ @@ -35,7 +36,12 @@ yargs(process.argv.slice(2)) function buildPackage() { const packageDir = new URL("./packages/web-features/", rootDir); - const filesToCopy = ["LICENSE.txt", "types.ts", "schemas/data.schema.json"]; + const filesToCopy = [ + "LICENSE.txt", + "types.quicktype.ts", + "types.ts", + "schemas/data.schema.json", + ]; if (!valid(data)) { logger.error("Data failed schema validation. No package built."); @@ -63,6 +69,10 @@ function buildPackage() { function buildExtendedJSON() { for (const [id, featureData] of Object.entries(data.features)) { + if (!isOrdinaryFeatureData(featureData)) { + continue; + } + if ( Array.isArray(featureData.compat_features) && featureData.compat_features.length && diff --git a/scripts/dist.ts b/scripts/dist.ts index 209aa1d154a..1832f6a4b89 100644 --- a/scripts/dist.ts +++ b/scripts/dist.ts @@ -14,6 +14,7 @@ import { isDeepStrictEqual } from "node:util"; import winston from "winston"; import YAML, { Document, Scalar, YAMLSeq } from "yaml"; import yargs from "yargs"; +import type { FeatureData, FeatureMovedData, FeatureSplitData } from "../types"; const compat = new Compat(); @@ -181,6 +182,39 @@ function compareStatus(a: SupportStatus, b: SupportStatus) { return 0; } +function toRedirectDist( + id: string, + source: FeatureMovedData | FeatureSplitData, +): YAML.Document { + const dist = new Document({}); + + const comment = [ + `Generated from: ${id}.yml`, + `This file intentionally left blank.`, + `Do not edit this file.`, + ]; + + const { kind } = source; + switch (kind) { + case "moved": + comment.push( + `The data for this feature has moved to ${source.redirect_target}.yml`, + ); + break; + case "split": + comment.push(`The data for this feature has moved to:`); + comment.push(...source.redirect_targets.map((dest) => ` - ${dest}.yml`)); + break; + default: + kind satisfies never; + throw new Error(`Unhandled feature kind ${kind}}`); + } + + dist.commentBefore = comment.map((line) => ` ${line}`).join("\n"); + + return dist; +} + /** * Generate a dist YAML document from a feature definition YAML file path. * @@ -192,6 +226,11 @@ function toDist(sourcePath: string): YAML.Document { const source = YAML.parse(fs.readFileSync(sourcePath, { encoding: "utf-8" })); const { name: id } = path.parse(sourcePath); + if ("redirect_target" in source || "redirect_targets" in source) { + return toRedirectDist(id, source); + } + source as Partial; + // Collect tagged compat features. A `compat_features` list in the source // takes precedence, but can be removed if it matches the tagged features. const taggedCompatFeatures = (tagsToFeatures.get(`web-features:${id}`) ?? []) diff --git a/scripts/find-ranged-headline-statuses.ts b/scripts/find-ranged-headline-statuses.ts index a5dabd2f0cd..e60f21efd00 100644 --- a/scripts/find-ranged-headline-statuses.ts +++ b/scripts/find-ranged-headline-statuses.ts @@ -1,7 +1,13 @@ import { features } from "../index"; +import { isOrdinaryFeatureData } from "../type-guards"; for (const [key, data] of Object.entries(features)) { - if ((data.status.baseline_low_date ?? "").includes("≤")) { - console.log(key); + if (isOrdinaryFeatureData(data)) { + if ( + "status" in data && + (data.status.baseline_low_date ?? "").includes("≤") + ) { + console.log(key); + } } } diff --git a/scripts/inspect-feature.ts b/scripts/inspect-feature.ts index 7c7c9e97f07..121dca044cf 100644 --- a/scripts/inspect-feature.ts +++ b/scripts/inspect-feature.ts @@ -3,6 +3,7 @@ import escapeHtml from "escape-html"; import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; +import winston from "winston"; import YAML from "yaml"; import yargs from "yargs"; import { features } from ".."; @@ -33,6 +34,15 @@ const argv = yargs(process.argv.slice(2)) defaultDescription: "warn", }).argv as Args; +const logger = winston.createLogger({ + level: argv.verbose > 0 ? "debug" : "warn", + format: winston.format.combine( + winston.format.colorize(), + winston.format.simple(), + ), + transports: new winston.transports.Console(), +}); + function main(): void { for (const filePath of argv.paths) { const { name, ext, dir } = path.parse(filePath); @@ -45,6 +55,12 @@ function main(): void { if (!feature) { throw new Error(`No feature found for ID ${id}`); } + if (feature.kind === "moved" || feature.kind === "split") { + logger.warn( + `${id} is a ${feature.kind} feature. Did you mean to inspect this?`, + ); + continue; + } const { compat_features } = feature; diff --git a/scripts/schema.ts b/scripts/schema.ts index 357bcf85a21..24cc429c0b3 100644 --- a/scripts/schema.ts +++ b/scripts/schema.ts @@ -9,15 +9,15 @@ import { validate } from "./validate.js"; let status: 0 | 1 = 0; -function checkSchemaConsistency(): void { - const schemaPath: string = path.join(path.dirname(url.fileURLToPath(import.meta.url)), "../schemas/data.schema.json"); - const schemaOnDisk: string = fs.readFileSync(schemaPath, { encoding: "utf-8"}); - const schemaGenerated: string = child_process.execSync("npm run --silent schema", { encoding: "utf-8"}).trim(); +function checkGeneratedFileConsistency(): void { + const quicktypePath: string = path.join(path.dirname(url.fileURLToPath(import.meta.url)), "../types.quicktype.ts"); + const quicktypeOnDisk: string = fs.readFileSync(quicktypePath, { encoding: "utf-8"}); + const quicktypeGenerated: string = child_process.execSync("npm run --silent schematypes", { encoding: "utf-8"}); - if (schemaOnDisk !== schemaGenerated) { - console.error("There's a mismatch between the schema on disk and types in `index.ts`."); + if (quicktypeOnDisk !== quicktypeGenerated) { + console.error("There's a mismatch between the types generated by quicktype and the types in `types.quicktype.ts`."); console.error("This may produce misleading results for feature validation."); - console.error("To fix this, run `npm run schema:write`."); + console.error("To fix this, run `npm run schematypes:write`."); status = 1; } } @@ -35,6 +35,6 @@ function valid() { } } -checkSchemaConsistency(); +checkGeneratedFileConsistency(); valid(); process.exit(status); diff --git a/scripts/specs.ts b/scripts/specs.ts index 6760ce61e17..a7006a8c920 100644 --- a/scripts/specs.ts +++ b/scripts/specs.ts @@ -3,6 +3,7 @@ import assert from "node:assert/strict"; import webSpecs from 'web-specs' with { type: 'json' }; import { features } from '../index.js'; +import { isOrdinaryFeatureData } from "../type-guards.js"; // Specs needs to be in "good standing". Nightly URLs are used if available, // otherwise the snapshot/versioned URL is used. See browser-specs/web-specs @@ -199,6 +200,10 @@ for (const [allowedUrl, message] of defaultAllowlist) { } for (const [id, data] of Object.entries(features)) { + if (!isOrdinaryFeatureData(data)) { + continue; + } + const specs = Array.isArray(data.spec) ? data.spec : [data.spec]; for (const spec of specs) { let url: URL; diff --git a/scripts/stats.ts b/scripts/stats.ts index 1894c73ba96..404efe51ddf 100644 --- a/scripts/stats.ts +++ b/scripts/stats.ts @@ -2,6 +2,7 @@ import { Compat } from "compute-baseline/browser-compat-data"; import { fileURLToPath } from "node:url"; import yargs from "yargs"; import { features } from "../index.js"; +import { isOrdinaryFeatureData } from "../type-guards.js"; const argv = yargs(process.argv.slice(2)) .scriptName("stats") @@ -14,11 +15,20 @@ const argv = yargs(process.argv.slice(2)) }).argv; export function stats(detailed: boolean = false) { - const featureCount = Object.keys(features).length; + const featureCount = Object.values(features).filter( + isOrdinaryFeatureData, + ).length; const keys = []; const doneKeys = Array.from( - new Set(Object.values(features).flatMap((f) => f.compat_features ?? [])), + new Set( + Object.values(features).flatMap((f) => { + if (isOrdinaryFeatureData(f)) { + return f.compat_features ?? []; + } + return []; + }), + ), ); const toDoKeys = []; @@ -35,6 +45,7 @@ export function stats(detailed: boolean = false) { } const featureSizes = Object.values(features) + .filter(isOrdinaryFeatureData) .map((feature) => (feature.compat_features ?? []).length) .sort((a, b) => a - b); diff --git a/scripts/update-drafts.ts b/scripts/update-drafts.ts index f3fac0babdf..ab84d708596 100644 --- a/scripts/update-drafts.ts +++ b/scripts/update-drafts.ts @@ -11,6 +11,7 @@ import { Document, parse } from "yaml"; import yargs from "yargs"; import { features } from "../index.js"; +import { isOrdinaryFeatureData } from "../type-guards.js"; import { FeatureData } from "../types.js"; type WebSpecsSpec = (typeof webSpecs)[number]; @@ -84,7 +85,7 @@ async function main() { // Build a map of used BCD keys to feature. const webFeatures = new Map(); Object.values(features).map((data) => { - if (data.compat_features) { + if (isOrdinaryFeatureData(data) && data.compat_features) { for (const compatFeature of data.compat_features) { webFeatures.set(compatFeature, data.name); } @@ -261,9 +262,12 @@ async function main() { } // Clean up completed specs, even if they've been superseded - const assignedKeys = Object.values(features).flatMap( - (f) => f.compat_features ?? [], - ); + const assignedKeys = Object.values(features).flatMap((f) => { + if (isOrdinaryFeatureData(f)) { + return f.compat_features ?? []; + } + return []; + }); for (const spec of webSpecs) { const id = formatIdentifier(spec.shortname); const destination = `features/draft/spec/${id}.yml`; diff --git a/type-guards.ts b/type-guards.ts new file mode 100644 index 00000000000..806a88139d4 --- /dev/null +++ b/type-guards.ts @@ -0,0 +1,13 @@ +import type { FeatureData, FeatureMovedData, FeatureSplitData } from "./types"; + +export function isOrdinaryFeatureData(x: unknown): x is FeatureData { + return typeof x === "object" && "kind" in x && x.kind === "feature"; +} + +export function isSplit(x: unknown): x is FeatureSplitData { + return typeof x === "object" && "kind" in x && x.kind === "split"; +} + +export function isMoved(x: unknown): x is FeatureMovedData { + return typeof x === "object" && "kind" in x && x.kind === "moved"; +} diff --git a/types.quicktype.ts b/types.quicktype.ts new file mode 100644 index 00000000000..9ee64a5766f --- /dev/null +++ b/types.quicktype.ts @@ -0,0 +1,221 @@ +/** + * The top-level web-features data package + */ +export interface WebFeaturesData { + /** + * Browsers and browser release data + */ + browsers: Browsers; + /** + * Feature identifiers and data + */ + features: { [key: string]: FeatureData }; + /** + * Group identifiers and data + */ + groups: { [key: string]: GroupData }; + /** + * Snapshot identifiers and data + */ + snapshots: { [key: string]: SnapshotData }; +} + +/** + * Browsers and browser release data + */ +export interface Browsers { + chrome: BrowserData; + chrome_android: BrowserData; + edge: BrowserData; + firefox: BrowserData; + firefox_android: BrowserData; + safari: BrowserData; + safari_ios: BrowserData; +} + +/** + * Browser information + */ +export interface BrowserData { + /** + * The name of the browser, as in "Edge" or "Safari on iOS" + */ + name: string; + releases: Release[]; +} + +/** + * Browser release information + */ +export interface Release { + /** + * The release date, as in "2023-12-11" + */ + date: string; + /** + * The version string, as in "10" or "17.1" + */ + version: string; +} + +/** + * A feature data entry + * + * A feature has permanently moved to exactly one other ID + * + * A feature has split into two or more other features + */ +export interface FeatureData { + /** + * caniuse.com identifiers + */ + caniuse?: string[]; + /** + * Sources of support data for this feature + */ + compat_features?: string[]; + /** + * Short description of the feature, as a plain text string + */ + description?: string; + /** + * Short description of the feature, as an HTML string + */ + description_html?: string; + /** + * Whether developers are formally discouraged from using this feature + */ + discouraged?: Discouraged; + /** + * Group identifiers + */ + group?: string[]; + kind: Kind; + /** + * Short name + */ + name?: string; + /** + * Snapshot identifiers + */ + snapshot?: string[]; + /** + * Specification URLs + */ + spec?: string[]; + /** + * Whether a feature is considered a "Baseline" web platform feature and when it achieved + * that status + */ + status?: StatusHeadline; + /** + * The new ID for this feature + */ + redirect_target?: string; + /** + * The new IDs for this feature + */ + redirect_targets?: string[]; +} + +/** + * Whether developers are formally discouraged from using this feature + */ +export interface Discouraged { + /** + * Links to a formal discouragement notice, such as specification text, intent-to-unship, + * etc. + */ + according_to: string[]; + /** + * IDs for features that substitute some or all of this feature's utility + */ + alternatives?: string[]; +} + +export type Kind = "feature" | "moved" | "split"; + +/** + * Whether a feature is considered a "Baseline" web platform feature and when it achieved + * that status + */ +export interface StatusHeadline { + /** + * Whether the feature is Baseline (low substatus), Baseline (high substatus), or not (false) + */ + baseline: boolean | BaselineEnum; + /** + * Date the feature achieved Baseline high status + */ + baseline_high_date?: string; + /** + * Date the feature achieved Baseline low status + */ + baseline_low_date?: string; + /** + * Statuses for each key in the feature's compat_features list, if applicable. Not available + * to the npm release of web-features. + */ + by_compat_key?: { [key: string]: Status }; + /** + * Browser versions that most-recently introduced the feature + */ + support: Support; +} + +export type BaselineEnum = "high" | "low"; + +export interface Status { + /** + * Whether the feature is Baseline (low substatus), Baseline (high substatus), or not (false) + */ + baseline: boolean | BaselineEnum; + /** + * Date the feature achieved Baseline high status + */ + baseline_high_date?: string; + /** + * Date the feature achieved Baseline low status + */ + baseline_low_date?: string; + /** + * Browser versions that most-recently introduced the feature + */ + support: Support; + [property: string]: any; +} + +/** + * Browser versions that most-recently introduced the feature + */ +export interface Support { + chrome?: string; + chrome_android?: string; + edge?: string; + firefox?: string; + firefox_android?: string; + safari?: string; + safari_ios?: string; +} + +export interface GroupData { + /** + * Short name + */ + name: string; + /** + * Identifier of parent group + */ + parent?: string; +} + +export interface SnapshotData { + /** + * Short name + */ + name: string; + /** + * Specification + */ + spec: string; +} diff --git a/types.ts b/types.ts index d1492262104..c14c124ac4a 100644 --- a/types.ts +++ b/types.ts @@ -1,97 +1,141 @@ -export interface WebFeaturesData { - /** Browsers and browser release data */ - browsers: { [key in BrowserIdentifier]: BrowserData }; - /** Feature identifiers and data */ - features: { [key: string]: FeatureData }; - /** Group identifiers and data */ - groups: { [key: string]: GroupData }; - /** Snapshot identifiers and data */ - snapshots: { [key: string]: SnapshotData }; -} +/* eslint-disable @typescript-eslint/no-unused-vars */ +// Quicktype produces definitions that are correct, but not as narrow or +// well-named as hand-written type definition might produce. This module takes +// the Quicktype-generated types as renames or modifies the types to be somewhat +// nicer to work with in TypeScript. +import type { + BaselineEnum as BaselineHighLow, + BrowserData, + Browsers, + Discouraged, + GroupData, + Kind, + FeatureData as QuicktypeMonolithicFeatureData, + Status as QuicktypeStatus, + StatusHeadline as QuicktypeStatusHeadline, + WebFeaturesData as QuicktypeWebFeaturesData, + Release, + SnapshotData, + Support, +} from "./types.quicktype"; -/** Browser information */ -export interface BrowserData { - /** The name of the browser, as in "Edge" or "Safari on iOS" */ - name: string; - /** The browser's releases */ - releases: Release[]; -} +// Passthrough types +export type { + BaselineHighLow, + BrowserData, + Browsers, + Discouraged, + GroupData, + Release, + SnapshotData, + Support, +}; -/** Browser release information */ -export interface Release { - /** The version string, as in "10" or "17.1" */ - version: string; - /** The release date, as in "2023-12-11" */ - date: string; +export interface Status extends QuicktypeStatus { + baseline: false | BaselineHighLow; } -export interface FeatureData { - /** Short name */ - name: string; - /** Short description of the feature, as a plain text string */ - description: string; - /** Short description of the feature, as an HTML string */ - description_html: string; - /** Specification URL(s) */ - spec: string | [string, string, ...string[]]; - /** Group identifier(s) */ - group?: string | [string, string, ...string[]]; - /** Snapshot identifier(s) */ - snapshot?: string | [string, string, ...string[]]; - /** caniuse.com identifier(s) */ - caniuse?: string | [string, string, ...string[]]; - /** Whether a feature is considered a "baseline" web platform feature and when it achieved that status */ - status: SupportStatus; - /** Sources of support data for this feature */ - compat_features?: string[]; - /** Whether developers are formally discouraged from using this feature */ - discouraged?: Discouraged; +export interface SupportStatus extends QuicktypeStatusHeadline { + baseline: false | BaselineHighLow; } -type BrowserIdentifier = "chrome" | "chrome_android" | "edge" | "firefox" | "firefox_android" | "safari" | "safari_ios"; +// These are "tests" for our type definitions. +const badQuicktypeStatusHeadline: QuicktypeStatusHeadline = { + baseline: true, // This is an improper value in our actual published data + support: {}, +}; +const badQuicktypeStatus: QuicktypeStatus = badQuicktypeStatusHeadline; -type BaselineHighLow = "high" | "low"; +const badSupportStatus: SupportStatus = { + // This validates that we're actually overriding Quicktype (and correctly). If + // `baseline: true` ever becomes possible in the `SupportStatus`, then + // TypeScript will complain about the next line. + // @ts-expect-error + baseline: true, + support: {}, +}; +const badStatus: Status = { + // @ts-expect-error + baseline: true, + support: {}, +}; +const goodSupportStatus: QuicktypeStatusHeadline | SupportStatus = { + baseline: false, + support: {}, +}; -interface Status { - /** Whether the feature is Baseline (low substatus), Baseline (high substatus), or not (false) */ - baseline: BaselineHighLow | false; - /** Date the feature achieved Baseline low status */ - baseline_low_date?: string; - /** Date the feature achieved Baseline high status */ - baseline_high_date?: string; - /** Browser versions that most-recently introduced the feature */ - support: { - [K in BrowserIdentifier]?: string; - }; +export interface WebFeaturesData + extends Pick { + features: { + [key: string]: FeatureData | FeatureMovedData | FeatureSplitData; + }; } -interface SupportStatus extends Status { - /** Statuses for each key in the feature's compat_features list, if applicable. Not available to the npm release of web-features. */ - by_compat_key?: Record -} +export type FeatureData = { kind: "feature" } & Required< + Pick< + QuicktypeMonolithicFeatureData, + "description_html" | "description" | "name" | "spec" | "status" + > +> & + Partial< + Pick< + QuicktypeMonolithicFeatureData, + "caniuse" | "compat_features" | "discouraged" | "group" | "snapshot" + > + >; -interface Discouraged { - /** Links to a formal discouragement notice, such as specification text, intent-to-unship, etc. */ - according_to: string[]; - /** IDs for features that substitute some or all of this feature's utility */ - alternatives?: string[]; - // TODO: alternatives ought to be `(keyof WebFeaturesData["features"])[]` - // but ts-json-schema-generator seems to have long-standing unresolved bugs - // around this. Remove this when - // https://github.com/web-platform-dx/web-features/issues/2722 is resolved. -} +const goodFeatureData: FeatureData = { + kind: "feature", + name: "Test", + description: "Hi", + description_html: "Hi", + spec: [""], + snapshot: [""], + group: [""], + caniuse: [""], + discouraged: { + according_to: [""], + alternatives: [""], + }, + status: { + baseline: false, + support: {}, + }, +}; -export interface GroupData { - /** Short name */ - name: string; - /** Identifier of parent group */ - parent?: string; +type FeatureRedirectData = { kind: Exclude } & Required< + Pick +>; + +export interface FeatureMovedData + extends Omit { + kind: "moved"; } -export interface SnapshotData { - /** Short name */ - name: string; - /** Specification */ - spec: string; +const goodFeatureMovedData: FeatureMovedData = { + kind: "moved", + redirect_target: "", +}; +const badFeatureMovedData: FeatureMovedData = { + kind: "moved", + // @ts-expect-error + redirect_targets: ["", ""], +}; + +export interface FeatureSplitData + extends Omit { + kind: "split"; } + +const goodFeatureSplitData: FeatureSplitData = { + kind: "split", + redirect_targets: ["", ""], +}; +const badFeatureSplitData: FeatureSplitData = { + kind: "split", + // @ts-expect-error + redirect_target: "", +}; + +export type BrowserIdentifier = keyof Browsers;