From 30d8ee2e022f679c16a22a6e60df7414d37316ba Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Feb 2026 20:16:53 +0100 Subject: [PATCH 001/128] =?UTF-8?q?refactor:=20rename=20mongo=E2=86=92data?= =?UTF-8?q?-api,=20MongoBSONTypes=E2=86=92BSONTypes=20+=20fix=20array=20st?= =?UTF-8?q?ats=20bugs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Group A of SchemaAnalyzer refactor: - Fix A1: array element stats overwrite bug (isNewTypeEntry) - Fix A2: probability >100% for array-embedded objects (x-documentsInspected) - Rename folder: src/utils/json/mongo/ → src/utils/json/data-api/ - Rename enum: MongoBSONTypes → BSONTypes - Rename file: MongoValueFormatters → ValueFormatters - Add 9 new tests for array stats and probability --- .gitignore | 3 + src/documentdb/ClusterSession.ts | 2 +- src/utils/json/data-api/BSONTypes.ts | 200 ++++++++ .../SchemaAnalyzer.arrayStats.test.ts | 459 ++++++++++++++++++ .../SchemaAnalyzer.test.ts | 0 .../{mongo => data-api}/SchemaAnalyzer.ts | 130 ++--- .../ValueFormatters.ts} | 52 +- .../basicMongoFindFilterSchema.json | 0 .../generateMongoFindJsonSchema.ts | 0 .../autocomplete/getKnownFields.ts | 0 .../{mongo => data-api}/mongoTestDocuments.ts | 0 src/utils/json/mongo/MongoBSONTypes.ts | 200 -------- src/utils/slickgrid/mongo/toSlickGridTable.ts | 12 +- src/utils/slickgrid/mongo/toSlickGridTree.ts | 12 +- .../collectionView/collectionViewRouter.ts | 6 +- .../components/queryEditor/QueryEditor.tsx | 2 +- 16 files changed, 775 insertions(+), 303 deletions(-) create mode 100644 src/utils/json/data-api/BSONTypes.ts create mode 100644 src/utils/json/data-api/SchemaAnalyzer.arrayStats.test.ts rename src/utils/json/{mongo => data-api}/SchemaAnalyzer.test.ts (100%) rename src/utils/json/{mongo => data-api}/SchemaAnalyzer.ts (85%) rename src/utils/json/{mongo/MongoValueFormatters.ts => data-api/ValueFormatters.ts} (63%) rename src/utils/json/{mongo => data-api}/autocomplete/basicMongoFindFilterSchema.json (100%) rename src/utils/json/{mongo => data-api}/autocomplete/generateMongoFindJsonSchema.ts (100%) rename src/utils/json/{mongo => data-api}/autocomplete/getKnownFields.ts (100%) rename src/utils/json/{mongo => data-api}/mongoTestDocuments.ts (100%) delete mode 100644 src/utils/json/mongo/MongoBSONTypes.ts diff --git a/.gitignore b/.gitignore index 7bc4f395e..ea5798951 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. +/docs/analysis/ +/docs/plan/ + # User-specific files *.suo *.user diff --git a/src/documentdb/ClusterSession.ts b/src/documentdb/ClusterSession.ts index da81218fe..b4ac8f3b1 100644 --- a/src/documentdb/ClusterSession.ts +++ b/src/documentdb/ClusterSession.ts @@ -7,7 +7,7 @@ import * as l10n from '@vscode/l10n'; import { EJSON } from 'bson'; import { ObjectId, type Document, type Filter, type WithId } from 'mongodb'; import { type JSONSchema } from '../utils/json/JSONSchema'; -import { getPropertyNamesAtLevel, updateSchemaWithDocument } from '../utils/json/mongo/SchemaAnalyzer'; +import { getPropertyNamesAtLevel, updateSchemaWithDocument } from '../utils/json/data-api/SchemaAnalyzer'; import { getDataAtPath } from '../utils/slickgrid/mongo/toSlickGridTable'; import { toSlickGridTree, type TreeData } from '../utils/slickgrid/mongo/toSlickGridTree'; import { ClustersClient, type FindQueryParams } from './ClustersClient'; diff --git a/src/utils/json/data-api/BSONTypes.ts b/src/utils/json/data-api/BSONTypes.ts new file mode 100644 index 000000000..ef52911e7 --- /dev/null +++ b/src/utils/json/data-api/BSONTypes.ts @@ -0,0 +1,200 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { + Binary, + BSONSymbol, + Code, + DBRef, + Decimal128, + Double, + Int32, + Long, + MaxKey, + MinKey, + ObjectId, + Timestamp, + UUID, +} from 'mongodb'; + +/** + * Represents the different data types that can be stored in a MongoDB document. + * The string representation is casesensitive and should match the MongoDB documentation. + * https://www.mongodb.com/docs/manual/reference/bson-types/ + */ +export enum BSONTypes { + String = 'string', + Number = 'number', + Int32 = 'int32', + Double = 'double', + Decimal128 = 'decimal128', + Long = 'long', + Boolean = 'boolean', + Object = 'object', + Array = 'array', + Null = 'null', + Undefined = 'undefined', + Date = 'date', + RegExp = 'regexp', + Binary = 'binary', + ObjectId = 'objectid', + Symbol = 'symbol', + Timestamp = 'timestamp', + UUID = 'uuid', + UUID_LEGACY = 'uuid-legacy', // old UUID subtype, used in some legacy data + MinKey = 'minkey', + MaxKey = 'maxkey', + DBRef = 'dbref', + Code = 'code', + CodeWithScope = 'codewithscope', + Map = 'map', + // Add any deprecated types if necessary + _UNKNOWN_ = '_unknown_', // Catch-all for unknown types +} + +export namespace BSONTypes { + const displayStringMap: Record = { + [BSONTypes.String]: 'String', + [BSONTypes.Number]: 'Number', + [BSONTypes.Int32]: 'Int32', + [BSONTypes.Double]: 'Double', + [BSONTypes.Decimal128]: 'Decimal128', + [BSONTypes.Long]: 'Long', + [BSONTypes.Boolean]: 'Boolean', + [BSONTypes.Object]: 'Object', + [BSONTypes.Array]: 'Array', + [BSONTypes.Null]: 'Null', + [BSONTypes.Undefined]: 'Undefined', + [BSONTypes.Date]: 'Date', + [BSONTypes.RegExp]: 'RegExp', + [BSONTypes.Binary]: 'Binary', + [BSONTypes.ObjectId]: 'ObjectId', + [BSONTypes.Symbol]: 'Symbol', + [BSONTypes.Timestamp]: 'Timestamp', + [BSONTypes.MinKey]: 'MinKey', + [BSONTypes.MaxKey]: 'MaxKey', + [BSONTypes.DBRef]: 'DBRef', + [BSONTypes.Code]: 'Code', + [BSONTypes.CodeWithScope]: 'CodeWithScope', + [BSONTypes.Map]: 'Map', + [BSONTypes._UNKNOWN_]: 'Unknown', + [BSONTypes.UUID]: 'UUID', + [BSONTypes.UUID_LEGACY]: 'UUID (Legacy)', + }; + + export function toDisplayString(type: BSONTypes): string { + return displayStringMap[type] || 'Unknown'; + } + + export function toString(type: BSONTypes): string { + return type; + } + + /** + * Converts a MongoDB data type to a case sensitive JSON data type + * @param type The MongoDB data type + * @returns A corresponding JSON data type (please note: it's case sensitive) + */ + export function toJSONType(type: BSONTypes): string { + switch (type) { + case BSONTypes.String: + case BSONTypes.Symbol: + case BSONTypes.Date: + case BSONTypes.Timestamp: + case BSONTypes.ObjectId: + case BSONTypes.RegExp: + case BSONTypes.Binary: + case BSONTypes.Code: + case BSONTypes.UUID: + case BSONTypes.UUID_LEGACY: + return 'string'; + + case BSONTypes.Boolean: + return 'boolean'; + + case BSONTypes.Int32: + case BSONTypes.Long: + case BSONTypes.Double: + case BSONTypes.Decimal128: + return 'number'; + + case BSONTypes.Object: + case BSONTypes.Map: + case BSONTypes.DBRef: + case BSONTypes.CodeWithScope: + return 'object'; + + case BSONTypes.Array: + return 'array'; + + case BSONTypes.Null: + case BSONTypes.Undefined: + case BSONTypes.MinKey: + case BSONTypes.MaxKey: + return 'null'; + + default: + return 'string'; // Default to string for unknown types + } + } + + /** + * Accepts a value from a MongoDB 'Document' object and returns the inferred type. + * @param value The value of a field in a MongoDB 'Document' object + * @returns + */ + export function inferType(value: unknown): BSONTypes { + if (value === null) return BSONTypes.Null; + if (value === undefined) return BSONTypes.Undefined; + + switch (typeof value) { + case 'string': + return BSONTypes.String; + case 'number': + return BSONTypes.Double; // JavaScript numbers are doubles + case 'boolean': + return BSONTypes.Boolean; + case 'object': + if (Array.isArray(value)) { + return BSONTypes.Array; + } + + // Check for common BSON types first + if (value instanceof ObjectId) return BSONTypes.ObjectId; + if (value instanceof Int32) return BSONTypes.Int32; + if (value instanceof Double) return BSONTypes.Double; + if (value instanceof Date) return BSONTypes.Date; + if (value instanceof Timestamp) return BSONTypes.Timestamp; + + // Less common types + if (value instanceof Decimal128) return BSONTypes.Decimal128; + if (value instanceof Long) return BSONTypes.Long; + if (value instanceof MinKey) return BSONTypes.MinKey; + if (value instanceof MaxKey) return BSONTypes.MaxKey; + if (value instanceof BSONSymbol) return BSONTypes.Symbol; + if (value instanceof DBRef) return BSONTypes.DBRef; + if (value instanceof Map) return BSONTypes.Map; + if (value instanceof UUID && value.sub_type === Binary.SUBTYPE_UUID) return BSONTypes.UUID; + if (value instanceof UUID && value.sub_type === Binary.SUBTYPE_UUID_OLD) + return BSONTypes.UUID_LEGACY; + if (value instanceof Buffer || value instanceof Binary) return BSONTypes.Binary; + if (value instanceof RegExp) return BSONTypes.RegExp; + if (value instanceof Code) { + if (value.scope) { + return BSONTypes.CodeWithScope; + } else { + return BSONTypes.Code; + } + } + + // Default to Object if none of the above match + return BSONTypes.Object; + default: + // This should never happen, but if it does, we'll catch it here + // TODO: add telemetry somewhere to know when it happens (not here, this could get hit too often) + return BSONTypes._UNKNOWN_; + } + } +} diff --git a/src/utils/json/data-api/SchemaAnalyzer.arrayStats.test.ts b/src/utils/json/data-api/SchemaAnalyzer.arrayStats.test.ts new file mode 100644 index 000000000..6933315da --- /dev/null +++ b/src/utils/json/data-api/SchemaAnalyzer.arrayStats.test.ts @@ -0,0 +1,459 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ObjectId, type Document, type WithId } from 'mongodb'; +import { type JSONSchema } from '../JSONSchema'; +import { updateSchemaWithDocument } from './SchemaAnalyzer'; + +/** + * This test file investigates the array element occurrence/stats problem. + * + * The core issue: When an array contains mixed types (e.g., strings AND objects), + * `x-typeOccurrence` on the items' type entries counts individual elements across + * ALL documents, not occurrences-per-document. This makes "field presence probability" + * for nested object properties inside arrays hard to interpret. + * + * Example scenario: + * doc1.data = ["a", "b", "c", {"value": 23}] → 3 strings, 1 object + * doc2.data = ["x", "y", {"value": 42, "flag": true}] → 2 strings, 1 object + * doc3.data = ["z"] → 1 string, 0 objects + * + * After processing 3 docs: + * - items.anyOf[string].x-typeOccurrence = 6 (total string elements across all docs) + * - items.anyOf[object].x-typeOccurrence = 2 (total object elements across all docs) + * - items.anyOf[object].properties.value.x-occurrence = 2 (from 2 object elements) + * - items.anyOf[object].properties.flag.x-occurrence = 1 (from 1 object element) + * + * The problem: what is items.anyOf[object].properties.value's "probability"? + * - 2/2? (present in every object element → makes sense) + * - 2/3? (present in 2 of 3 documents → misleading, doc3 has no objects at all) + * - 2/6? (present in 2 of 6 total elements → nonsensical, mixes types) + * + * There's no x-documentsInspected equivalent at the array level to anchor + * the occurrence count. + */ +describe('Array element occurrence analysis', () => { + it('counts element types across multiple documents', () => { + const schema: JSONSchema = {}; + + const doc1: WithId = { + _id: new ObjectId(), + data: ['a', 'b', 'c', { value: 23 }], + }; + const doc2: WithId = { + _id: new ObjectId(), + data: ['x', 'y', { value: 42, flag: true }], + }; + const doc3: WithId = { + _id: new ObjectId(), + data: ['z'], + }; + + updateSchemaWithDocument(schema, doc1); + updateSchemaWithDocument(schema, doc2); + updateSchemaWithDocument(schema, doc3); + + // data field: array seen in 3 docs + const dataField = schema.properties?.['data'] as JSONSchema; + expect(dataField['x-occurrence']).toBe(3); + + // The array type entry + const arrayTypeEntry = dataField.anyOf?.find((e) => (e as JSONSchema)['x-bsonType'] === 'array') as JSONSchema; + expect(arrayTypeEntry).toBeDefined(); + expect(arrayTypeEntry['x-typeOccurrence']).toBe(3); + + // Array items + const itemsSchema = arrayTypeEntry.items as JSONSchema; + const stringEntry = itemsSchema.anyOf?.find((e) => (e as JSONSchema)['x-bsonType'] === 'string') as JSONSchema; + const objectEntry = itemsSchema.anyOf?.find((e) => (e as JSONSchema)['x-bsonType'] === 'object') as JSONSchema; + + // String elements: "a","b","c","x","y","z" = 6 total + expect(stringEntry['x-typeOccurrence']).toBe(6); + + // Object elements: {value:23}, {value:42,flag:true} = 2 total + expect(objectEntry['x-typeOccurrence']).toBe(2); + + // Properties inside the object elements + const valueField = objectEntry.properties?.['value'] as JSONSchema; + const flagField = objectEntry.properties?.['flag'] as JSONSchema; + + // "value" appeared in both objects → x-occurrence = 2 + expect(valueField['x-occurrence']).toBe(2); + + // "flag" appeared in 1 object → x-occurrence = 1 + expect(flagField['x-occurrence']).toBe(1); + + // THE CORE QUESTION: What is the denominator for probability? + // + // We know objectEntry['x-typeOccurrence'] = 2 (2 objects total across all arrays). + // So valueField probability = 2/2 = 100% (correct: every object had "value") + // And flagField probability = 1/2 = 50% (correct: half of objects had "flag") + // + // BUT: there is NO x-documentsInspected on objectEntry to formally define + // the denominator. The consumer has to know to use x-typeOccurrence as the + // denominator for nested properties inside array elements. + // + // This actually WORKS — the semantics are: + // "of the N objects observed inside this array, M had this property" + // + // It just isn't obvious from the schema structure. + }); + + it('tracks min/max array lengths across documents', () => { + const schema: JSONSchema = {}; + + const doc1: WithId = { + _id: new ObjectId(), + tags: ['a', 'b', 'c'], + }; + const doc2: WithId = { + _id: new ObjectId(), + tags: ['x'], + }; + const doc3: WithId = { + _id: new ObjectId(), + tags: ['p', 'q', 'r', 's', 't'], + }; + + updateSchemaWithDocument(schema, doc1); + updateSchemaWithDocument(schema, doc2); + updateSchemaWithDocument(schema, doc3); + + const tagsField = schema.properties?.['tags'] as JSONSchema; + const arrayEntry = tagsField.anyOf?.find((e) => (e as JSONSchema)['x-bsonType'] === 'array') as JSONSchema; + + expect(arrayEntry['x-minItems']).toBe(1); + expect(arrayEntry['x-maxItems']).toBe(5); + }); + + it('accumulates nested object properties from objects inside arrays across documents', () => { + const schema: JSONSchema = {}; + + // doc1 has two objects with different properties in the items array + const doc1: WithId = { + _id: new ObjectId(), + items: [ + { name: 'Laptop', price: 999 }, + { name: 'Mouse', price: 29, discount: true }, + ], + }; + + // doc2 has one object with yet another property + const doc2: WithId = { + _id: new ObjectId(), + items: [{ name: 'Desk', weight: 50 }], + }; + + updateSchemaWithDocument(schema, doc1); + updateSchemaWithDocument(schema, doc2); + + const itemsField = schema.properties?.['items'] as JSONSchema; + const arrayEntry = itemsField.anyOf?.find((e) => (e as JSONSchema)['x-bsonType'] === 'array') as JSONSchema; + const objEntry = (arrayEntry.items as JSONSchema).anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'object', + ) as JSONSchema; + + const props = objEntry.properties as JSONSchema; + + // "name" appeared in all 3 object elements + expect((props['name'] as JSONSchema)['x-occurrence']).toBe(3); + + // "price" appeared in 2 of 3 object elements + expect((props['price'] as JSONSchema)['x-occurrence']).toBe(2); + + // "discount" appeared in 1 of 3 object elements + expect((props['discount'] as JSONSchema)['x-occurrence']).toBe(1); + + // "weight" appeared in 1 of 3 object elements + expect((props['weight'] as JSONSchema)['x-occurrence']).toBe(1); + + // Total object elements = 3 (2 from doc1 + 1 from doc2) + expect(objEntry['x-typeOccurrence']).toBe(3); + + // So probability interpretations: + // name: 3/3 = 100% + // price: 2/3 = 67% + // discount: 1/3 = 33% + // weight: 1/3 = 33% + // + // This is correct! x-typeOccurrence serves as the denominator. + }); + + it('handles arrays that ONLY contain primitives (no occurrence complexity)', () => { + const schema: JSONSchema = {}; + + const doc1: WithId = { + _id: new ObjectId(), + scores: [90, 85, 78], + }; + const doc2: WithId = { + _id: new ObjectId(), + scores: [100, 55], + }; + + updateSchemaWithDocument(schema, doc1); + updateSchemaWithDocument(schema, doc2); + + const scoresField = schema.properties?.['scores'] as JSONSchema; + const arrayEntry = scoresField.anyOf?.find((e) => (e as JSONSchema)['x-bsonType'] === 'array') as JSONSchema; + + const numEntry = (arrayEntry.items as JSONSchema).anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'double', + ) as JSONSchema; + + // 5 total numeric elements + expect(numEntry['x-typeOccurrence']).toBe(5); + + // Stats across all elements + expect(numEntry['x-minValue']).toBe(55); + expect(numEntry['x-maxValue']).toBe(100); + + // Array length stats + expect(arrayEntry['x-minItems']).toBe(2); + expect(arrayEntry['x-maxItems']).toBe(3); + }); + + it('verifies that encounteredMongoTypes map is per-document', () => { + // The encounteredMongoTypes map is created inside the Array case handler. + // It controls whether initializeStatsForValue or aggregateStatsForValue is called. + // If it's per-array-occurrence (per document), stats should initialize fresh for each doc. + // + // BUT WAIT: The map is local to the switch case, which processes ONE array per queue item. + // Multiple documents contribute different queue items, and the map is re-created for each. + // However, the stats update goes to the SAME itemEntry across documents (because + // findTypeEntry finds the existing entry). So: + // + // doc1.scores = [10, 20] → first array processing, encounteredMongoTypes fresh + // - element 10: initializeStatsForValue (sets x-minValue=10, x-maxValue=10) + // - element 20: aggregateStatsForValue (updates x-maxValue=20) + // + // doc2.scores = [5, 30] → second array processing, encounteredMongoTypes fresh + // - element 5: initializeStatsForValue ← BUT x-minValue is already 10 from doc1! + // initializeStatsForValue OVERWRITES x-minValue to 5 (correct by accident here) + // Actually let's check... initializeStatsForValue sets x-maxValue = 5 + // and x-minValue = 5. So the 20 from doc1 would be lost! + // + // This is a REAL BUG: initializeStatsForValue is called for the first occurrence + // per array, but the typeEntry already has stats from previous arrays. + + const schema: JSONSchema = {}; + + const doc1: WithId = { + _id: new ObjectId(), + scores: [10, 20, 30], + }; + const doc2: WithId = { + _id: new ObjectId(), + scores: [5, 15], + }; + + updateSchemaWithDocument(schema, doc1); + updateSchemaWithDocument(schema, doc2); + + const scoresField = schema.properties?.['scores'] as JSONSchema; + const arrayEntry = scoresField.anyOf?.find((e) => (e as JSONSchema)['x-bsonType'] === 'array') as JSONSchema; + + const numEntry = (arrayEntry.items as JSONSchema).anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'double', + ) as JSONSchema; + + // Expected correct values: + // All 5 elements: 10, 20, 30, 5, 15 + // Global min = 5, global max = 30 + + // If there's a bug, doc2 processing re-initializes: + // after doc1: min=10, max=30 + // doc2 first element (5): initializeStatsForValue → sets min=5, max=5 + // doc2 second element (15): aggregateStatsForValue → max becomes 15 + // final: min=5, max=15 ← WRONG (lost 30 from doc1) + + // Let's check what actually happens: + console.log('numEntry x-minValue:', numEntry['x-minValue']); + console.log('numEntry x-maxValue:', numEntry['x-maxValue']); + + // This test documents the actual behavior (might be buggy): + expect(numEntry['x-minValue']).toBe(5); + // If the bug exists, this will be 15 instead of 30: + expect(numEntry['x-maxValue']).toBe(30); // should be 30 if correct + }); +}); + +describe('Array probability denominator problem', () => { + it('reproduces the >100% probability bug: empty array + large array', () => { + // User scenario: + // doc1: a = [] → 0 objects + // doc2: a = [{b:1}, {b:2}, ..., {b:100}] → 100 objects + // + // Naively computing probability as: + // occurrence_of_b / root.x-documentsInspected = 100 / 2 = 5000% + // + // The correct probability should be: + // occurrence_of_b / objectEntry.x-typeOccurrence = 100 / 100 = 100% + // + // FIX: Set x-documentsInspected on the object type entry so the uniform + // formula `x-occurrence / parent.x-documentsInspected` works at every + // nesting level. + + const schema: JSONSchema = {}; + + const doc1: WithId = { + _id: new ObjectId(), + a: [], // empty array + }; + + // doc2: 100 objects, each with property "b" + const objectElements: Record[] = []; + for (let i = 1; i <= 100; i++) { + objectElements.push({ b: i }); + } + const doc2: WithId = { + _id: new ObjectId(), + a: objectElements, + }; + + updateSchemaWithDocument(schema, doc1); + updateSchemaWithDocument(schema, doc2); + + // Root level + expect(schema['x-documentsInspected']).toBe(2); + + // Navigate to the object type entry inside the array + const aField = schema.properties?.['a'] as JSONSchema; + expect(aField['x-occurrence']).toBe(2); // both docs have 'a' + + const arrayEntry = aField.anyOf?.find((e) => (e as JSONSchema)['x-bsonType'] === 'array') as JSONSchema; + const objectEntry = (arrayEntry.items as JSONSchema).anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'object', + ) as JSONSchema; + + // 100 object elements total + expect(objectEntry['x-typeOccurrence']).toBe(100); + + // Property "b" appears in all 100 objects + const bField = objectEntry.properties?.['b'] as JSONSchema; + expect(bField['x-occurrence']).toBe(100); + + // THE FIX: objectEntry should have x-documentsInspected = 100 + // so that the uniform formula works: + // probability = b.x-occurrence / objectEntry.x-documentsInspected + // = 100 / 100 = 100% + expect(objectEntry['x-documentsInspected']).toBe(100); + }); + + it('correctly computes probability for sparse properties in array objects', () => { + // doc1: items = [{name:"A", price:10}, {name:"B"}] → 2 objects, name in both, price in 1 + // doc2: items = [{name:"C", discount:true}] → 1 object + // + // Total objects = 3 + // name: 3/3 = 100% + // price: 1/3 = 33% + // discount: 1/3 = 33% + + const schema: JSONSchema = {}; + + const doc1: WithId = { + _id: new ObjectId(), + items: [{ name: 'A', price: 10 }, { name: 'B' }], + }; + const doc2: WithId = { + _id: new ObjectId(), + items: [{ name: 'C', discount: true }], + }; + + updateSchemaWithDocument(schema, doc1); + updateSchemaWithDocument(schema, doc2); + + const itemsField = schema.properties?.['items'] as JSONSchema; + const arrayEntry = itemsField.anyOf?.find((e) => (e as JSONSchema)['x-bsonType'] === 'array') as JSONSchema; + const objectEntry = (arrayEntry.items as JSONSchema).anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'object', + ) as JSONSchema; + + // The object type entry should have x-documentsInspected = 3 + expect(objectEntry['x-documentsInspected']).toBe(3); + + const props = objectEntry.properties as Record; + + // Probability = x-occurrence / x-documentsInspected (uniform formula) + expect(props['name']['x-occurrence']).toBe(3); // 3/3 = 100% + expect(props['price']['x-occurrence']).toBe(1); // 1/3 = 33% + expect(props['discount']['x-occurrence']).toBe(1); // 1/3 = 33% + }); + + it('sets x-documentsInspected on nested objects at all levels', () => { + // items: [{address: {city: "NY", zip: "10001"}}, {address: {city: "LA"}}] + // + // At items.anyOf[object] level: x-documentsInspected = 2 + // At address.anyOf[object] level: x-documentsInspected = 2 + // city: 2/2 = 100%, zip: 1/2 = 50% + + const schema: JSONSchema = {}; + + const doc: WithId = { + _id: new ObjectId(), + items: [{ address: { city: 'NY', zip: '10001' } }, { address: { city: 'LA' } }], + }; + + updateSchemaWithDocument(schema, doc); + + const itemsField = schema.properties?.['items'] as JSONSchema; + const arrayEntry = itemsField.anyOf?.find((e) => (e as JSONSchema)['x-bsonType'] === 'array') as JSONSchema; + const objectEntry = (arrayEntry.items as JSONSchema).anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'object', + ) as JSONSchema; + + // 2 objects in the array + expect(objectEntry['x-documentsInspected']).toBe(2); + + // address.anyOf[object] — the nested object type + const addressProp = objectEntry.properties?.['address'] as JSONSchema; + const addressObjEntry = addressProp.anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'object', + ) as JSONSchema; + + // Both objects had address, and both addresses were objects + expect(addressObjEntry['x-documentsInspected']).toBe(2); + + const addrProps = addressObjEntry.properties as Record; + expect(addrProps['city']['x-occurrence']).toBe(2); // 2/2 = 100% + expect(addrProps['zip']['x-occurrence']).toBe(1); // 1/2 = 50% + }); + + it('does NOT change x-documentsInspected at root level (root keeps document count)', () => { + const schema: JSONSchema = {}; + + const doc1: WithId = { + _id: new ObjectId(), + name: 'Alice', + address: { city: 'NY' }, + }; + const doc2: WithId = { + _id: new ObjectId(), + name: 'Bob', + address: { city: 'LA', zip: '90001' }, + }; + + updateSchemaWithDocument(schema, doc1); + updateSchemaWithDocument(schema, doc2); + + // Root x-documentsInspected is document count, not affected by the fix + expect(schema['x-documentsInspected']).toBe(2); + + // Root-level probability still works: name.occurrence(2) / documentsInspected(2) = 100% + const nameField = schema.properties?.['name'] as JSONSchema; + expect(nameField['x-occurrence']).toBe(2); + + // Nested object: address.anyOf[object] should have x-documentsInspected = 2 + const addressField = schema.properties?.['address'] as JSONSchema; + const addressObjEntry = addressField.anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'object', + ) as JSONSchema; + expect(addressObjEntry['x-documentsInspected']).toBe(2); + + const addrProps = addressObjEntry.properties as Record; + expect(addrProps['city']['x-occurrence']).toBe(2); // 2/2 = 100% + expect(addrProps['zip']['x-occurrence']).toBe(1); // 1/2 = 50% + }); +}); diff --git a/src/utils/json/mongo/SchemaAnalyzer.test.ts b/src/utils/json/data-api/SchemaAnalyzer.test.ts similarity index 100% rename from src/utils/json/mongo/SchemaAnalyzer.test.ts rename to src/utils/json/data-api/SchemaAnalyzer.test.ts diff --git a/src/utils/json/mongo/SchemaAnalyzer.ts b/src/utils/json/data-api/SchemaAnalyzer.ts similarity index 85% rename from src/utils/json/mongo/SchemaAnalyzer.ts rename to src/utils/json/data-api/SchemaAnalyzer.ts index 278f51fc4..bc97dff49 100644 --- a/src/utils/json/mongo/SchemaAnalyzer.ts +++ b/src/utils/json/data-api/SchemaAnalyzer.ts @@ -60,7 +60,7 @@ import { assert } from 'console'; import Denque from 'denque'; import { type Document, type WithId } from 'mongodb'; import { type JSONSchema } from '../JSONSchema'; -import { MongoBSONTypes } from './MongoBSONTypes'; +import { BSONTypes } from './BSONTypes'; export function updateSchemaWithDocument(schema: JSONSchema, document: WithId): void { // Initialize schema if it's empty @@ -74,7 +74,7 @@ export function updateSchemaWithDocument(schema: JSONSchema, document: WithId; const objKeysCount = Object.keys(objValue).length; // Update min and max property counts updateMinMaxStats(item.propertySchema, 'x-minProperties', 'x-maxProperties', objKeysCount); + // Track how many object instances contributed to this sub-schema. + // This enables uniform probability computation at every nesting level: + // probability = property.x-occurrence / parentObject.x-documentsInspected + // + // Without this, array-embedded objects have no denominator for probability. + // Example: doc1.a=[], doc2.a=[{b:1},...,{b:100}] + // b.x-occurrence = 100, root.x-documentsInspected = 2 + // Naive: 100/2 = 5000% — wrong! + // With fix: objectEntry.x-documentsInspected = 100, so 100/100 = 100% + item.propertySchema['x-documentsInspected'] = (item.propertySchema['x-documentsInspected'] ?? 0) + 1; + // Ensure 'properties' exists if (!item.propertySchema.properties) { item.propertySchema.properties = {}; @@ -158,7 +169,7 @@ export function updateSchemaWithDocument(schema: JSONSchema, document: WithId = new Map(); - // Iterate over the array elements for (const element of arrayValue) { - const elementMongoType = MongoBSONTypes.inferType(element); + const elementMongoType = BSONTypes.inferType(element); // Find or create the type entry in 'items.anyOf' let itemEntry = findTypeEntry(itemsSchema.anyOf as JSONSchema[], elementMongoType); + const isNewTypeEntry = !itemEntry; if (!itemEntry) { // Create a new type entry itemEntry = { - type: MongoBSONTypes.toJSONType(elementMongoType), + type: BSONTypes.toJSONType(elementMongoType), 'x-bsonType': elementMongoType, 'x-typeOccurrence': 0, }; @@ -249,18 +258,19 @@ export function updateSchemaWithDocument(schema: JSONSchema, document: WithId entry['x-bsonType'] === bsonType); } @@ -314,7 +324,7 @@ export function getSchemaFromDocument(document: WithId): JSONSchema { type WorkItem = { fieldName: string; - fieldMongoType: MongoBSONTypes; // the inferred BSON type + fieldMongoType: BSONTypes; // the inferred BSON type propertyTypeEntry: JSONSchema; // points to the entry within the 'anyOf' property of the schema fieldValue: unknown; pathSoFar: string; // used for debugging @@ -329,10 +339,10 @@ export function getSchemaFromDocument(document: WithId): JSONSchema { * Push all elements from the root of the document into the queue */ for (const [name, value] of Object.entries(document)) { - const mongoDatatype = MongoBSONTypes.inferType(value); + const mongoDatatype = BSONTypes.inferType(value); const typeEntry = { - type: MongoBSONTypes.toJSONType(mongoDatatype), + type: BSONTypes.toJSONType(mongoDatatype), 'x-bsonType': mongoDatatype, 'x-typeOccurrence': 1, }; @@ -362,7 +372,7 @@ export function getSchemaFromDocument(document: WithId): JSONSchema { } switch (item.fieldMongoType) { - case MongoBSONTypes.Object: { + case BSONTypes.Object: { const objKeys = Object.keys(item.fieldValue as object).length; item.propertyTypeEntry['x-maxLength'] = objKeys; item.propertyTypeEntry['x-minLength'] = objKeys; @@ -371,10 +381,10 @@ export function getSchemaFromDocument(document: WithId): JSONSchema { item.propertyTypeEntry.properties = {}; for (const [name, value] of Object.entries(item.fieldValue as object)) { - const mongoDatatype = MongoBSONTypes.inferType(value); + const mongoDatatype = BSONTypes.inferType(value); const typeEntry = { - type: MongoBSONTypes.toJSONType(mongoDatatype), + type: BSONTypes.toJSONType(mongoDatatype), 'x-bsonType': mongoDatatype, 'x-typeOccurrence': 1, }; @@ -392,7 +402,7 @@ export function getSchemaFromDocument(document: WithId): JSONSchema { } break; } - case MongoBSONTypes.Array: { + case BSONTypes.Array: { const arrayLength = (item.fieldValue as unknown[]).length; item.propertyTypeEntry['x-maxLength'] = arrayLength; item.propertyTypeEntry['x-minLength'] = arrayLength; @@ -401,17 +411,17 @@ export function getSchemaFromDocument(document: WithId): JSONSchema { item.propertyTypeEntry.items = {}; item.propertyTypeEntry.items.anyOf = []; - const encounteredMongoTypes: Map = new Map(); + const encounteredMongoTypes: Map = new Map(); // iterate over the array and infer the type of each element for (const element of item.fieldValue as unknown[]) { - const elementMongoType = MongoBSONTypes.inferType(element); + const elementMongoType = BSONTypes.inferType(element); let itemEntry: JSONSchema; if (!encounteredMongoTypes.has(elementMongoType)) { itemEntry = { - type: MongoBSONTypes.toJSONType(elementMongoType), + type: BSONTypes.toJSONType(elementMongoType), 'x-bsonType': elementMongoType, 'x-typeOccurrence': 1, // Initialize type occurrence counter }; @@ -435,7 +445,7 @@ export function getSchemaFromDocument(document: WithId): JSONSchema { // an imporant exception for arrays as we have to start adding them already now to the schema // (if we want to avoid more iterations over the data) - if (elementMongoType === MongoBSONTypes.Object || elementMongoType === MongoBSONTypes.Array) { + if (elementMongoType === BSONTypes.Object || elementMongoType === BSONTypes.Array) { fifoQueue.push({ fieldName: '[]', // Array items don't have a field name fieldMongoType: elementMongoType, @@ -464,56 +474,56 @@ export function getSchemaFromDocument(document: WithId): JSONSchema { * Helper function to compute stats for a value based on its MongoDB data type * Updates the provided propertyTypeEntry with the computed stats */ -function initializeStatsForValue(value: unknown, mongoType: MongoBSONTypes, propertyTypeEntry: JSONSchema): void { +function initializeStatsForValue(value: unknown, mongoType: BSONTypes, propertyTypeEntry: JSONSchema): void { switch (mongoType) { - case MongoBSONTypes.String: { + case BSONTypes.String: { const currentLength = (value as string).length; propertyTypeEntry['x-maxLength'] = currentLength; propertyTypeEntry['x-minLength'] = currentLength; break; } - case MongoBSONTypes.Number: - case MongoBSONTypes.Int32: - case MongoBSONTypes.Long: - case MongoBSONTypes.Double: - case MongoBSONTypes.Decimal128: { + case BSONTypes.Number: + case BSONTypes.Int32: + case BSONTypes.Long: + case BSONTypes.Double: + case BSONTypes.Decimal128: { const numericValue = Number(value); propertyTypeEntry['x-maxValue'] = numericValue; propertyTypeEntry['x-minValue'] = numericValue; break; } - case MongoBSONTypes.Boolean: { + case BSONTypes.Boolean: { const boolValue = value as boolean; propertyTypeEntry['x-trueCount'] = boolValue ? 1 : 0; propertyTypeEntry['x-falseCount'] = boolValue ? 0 : 1; break; } - case MongoBSONTypes.Date: { + case BSONTypes.Date: { const dateValue = (value as Date).getTime(); propertyTypeEntry['x-maxDate'] = dateValue; propertyTypeEntry['x-minDate'] = dateValue; break; } - case MongoBSONTypes.Binary: { + case BSONTypes.Binary: { const binaryLength = (value as Buffer).length; propertyTypeEntry['x-maxLength'] = binaryLength; propertyTypeEntry['x-minLength'] = binaryLength; break; } - case MongoBSONTypes.Null: - case MongoBSONTypes.RegExp: - case MongoBSONTypes.ObjectId: - case MongoBSONTypes.MinKey: - case MongoBSONTypes.MaxKey: - case MongoBSONTypes.Symbol: - case MongoBSONTypes.Timestamp: - case MongoBSONTypes.DBRef: - case MongoBSONTypes.Map: + case BSONTypes.Null: + case BSONTypes.RegExp: + case BSONTypes.ObjectId: + case BSONTypes.MinKey: + case BSONTypes.MaxKey: + case BSONTypes.Symbol: + case BSONTypes.Timestamp: + case BSONTypes.DBRef: + case BSONTypes.Map: // No stats computation for other types break; @@ -527,9 +537,9 @@ function initializeStatsForValue(value: unknown, mongoType: MongoBSONTypes, prop * Helper function to aggregate stats for a value based on its MongoDB data type * Used when processing multiple values (e.g., elements in arrays) */ -function aggregateStatsForValue(value: unknown, mongoType: MongoBSONTypes, propertyTypeEntry: JSONSchema): void { +function aggregateStatsForValue(value: unknown, mongoType: BSONTypes, propertyTypeEntry: JSONSchema): void { switch (mongoType) { - case MongoBSONTypes.String: { + case BSONTypes.String: { const currentLength = (value as string).length; // Update minLength @@ -544,11 +554,11 @@ function aggregateStatsForValue(value: unknown, mongoType: MongoBSONTypes, prope break; } - case MongoBSONTypes.Number: - case MongoBSONTypes.Int32: - case MongoBSONTypes.Long: - case MongoBSONTypes.Double: - case MongoBSONTypes.Decimal128: { + case BSONTypes.Number: + case BSONTypes.Int32: + case BSONTypes.Long: + case BSONTypes.Double: + case BSONTypes.Decimal128: { const numericValue = Number(value); // Update minValue @@ -563,7 +573,7 @@ function aggregateStatsForValue(value: unknown, mongoType: MongoBSONTypes, prope break; } - case MongoBSONTypes.Boolean: { + case BSONTypes.Boolean: { const boolValue = value as boolean; // Update trueCount and falseCount @@ -581,7 +591,7 @@ function aggregateStatsForValue(value: unknown, mongoType: MongoBSONTypes, prope break; } - case MongoBSONTypes.Date: { + case BSONTypes.Date: { const dateValue = (value as Date).getTime(); // Update minDate @@ -596,7 +606,7 @@ function aggregateStatsForValue(value: unknown, mongoType: MongoBSONTypes, prope break; } - case MongoBSONTypes.Binary: { + case BSONTypes.Binary: { const binaryLength = (value as Buffer).length; // Update minLength diff --git a/src/utils/json/mongo/MongoValueFormatters.ts b/src/utils/json/data-api/ValueFormatters.ts similarity index 63% rename from src/utils/json/mongo/MongoValueFormatters.ts rename to src/utils/json/data-api/ValueFormatters.ts index 243ce2631..8d770e318 100644 --- a/src/utils/json/mongo/MongoValueFormatters.ts +++ b/src/utils/json/data-api/ValueFormatters.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { type Binary, type BSONRegExp, type ObjectId } from 'mongodb'; -import { MongoBSONTypes } from './MongoBSONTypes'; +import { BSONTypes } from './BSONTypes'; /** * Converts a MongoDB value to its display string representation based on its type. @@ -24,60 +24,60 @@ import { MongoBSONTypes } from './MongoBSONTypes'; * * For unsupported or unknown types, the function defaults to JSON stringification. */ -export function valueToDisplayString(value: unknown, type: MongoBSONTypes): string { +export function valueToDisplayString(value: unknown, type: BSONTypes): string { switch (type) { - case MongoBSONTypes.String: { + case BSONTypes.String: { return value as string; } - case MongoBSONTypes.Number: - case MongoBSONTypes.Int32: - case MongoBSONTypes.Double: - case MongoBSONTypes.Decimal128: - case MongoBSONTypes.Long: { + case BSONTypes.Number: + case BSONTypes.Int32: + case BSONTypes.Double: + case BSONTypes.Decimal128: + case BSONTypes.Long: { return (value as number).toString(); } - case MongoBSONTypes.Boolean: { + case BSONTypes.Boolean: { return (value as boolean).toString(); } - case MongoBSONTypes.Date: { + case BSONTypes.Date: { return (value as Date).toISOString(); } - case MongoBSONTypes.ObjectId: { + case BSONTypes.ObjectId: { return (value as ObjectId).toHexString(); } - case MongoBSONTypes.Null: { + case BSONTypes.Null: { return 'null'; } - case MongoBSONTypes.RegExp: { + case BSONTypes.RegExp: { const v = value as BSONRegExp; return `${v.pattern} ${v.options}`; } - case MongoBSONTypes.Binary: { + case BSONTypes.Binary: { return `Binary[${(value as Binary).length()}]`; } - case MongoBSONTypes.Symbol: { + case BSONTypes.Symbol: { return (value as symbol).toString(); } - case MongoBSONTypes.Timestamp: { + case BSONTypes.Timestamp: { return (value as { toString: () => string }).toString(); } - case MongoBSONTypes.MinKey: { + case BSONTypes.MinKey: { return 'MinKey'; } - case MongoBSONTypes.MaxKey: { + case BSONTypes.MaxKey: { return 'MaxKey'; } - case MongoBSONTypes.Code: - case MongoBSONTypes.CodeWithScope: { + case BSONTypes.Code: + case BSONTypes.CodeWithScope: { return JSON.stringify(value); } - case MongoBSONTypes.Array: - case MongoBSONTypes.Object: - case MongoBSONTypes.Map: - case MongoBSONTypes.DBRef: - case MongoBSONTypes.Undefined: - case MongoBSONTypes._UNKNOWN_: + case BSONTypes.Array: + case BSONTypes.Object: + case BSONTypes.Map: + case BSONTypes.DBRef: + case BSONTypes.Undefined: + case BSONTypes._UNKNOWN_: default: { return JSON.stringify(value); } diff --git a/src/utils/json/mongo/autocomplete/basicMongoFindFilterSchema.json b/src/utils/json/data-api/autocomplete/basicMongoFindFilterSchema.json similarity index 100% rename from src/utils/json/mongo/autocomplete/basicMongoFindFilterSchema.json rename to src/utils/json/data-api/autocomplete/basicMongoFindFilterSchema.json diff --git a/src/utils/json/mongo/autocomplete/generateMongoFindJsonSchema.ts b/src/utils/json/data-api/autocomplete/generateMongoFindJsonSchema.ts similarity index 100% rename from src/utils/json/mongo/autocomplete/generateMongoFindJsonSchema.ts rename to src/utils/json/data-api/autocomplete/generateMongoFindJsonSchema.ts diff --git a/src/utils/json/mongo/autocomplete/getKnownFields.ts b/src/utils/json/data-api/autocomplete/getKnownFields.ts similarity index 100% rename from src/utils/json/mongo/autocomplete/getKnownFields.ts rename to src/utils/json/data-api/autocomplete/getKnownFields.ts diff --git a/src/utils/json/mongo/mongoTestDocuments.ts b/src/utils/json/data-api/mongoTestDocuments.ts similarity index 100% rename from src/utils/json/mongo/mongoTestDocuments.ts rename to src/utils/json/data-api/mongoTestDocuments.ts diff --git a/src/utils/json/mongo/MongoBSONTypes.ts b/src/utils/json/mongo/MongoBSONTypes.ts deleted file mode 100644 index fa97add9c..000000000 --- a/src/utils/json/mongo/MongoBSONTypes.ts +++ /dev/null @@ -1,200 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { - Binary, - BSONSymbol, - Code, - DBRef, - Decimal128, - Double, - Int32, - Long, - MaxKey, - MinKey, - ObjectId, - Timestamp, - UUID, -} from 'mongodb'; - -/** - * Represents the different data types that can be stored in a MongoDB document. - * The string representation is casesensitive and should match the MongoDB documentation. - * https://www.mongodb.com/docs/manual/reference/bson-types/ - */ -export enum MongoBSONTypes { - String = 'string', - Number = 'number', - Int32 = 'int32', - Double = 'double', - Decimal128 = 'decimal128', - Long = 'long', - Boolean = 'boolean', - Object = 'object', - Array = 'array', - Null = 'null', - Undefined = 'undefined', - Date = 'date', - RegExp = 'regexp', - Binary = 'binary', - ObjectId = 'objectid', - Symbol = 'symbol', - Timestamp = 'timestamp', - UUID = 'uuid', - UUID_LEGACY = 'uuid-legacy', // old UUID subtype, used in some legacy data - MinKey = 'minkey', - MaxKey = 'maxkey', - DBRef = 'dbref', - Code = 'code', - CodeWithScope = 'codewithscope', - Map = 'map', - // Add any deprecated types if necessary - _UNKNOWN_ = '_unknown_', // Catch-all for unknown types -} - -export namespace MongoBSONTypes { - const displayStringMap: Record = { - [MongoBSONTypes.String]: 'String', - [MongoBSONTypes.Number]: 'Number', - [MongoBSONTypes.Int32]: 'Int32', - [MongoBSONTypes.Double]: 'Double', - [MongoBSONTypes.Decimal128]: 'Decimal128', - [MongoBSONTypes.Long]: 'Long', - [MongoBSONTypes.Boolean]: 'Boolean', - [MongoBSONTypes.Object]: 'Object', - [MongoBSONTypes.Array]: 'Array', - [MongoBSONTypes.Null]: 'Null', - [MongoBSONTypes.Undefined]: 'Undefined', - [MongoBSONTypes.Date]: 'Date', - [MongoBSONTypes.RegExp]: 'RegExp', - [MongoBSONTypes.Binary]: 'Binary', - [MongoBSONTypes.ObjectId]: 'ObjectId', - [MongoBSONTypes.Symbol]: 'Symbol', - [MongoBSONTypes.Timestamp]: 'Timestamp', - [MongoBSONTypes.MinKey]: 'MinKey', - [MongoBSONTypes.MaxKey]: 'MaxKey', - [MongoBSONTypes.DBRef]: 'DBRef', - [MongoBSONTypes.Code]: 'Code', - [MongoBSONTypes.CodeWithScope]: 'CodeWithScope', - [MongoBSONTypes.Map]: 'Map', - [MongoBSONTypes._UNKNOWN_]: 'Unknown', - [MongoBSONTypes.UUID]: 'UUID', - [MongoBSONTypes.UUID_LEGACY]: 'UUID (Legacy)', - }; - - export function toDisplayString(type: MongoBSONTypes): string { - return displayStringMap[type] || 'Unknown'; - } - - export function toString(type: MongoBSONTypes): string { - return type; - } - - /** - * Converts a MongoDB data type to a case sensitive JSON data type - * @param type The MongoDB data type - * @returns A corresponding JSON data type (please note: it's case sensitive) - */ - export function toJSONType(type: MongoBSONTypes): string { - switch (type) { - case MongoBSONTypes.String: - case MongoBSONTypes.Symbol: - case MongoBSONTypes.Date: - case MongoBSONTypes.Timestamp: - case MongoBSONTypes.ObjectId: - case MongoBSONTypes.RegExp: - case MongoBSONTypes.Binary: - case MongoBSONTypes.Code: - case MongoBSONTypes.UUID: - case MongoBSONTypes.UUID_LEGACY: - return 'string'; - - case MongoBSONTypes.Boolean: - return 'boolean'; - - case MongoBSONTypes.Int32: - case MongoBSONTypes.Long: - case MongoBSONTypes.Double: - case MongoBSONTypes.Decimal128: - return 'number'; - - case MongoBSONTypes.Object: - case MongoBSONTypes.Map: - case MongoBSONTypes.DBRef: - case MongoBSONTypes.CodeWithScope: - return 'object'; - - case MongoBSONTypes.Array: - return 'array'; - - case MongoBSONTypes.Null: - case MongoBSONTypes.Undefined: - case MongoBSONTypes.MinKey: - case MongoBSONTypes.MaxKey: - return 'null'; - - default: - return 'string'; // Default to string for unknown types - } - } - - /** - * Accepts a value from a MongoDB 'Document' object and returns the inferred type. - * @param value The value of a field in a MongoDB 'Document' object - * @returns - */ - export function inferType(value: unknown): MongoBSONTypes { - if (value === null) return MongoBSONTypes.Null; - if (value === undefined) return MongoBSONTypes.Undefined; - - switch (typeof value) { - case 'string': - return MongoBSONTypes.String; - case 'number': - return MongoBSONTypes.Double; // JavaScript numbers are doubles - case 'boolean': - return MongoBSONTypes.Boolean; - case 'object': - if (Array.isArray(value)) { - return MongoBSONTypes.Array; - } - - // Check for common BSON types first - if (value instanceof ObjectId) return MongoBSONTypes.ObjectId; - if (value instanceof Int32) return MongoBSONTypes.Int32; - if (value instanceof Double) return MongoBSONTypes.Double; - if (value instanceof Date) return MongoBSONTypes.Date; - if (value instanceof Timestamp) return MongoBSONTypes.Timestamp; - - // Less common types - if (value instanceof Decimal128) return MongoBSONTypes.Decimal128; - if (value instanceof Long) return MongoBSONTypes.Long; - if (value instanceof MinKey) return MongoBSONTypes.MinKey; - if (value instanceof MaxKey) return MongoBSONTypes.MaxKey; - if (value instanceof BSONSymbol) return MongoBSONTypes.Symbol; - if (value instanceof DBRef) return MongoBSONTypes.DBRef; - if (value instanceof Map) return MongoBSONTypes.Map; - if (value instanceof UUID && value.sub_type === Binary.SUBTYPE_UUID) return MongoBSONTypes.UUID; - if (value instanceof UUID && value.sub_type === Binary.SUBTYPE_UUID_OLD) - return MongoBSONTypes.UUID_LEGACY; - if (value instanceof Buffer || value instanceof Binary) return MongoBSONTypes.Binary; - if (value instanceof RegExp) return MongoBSONTypes.RegExp; - if (value instanceof Code) { - if (value.scope) { - return MongoBSONTypes.CodeWithScope; - } else { - return MongoBSONTypes.Code; - } - } - - // Default to Object if none of the above match - return MongoBSONTypes.Object; - default: - // This should never happen, but if it does, we'll catch it here - // TODO: add telemetry somewhere to know when it happens (not here, this could get hit too often) - return MongoBSONTypes._UNKNOWN_; - } - } -} diff --git a/src/utils/slickgrid/mongo/toSlickGridTable.ts b/src/utils/slickgrid/mongo/toSlickGridTable.ts index 737fcb7c0..ece8d02e6 100644 --- a/src/utils/slickgrid/mongo/toSlickGridTable.ts +++ b/src/utils/slickgrid/mongo/toSlickGridTable.ts @@ -6,8 +6,8 @@ import { EJSON } from 'bson'; import { type Document, type WithId } from 'mongodb'; import { type TableDataEntry } from '../../../documentdb/ClusterSession'; -import { MongoBSONTypes } from '../../json/mongo/MongoBSONTypes'; -import { valueToDisplayString } from '../../json/mongo/MongoValueFormatters'; +import { BSONTypes } from '../../json/data-api/BSONTypes'; +import { valueToDisplayString } from '../../json/data-api/ValueFormatters'; /** * Extracts data from a list of MongoDB documents at a specified path. @@ -45,8 +45,8 @@ export function getDataAtPath(documents: WithId[], path: string[]): Ta // we also make sure that the '_id' field is always included in the data! if (doc._id) { row['_id'] = { - value: valueToDisplayString(doc._id, MongoBSONTypes.inferType(doc._id)), - type: MongoBSONTypes.inferType(doc._id), + value: valueToDisplayString(doc._id, BSONTypes.inferType(doc._id)), + type: BSONTypes.inferType(doc._id), }; // TODO: problem here -> what if the user has a field with this name... row['x-objectid'] = EJSON.stringify(doc._id, { relaxed: false }); // this is crucial, we need to retain the _id field for future queries from the table view @@ -72,13 +72,13 @@ export function getDataAtPath(documents: WithId[], path: string[]): Ta continue; } else { const value: unknown = subdocument[key]; - const type: MongoBSONTypes = MongoBSONTypes.inferType(value); + const type: BSONTypes = BSONTypes.inferType(value); // eslint-disable-next-line if (value instanceof Array) { row[key] = { value: `array[${value.length}]`, - type: MongoBSONTypes.Array, + type: BSONTypes.Array, }; } else { row[key] = { value: valueToDisplayString(value, type), type: type }; diff --git a/src/utils/slickgrid/mongo/toSlickGridTree.ts b/src/utils/slickgrid/mongo/toSlickGridTree.ts index 9d3742cfe..1db9e979d 100644 --- a/src/utils/slickgrid/mongo/toSlickGridTree.ts +++ b/src/utils/slickgrid/mongo/toSlickGridTree.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { type Document, type ObjectId, type WithId } from 'mongodb'; -import { MongoBSONTypes } from '../../json/mongo/MongoBSONTypes'; -import { valueToDisplayString } from '../../json/mongo/MongoValueFormatters'; +import { BSONTypes } from '../../json/data-api/BSONTypes'; +import { valueToDisplayString } from '../../json/data-api/ValueFormatters'; /** * The data structure for a single node entry in the tree data structure for SlickGrid. @@ -113,10 +113,10 @@ export function documentToSlickGridTree(document: WithId, idPrefix?: s continue; } - const dataType: MongoBSONTypes = MongoBSONTypes.inferType(stackEntry.value); + const dataType: BSONTypes = BSONTypes.inferType(stackEntry.value); switch (dataType) { - case MongoBSONTypes.Object: { + case BSONTypes.Object: { tree.push({ id: globalEntryId, field: `${stackEntry.key}`, @@ -131,7 +131,7 @@ export function documentToSlickGridTree(document: WithId, idPrefix?: s }); break; } - case MongoBSONTypes.Array: { + case BSONTypes.Array: { const value = stackEntry.value as unknown[]; tree.push({ @@ -157,7 +157,7 @@ export function documentToSlickGridTree(document: WithId, idPrefix?: s id: globalEntryId, field: `${stackEntry.key}`, value: valueToDisplayString(stackEntry.value, dataType), - type: MongoBSONTypes.toDisplayString(MongoBSONTypes.inferType(stackEntry.value)), + type: BSONTypes.toDisplayString(BSONTypes.inferType(stackEntry.value)), parentId: stackEntry.parentId, }); break; diff --git a/src/webviews/documentdb/collectionView/collectionViewRouter.ts b/src/webviews/documentdb/collectionView/collectionViewRouter.ts index fec8eb05d..c2d71e1d9 100644 --- a/src/webviews/documentdb/collectionView/collectionViewRouter.ts +++ b/src/webviews/documentdb/collectionView/collectionViewRouter.ts @@ -12,7 +12,7 @@ import { type JSONSchema } from 'vscode-json-languageservice'; import { z } from 'zod'; import { ClusterSession } from '../../../documentdb/ClusterSession'; import { getConfirmationAsInSettings } from '../../../utils/dialogs/getConfirmation'; -import { getKnownFields, type FieldEntry } from '../../../utils/json/mongo/autocomplete/getKnownFields'; +import { getKnownFields, type FieldEntry } from '../../../utils/json/data-api/autocomplete/getKnownFields'; import { publicProcedureWithTelemetry, router, type WithTelemetry } from '../../api/extension-server/trpc'; import * as l10n from '@vscode/l10n'; @@ -40,8 +40,8 @@ import { ext } from '../../../extensionVariables'; import { QueryInsightsAIService } from '../../../services/ai/QueryInsightsAIService'; import { type CollectionItem } from '../../../tree/documentdb/CollectionItem'; // eslint-disable-next-line import/no-internal-modules -import basicFindQuerySchema from '../../../utils/json/mongo/autocomplete/basicMongoFindFilterSchema.json'; -import { generateMongoFindJsonSchema } from '../../../utils/json/mongo/autocomplete/generateMongoFindJsonSchema'; +import basicFindQuerySchema from '../../../utils/json/data-api/autocomplete/basicMongoFindFilterSchema.json'; +import { generateMongoFindJsonSchema } from '../../../utils/json/data-api/autocomplete/generateMongoFindJsonSchema'; import { promptAfterActionEventually } from '../../../utils/survey'; import { UsageImpact } from '../../../utils/surveyTypes'; import { type BaseRouterContext } from '../../api/configuration/appRouter'; diff --git a/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx b/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx index 7b6d7e8ec..b03e5e9bb 100644 --- a/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx +++ b/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx @@ -11,7 +11,7 @@ import { InputWithProgress } from '../../../../components/InputWithProgress'; // eslint-disable-next-line import/no-internal-modules import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; // eslint-disable-next-line import/no-internal-modules -import basicFindQuerySchema from '../../../../../utils/json/mongo/autocomplete/basicMongoFindFilterSchema.json'; +import basicFindQuerySchema from '../../../../../utils/json/data-api/autocomplete/basicMongoFindFilterSchema.json'; import { useConfiguration } from '../../../../api/webview-client/useConfiguration'; import { type CollectionViewWebviewConfigurationType } from '../../collectionViewController'; From 50dabfb827e7284a35a76c4b627a87f8a144171d Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Feb 2026 20:22:56 +0100 Subject: [PATCH 002/128] refactor: convert SchemaAnalyzer to class with addDocument/getSchema API Group B of SchemaAnalyzer refactor: - B1: SchemaAnalyzer class with addDocument(), getSchema(), reset(), getDocumentCount() - B2: clone() method using structuredClone for schema branching - B3: addDocuments() batch convenience method - B4: static fromDocument()/fromDocuments() factories (replaces getSchemaFromDocument) - B5: Migrate ClusterSession to use SchemaAnalyzer instance - B6-B7: Remove old free functions (updateSchemaWithDocument, getSchemaFromDocument) - Keep getPropertyNamesAtLevel, getSchemaAtPath, buildFullPaths as standalone exports --- src/documentdb/ClusterSession.ts | 14 +- .../SchemaAnalyzer.arrayStats.test.ts | 67 ++-- .../json/data-api/SchemaAnalyzer.test.ts | 45 +-- src/utils/json/data-api/SchemaAnalyzer.ts | 285 +++++------------- 4 files changed, 149 insertions(+), 262 deletions(-) diff --git a/src/documentdb/ClusterSession.ts b/src/documentdb/ClusterSession.ts index b4ac8f3b1..53ae67c7e 100644 --- a/src/documentdb/ClusterSession.ts +++ b/src/documentdb/ClusterSession.ts @@ -7,7 +7,7 @@ import * as l10n from '@vscode/l10n'; import { EJSON } from 'bson'; import { ObjectId, type Document, type Filter, type WithId } from 'mongodb'; import { type JSONSchema } from '../utils/json/JSONSchema'; -import { getPropertyNamesAtLevel, updateSchemaWithDocument } from '../utils/json/data-api/SchemaAnalyzer'; +import { SchemaAnalyzer, getPropertyNamesAtLevel } from '../utils/json/data-api/SchemaAnalyzer'; import { getDataAtPath } from '../utils/slickgrid/mongo/toSlickGridTable'; import { toSlickGridTree, type TreeData } from '../utils/slickgrid/mongo/toSlickGridTree'; import { ClustersClient, type FindQueryParams } from './ClustersClient'; @@ -78,7 +78,7 @@ export class ClusterSession { * Updates progressively as users navigate through different pages. * Reset when the query or page size changes. */ - private _accumulatedJsonSchema: JSONSchema = {}; + private _schemaAnalyzer: SchemaAnalyzer = new SchemaAnalyzer(); /** * Tracks the highest page number that has been accumulated into the schema. @@ -162,7 +162,7 @@ export class ClusterSession { } // The user's query has changed, invalidate all caches - this._accumulatedJsonSchema = {}; + this._schemaAnalyzer.reset(); this._highestPageAccumulated = 0; this._currentPageSize = null; this._currentRawDocuments = []; @@ -185,7 +185,7 @@ export class ClusterSession { private resetAccumulationIfPageSizeChanged(newPageSize: number): void { if (this._currentPageSize !== null && this._currentPageSize !== newPageSize) { // Page size changed, reset accumulation tracking - this._accumulatedJsonSchema = {}; + this._schemaAnalyzer.reset(); this._highestPageAccumulated = 0; } this._currentPageSize = newPageSize; @@ -298,7 +298,7 @@ export class ClusterSession { // Since navigation is sequential and starts at page 1, we only need to track // the highest page number accumulated if (pageNumber > this._highestPageAccumulated) { - this._currentRawDocuments.map((doc) => updateSchemaWithDocument(this._accumulatedJsonSchema, doc)); + this._schemaAnalyzer.addDocuments(this._currentRawDocuments); this._highestPageAccumulated = pageNumber; } @@ -355,7 +355,7 @@ export class ClusterSession { public getCurrentPageAsTable(path: string[]): TableData { const responsePack: TableData = { path: path, - headers: getPropertyNamesAtLevel(this._accumulatedJsonSchema, path), + headers: getPropertyNamesAtLevel(this._schemaAnalyzer.getSchema(), path), data: getDataAtPath(this._currentRawDocuments, path), }; @@ -363,7 +363,7 @@ export class ClusterSession { } public getCurrentSchema(): JSONSchema { - return this._accumulatedJsonSchema; + return this._schemaAnalyzer.getSchema(); } // ============================================================================ diff --git a/src/utils/json/data-api/SchemaAnalyzer.arrayStats.test.ts b/src/utils/json/data-api/SchemaAnalyzer.arrayStats.test.ts index 6933315da..1f0ce7a3e 100644 --- a/src/utils/json/data-api/SchemaAnalyzer.arrayStats.test.ts +++ b/src/utils/json/data-api/SchemaAnalyzer.arrayStats.test.ts @@ -5,7 +5,7 @@ import { ObjectId, type Document, type WithId } from 'mongodb'; import { type JSONSchema } from '../JSONSchema'; -import { updateSchemaWithDocument } from './SchemaAnalyzer'; +import { SchemaAnalyzer } from './SchemaAnalyzer'; /** * This test file investigates the array element occurrence/stats problem. @@ -36,7 +36,7 @@ import { updateSchemaWithDocument } from './SchemaAnalyzer'; */ describe('Array element occurrence analysis', () => { it('counts element types across multiple documents', () => { - const schema: JSONSchema = {}; + const analyzer = new SchemaAnalyzer(); const doc1: WithId = { _id: new ObjectId(), @@ -51,9 +51,10 @@ describe('Array element occurrence analysis', () => { data: ['z'], }; - updateSchemaWithDocument(schema, doc1); - updateSchemaWithDocument(schema, doc2); - updateSchemaWithDocument(schema, doc3); + analyzer.addDocument(doc1); + analyzer.addDocument(doc2); + analyzer.addDocument(doc3); + const schema = analyzer.getSchema(); // data field: array seen in 3 docs const dataField = schema.properties?.['data'] as JSONSchema; @@ -102,7 +103,7 @@ describe('Array element occurrence analysis', () => { }); it('tracks min/max array lengths across documents', () => { - const schema: JSONSchema = {}; + const analyzer = new SchemaAnalyzer(); const doc1: WithId = { _id: new ObjectId(), @@ -117,9 +118,10 @@ describe('Array element occurrence analysis', () => { tags: ['p', 'q', 'r', 's', 't'], }; - updateSchemaWithDocument(schema, doc1); - updateSchemaWithDocument(schema, doc2); - updateSchemaWithDocument(schema, doc3); + analyzer.addDocument(doc1); + analyzer.addDocument(doc2); + analyzer.addDocument(doc3); + const schema = analyzer.getSchema(); const tagsField = schema.properties?.['tags'] as JSONSchema; const arrayEntry = tagsField.anyOf?.find((e) => (e as JSONSchema)['x-bsonType'] === 'array') as JSONSchema; @@ -129,7 +131,7 @@ describe('Array element occurrence analysis', () => { }); it('accumulates nested object properties from objects inside arrays across documents', () => { - const schema: JSONSchema = {}; + const analyzer = new SchemaAnalyzer(); // doc1 has two objects with different properties in the items array const doc1: WithId = { @@ -146,8 +148,9 @@ describe('Array element occurrence analysis', () => { items: [{ name: 'Desk', weight: 50 }], }; - updateSchemaWithDocument(schema, doc1); - updateSchemaWithDocument(schema, doc2); + analyzer.addDocument(doc1); + analyzer.addDocument(doc2); + const schema = analyzer.getSchema(); const itemsField = schema.properties?.['items'] as JSONSchema; const arrayEntry = itemsField.anyOf?.find((e) => (e as JSONSchema)['x-bsonType'] === 'array') as JSONSchema; @@ -182,7 +185,7 @@ describe('Array element occurrence analysis', () => { }); it('handles arrays that ONLY contain primitives (no occurrence complexity)', () => { - const schema: JSONSchema = {}; + const analyzer = new SchemaAnalyzer(); const doc1: WithId = { _id: new ObjectId(), @@ -193,8 +196,9 @@ describe('Array element occurrence analysis', () => { scores: [100, 55], }; - updateSchemaWithDocument(schema, doc1); - updateSchemaWithDocument(schema, doc2); + analyzer.addDocument(doc1); + analyzer.addDocument(doc2); + const schema = analyzer.getSchema(); const scoresField = schema.properties?.['scores'] as JSONSchema; const arrayEntry = scoresField.anyOf?.find((e) => (e as JSONSchema)['x-bsonType'] === 'array') as JSONSchema; @@ -238,7 +242,7 @@ describe('Array element occurrence analysis', () => { // This is a REAL BUG: initializeStatsForValue is called for the first occurrence // per array, but the typeEntry already has stats from previous arrays. - const schema: JSONSchema = {}; + const analyzer = new SchemaAnalyzer(); const doc1: WithId = { _id: new ObjectId(), @@ -249,8 +253,9 @@ describe('Array element occurrence analysis', () => { scores: [5, 15], }; - updateSchemaWithDocument(schema, doc1); - updateSchemaWithDocument(schema, doc2); + analyzer.addDocument(doc1); + analyzer.addDocument(doc2); + const schema = analyzer.getSchema(); const scoresField = schema.properties?.['scores'] as JSONSchema; const arrayEntry = scoresField.anyOf?.find((e) => (e as JSONSchema)['x-bsonType'] === 'array') as JSONSchema; @@ -296,7 +301,7 @@ describe('Array probability denominator problem', () => { // formula `x-occurrence / parent.x-documentsInspected` works at every // nesting level. - const schema: JSONSchema = {}; + const analyzer = new SchemaAnalyzer(); const doc1: WithId = { _id: new ObjectId(), @@ -313,8 +318,9 @@ describe('Array probability denominator problem', () => { a: objectElements, }; - updateSchemaWithDocument(schema, doc1); - updateSchemaWithDocument(schema, doc2); + analyzer.addDocument(doc1); + analyzer.addDocument(doc2); + const schema = analyzer.getSchema(); // Root level expect(schema['x-documentsInspected']).toBe(2); @@ -351,7 +357,7 @@ describe('Array probability denominator problem', () => { // price: 1/3 = 33% // discount: 1/3 = 33% - const schema: JSONSchema = {}; + const analyzer = new SchemaAnalyzer(); const doc1: WithId = { _id: new ObjectId(), @@ -362,8 +368,9 @@ describe('Array probability denominator problem', () => { items: [{ name: 'C', discount: true }], }; - updateSchemaWithDocument(schema, doc1); - updateSchemaWithDocument(schema, doc2); + analyzer.addDocument(doc1); + analyzer.addDocument(doc2); + const schema = analyzer.getSchema(); const itemsField = schema.properties?.['items'] as JSONSchema; const arrayEntry = itemsField.anyOf?.find((e) => (e as JSONSchema)['x-bsonType'] === 'array') as JSONSchema; @@ -389,14 +396,15 @@ describe('Array probability denominator problem', () => { // At address.anyOf[object] level: x-documentsInspected = 2 // city: 2/2 = 100%, zip: 1/2 = 50% - const schema: JSONSchema = {}; + const analyzer = new SchemaAnalyzer(); const doc: WithId = { _id: new ObjectId(), items: [{ address: { city: 'NY', zip: '10001' } }, { address: { city: 'LA' } }], }; - updateSchemaWithDocument(schema, doc); + analyzer.addDocument(doc); + const schema = analyzer.getSchema(); const itemsField = schema.properties?.['items'] as JSONSchema; const arrayEntry = itemsField.anyOf?.find((e) => (e as JSONSchema)['x-bsonType'] === 'array') as JSONSchema; @@ -422,7 +430,7 @@ describe('Array probability denominator problem', () => { }); it('does NOT change x-documentsInspected at root level (root keeps document count)', () => { - const schema: JSONSchema = {}; + const analyzer = new SchemaAnalyzer(); const doc1: WithId = { _id: new ObjectId(), @@ -435,8 +443,9 @@ describe('Array probability denominator problem', () => { address: { city: 'LA', zip: '90001' }, }; - updateSchemaWithDocument(schema, doc1); - updateSchemaWithDocument(schema, doc2); + analyzer.addDocument(doc1); + analyzer.addDocument(doc2); + const schema = analyzer.getSchema(); // Root x-documentsInspected is document count, not affected by the fix expect(schema['x-documentsInspected']).toBe(2); diff --git a/src/utils/json/data-api/SchemaAnalyzer.test.ts b/src/utils/json/data-api/SchemaAnalyzer.test.ts index 731791611..f8da609b9 100644 --- a/src/utils/json/data-api/SchemaAnalyzer.test.ts +++ b/src/utils/json/data-api/SchemaAnalyzer.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { type JSONSchema, type JSONSchemaRef } from '../JSONSchema'; -import { getPropertyNamesAtLevel, updateSchemaWithDocument } from './SchemaAnalyzer'; +import { SchemaAnalyzer, getPropertyNamesAtLevel } from './SchemaAnalyzer'; import { arraysWithDifferentDataTypes, complexDocument, @@ -17,15 +17,15 @@ import { describe('DocumentDB Schema Analyzer', () => { it('prints out schema for testing', () => { - const schema: JSONSchema = {}; - updateSchemaWithDocument(schema, embeddedDocumentOnly); + const analyzer = SchemaAnalyzer.fromDocument(embeddedDocumentOnly); + const schema = analyzer.getSchema(); console.log(JSON.stringify(schema, null, 2)); expect(schema).toBeDefined(); }); it('supports many documents', () => { - const schema: JSONSchema = {}; - sparseDocumentsArray.forEach((doc) => updateSchemaWithDocument(schema, doc)); + const analyzer = SchemaAnalyzer.fromDocuments(sparseDocumentsArray); + const schema = analyzer.getSchema(); expect(schema).toBeDefined(); // Check that 'x-documentsInspected' is correct @@ -66,8 +66,8 @@ describe('DocumentDB Schema Analyzer', () => { }); it('detects all BSON types from flatDocument', () => { - const schema: JSONSchema = {}; - updateSchemaWithDocument(schema, flatDocument); + const analyzer = SchemaAnalyzer.fromDocument(flatDocument); + const schema = analyzer.getSchema(); // Check that all fields are detected const expectedFields = Object.keys(flatDocument); @@ -92,8 +92,8 @@ describe('DocumentDB Schema Analyzer', () => { }); it('detects embedded objects correctly', () => { - const schema: JSONSchema = {}; - updateSchemaWithDocument(schema, embeddedDocumentOnly); + const analyzer = SchemaAnalyzer.fromDocument(embeddedDocumentOnly); + const schema = analyzer.getSchema(); // Check that the root properties are detected expect(schema.properties).toHaveProperty('personalInfo'); @@ -118,8 +118,8 @@ describe('DocumentDB Schema Analyzer', () => { }); it('detects arrays and their element types correctly', () => { - const schema: JSONSchema = {}; - updateSchemaWithDocument(schema, arraysWithDifferentDataTypes); + const analyzer = SchemaAnalyzer.fromDocument(arraysWithDifferentDataTypes); + const schema = analyzer.getSchema(); // Check that arrays are detected expect(schema.properties).toHaveProperty('integersArray'); @@ -150,8 +150,8 @@ describe('DocumentDB Schema Analyzer', () => { }); it('handles arrays within objects and objects within arrays', () => { - const schema: JSONSchema = {}; - updateSchemaWithDocument(schema, complexDocument); + const analyzer = SchemaAnalyzer.fromDocument(complexDocument); + const schema = analyzer.getSchema(); // Access 'user.profile.hobbies' const userProfile = schema.properties && schema.properties['user'].anyOf?.[0]?.properties?.['profile']; @@ -179,8 +179,8 @@ describe('DocumentDB Schema Analyzer', () => { }); it('updates schema correctly when processing multiple documents', () => { - const schema: JSONSchema = {}; - complexDocumentsArray.forEach((doc) => updateSchemaWithDocument(schema, doc)); + const analyzer = SchemaAnalyzer.fromDocuments(complexDocumentsArray); + const schema = analyzer.getSchema(); // Check that 'x-documentsInspected' is correct expect(schema['x-documentsInspected']).toBe(complexDocumentsArray.length); @@ -207,8 +207,8 @@ describe('DocumentDB Schema Analyzer', () => { describe('traverses schema', () => { it('with valid paths', () => { - const schema: JSONSchema = {}; - updateSchemaWithDocument(schema, complexDocument); + const analyzer = SchemaAnalyzer.fromDocument(complexDocument); + const schema = analyzer.getSchema(); let propertiesAtRoot = getPropertyNamesAtLevel(schema, []); expect(propertiesAtRoot).toHaveLength(4); @@ -221,8 +221,8 @@ describe('DocumentDB Schema Analyzer', () => { }); it('with broken paths', () => { - const schema: JSONSchema = {}; - updateSchemaWithDocument(schema, complexDocument); + const analyzer = SchemaAnalyzer.fromDocument(complexDocument); + const schema = analyzer.getSchema(); const propertiesAtRoot = getPropertyNamesAtLevel(schema, []); expect(propertiesAtRoot).toHaveLength(4); @@ -233,9 +233,10 @@ describe('DocumentDB Schema Analyzer', () => { }); it('with sparse docs and mixed types', () => { - const schema: JSONSchema = {}; - updateSchemaWithDocument(schema, complexDocument); - updateSchemaWithDocument(schema, complexDocumentWithOddTypes); + const analyzer = new SchemaAnalyzer(); + analyzer.addDocument(complexDocument); + analyzer.addDocument(complexDocumentWithOddTypes); + const schema = analyzer.getSchema(); let propertiesAtRoot = getPropertyNamesAtLevel(schema, []); expect(propertiesAtRoot).toHaveLength(4); diff --git a/src/utils/json/data-api/SchemaAnalyzer.ts b/src/utils/json/data-api/SchemaAnalyzer.ts index bc97dff49..c340172a9 100644 --- a/src/utils/json/data-api/SchemaAnalyzer.ts +++ b/src/utils/json/data-api/SchemaAnalyzer.ts @@ -3,66 +3,96 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as l10n from '@vscode/l10n'; +import { assert } from 'console'; +import Denque from 'denque'; +import { type Document, type WithId } from 'mongodb'; +import { type JSONSchema } from '../JSONSchema'; +import { BSONTypes } from './BSONTypes'; + /** - * This is an example of a JSON Schema document that will be generated from MongoDB documents. - * It's optimized for the use-case of generating a schema for a table view, the monaco editor, and schema statistics. - * - * This is a 'work in progress' and will be updated as we progress with the project. - * - * Curent focus is: - * - discovery of the document structure - * - basic pre for future statistics work + * Incremental schema analyzer for documents from the MongoDB API / DocumentDB API. * - * Future tasks: - * - statistics aggregation - * - meaningful 'description' and 'markdownDescription' - * - add more properties to the schema, incl. properties like '$id', '$schema', and enable schema sharing/download + * Analyzes documents one at a time (or in batches) and builds a cumulative + * JSON Schema with statistical extensions (x-occurrence, x-bsonType, etc.). * + * The output schema follows JSON Schema draft-07 with custom x- extensions. + */ +export class SchemaAnalyzer { + private _schema: JSONSchema = {}; -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://example.com/sample.schema.json", - "title": "Sample Document Schema", - "type": "object", - "properties": { - "a-propert-root-level": { - "description": "a description as text", - "anyOf": [ // anyOf is used to indicate that the value can be of any of the types listed - { - "type": "string" - }, - { - "type": "string" - } - ] - }, - "isOpen": { - "description": "Indicates if the item is open", - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "number" + /** + * Adds a single document to the accumulated schema. + * This is the primary incremental API — call once per document. + */ + addDocument(document: WithId): void { + updateSchemaWithDocumentInternal(this._schema, document); + } + + /** + * Adds multiple documents to the accumulated schema. + * Convenience method equivalent to calling addDocument() for each. + */ + addDocuments(documents: ReadonlyArray>): void { + for (const doc of documents) { + this.addDocument(doc); } - ] } - }, - "required": ["isOpen"] -} - * - * - */ + /** + * Returns the current accumulated JSON Schema. + * The returned object is a live reference (not a copy) — do not mutate externally. + */ + getSchema(): JSONSchema { + return this._schema; + } -import * as l10n from '@vscode/l10n'; -import { assert } from 'console'; -import Denque from 'denque'; -import { type Document, type WithId } from 'mongodb'; -import { type JSONSchema } from '../JSONSchema'; -import { BSONTypes } from './BSONTypes'; + /** + * Returns the number of documents analyzed so far. + */ + getDocumentCount(): number { + return (this._schema['x-documentsInspected'] as number) ?? 0; + } + + /** + * Resets the analyzer to its initial empty state. + */ + reset(): void { + this._schema = {}; + } -export function updateSchemaWithDocument(schema: JSONSchema, document: WithId): void { + /** + * Creates a deep copy of this analyzer, including all accumulated schema data. + * Useful for aggregation stage branching where each stage needs its own schema state. + */ + clone(): SchemaAnalyzer { + const copy = new SchemaAnalyzer(); + copy._schema = structuredClone(this._schema); + return copy; + } + + /** + * Creates a SchemaAnalyzer from a single document. + * Equivalent to creating an instance and calling addDocument() once. + */ + static fromDocument(document: WithId): SchemaAnalyzer { + const analyzer = new SchemaAnalyzer(); + analyzer.addDocument(document); + return analyzer; + } + + /** + * Creates a SchemaAnalyzer from multiple documents. + * Equivalent to creating an instance and calling addDocuments(). + */ + static fromDocuments(documents: ReadonlyArray>): SchemaAnalyzer { + const analyzer = new SchemaAnalyzer(); + analyzer.addDocuments(documents); + return analyzer; + } +} + +function updateSchemaWithDocumentInternal(schema: JSONSchema, document: WithId): void { // Initialize schema if it's empty if (!schema.properties) { schema.properties = {}; @@ -317,159 +347,6 @@ function updateMinMaxStats(schema: JSONSchema, minKey: string, maxKey: string, v } } -export function getSchemaFromDocument(document: WithId): JSONSchema { - const schema: JSONSchema = {}; - schema['x-documentsInspected'] = 1; // we're inspecting one document, this will make sense when we start aggregating stats - schema.properties = {}; - - type WorkItem = { - fieldName: string; - fieldMongoType: BSONTypes; // the inferred BSON type - propertyTypeEntry: JSONSchema; // points to the entry within the 'anyOf' property of the schema - fieldValue: unknown; - pathSoFar: string; // used for debugging - }; - - // having some import/require issues with Denque atm - // prototype with an array - //const fifoQueue = new Denque(); - const fifoQueue: WorkItem[] = []; - - /** - * Push all elements from the root of the document into the queue - */ - for (const [name, value] of Object.entries(document)) { - const mongoDatatype = BSONTypes.inferType(value); - - const typeEntry = { - type: BSONTypes.toJSONType(mongoDatatype), - 'x-bsonType': mongoDatatype, - 'x-typeOccurrence': 1, - }; - - // please note (1/2): we're adding the type entry to the schema here - schema.properties[name] = { anyOf: [typeEntry], 'x-occurrence': 1 }; - - fifoQueue.push({ - fieldName: name, - fieldMongoType: mongoDatatype, - propertyTypeEntry: typeEntry, // please note (2/2): and we're keeping a reference to it here for further updates - fieldValue: value, - pathSoFar: name, - }); - } - - /** - * Work through the queue, adding elements to the schema as we go. - * This is a breadth-first search of the document, do note special - * handling on objects/arrays - */ - while (fifoQueue.length > 0) { - const item = fifoQueue.shift(); // todo, replace with a proper queue - if (item === undefined) { - // unexpected, but let's try to continue - continue; - } - - switch (item.fieldMongoType) { - case BSONTypes.Object: { - const objKeys = Object.keys(item.fieldValue as object).length; - item.propertyTypeEntry['x-maxLength'] = objKeys; - item.propertyTypeEntry['x-minLength'] = objKeys; - - // prepare an entry for the object properties - item.propertyTypeEntry.properties = {}; - - for (const [name, value] of Object.entries(item.fieldValue as object)) { - const mongoDatatype = BSONTypes.inferType(value); - - const typeEntry = { - type: BSONTypes.toJSONType(mongoDatatype), - 'x-bsonType': mongoDatatype, - 'x-typeOccurrence': 1, - }; - - // please note (1/2): we're adding the entry to the main schema here - item.propertyTypeEntry.properties[name] = { anyOf: [typeEntry], 'x-occurrence': 1 }; - - fifoQueue.push({ - fieldName: name, - fieldMongoType: mongoDatatype, - propertyTypeEntry: typeEntry, // please note (2/2): and we're keeping a reference to it here for further updates to the schema - fieldValue: value, - pathSoFar: `${item.pathSoFar}.${item.fieldName}`, - }); - } - break; - } - case BSONTypes.Array: { - const arrayLength = (item.fieldValue as unknown[]).length; - item.propertyTypeEntry['x-maxLength'] = arrayLength; - item.propertyTypeEntry['x-minLength'] = arrayLength; - - // preapare the array items entry (in two lines for ts not to compalin about the missing type later on) - item.propertyTypeEntry.items = {}; - item.propertyTypeEntry.items.anyOf = []; - - const encounteredMongoTypes: Map = new Map(); - - // iterate over the array and infer the type of each element - for (const element of item.fieldValue as unknown[]) { - const elementMongoType = BSONTypes.inferType(element); - - let itemEntry: JSONSchema; - - if (!encounteredMongoTypes.has(elementMongoType)) { - itemEntry = { - type: BSONTypes.toJSONType(elementMongoType), - 'x-bsonType': elementMongoType, - 'x-typeOccurrence': 1, // Initialize type occurrence counter - }; - item.propertyTypeEntry.items.anyOf.push(itemEntry); - encounteredMongoTypes.set(elementMongoType, itemEntry); - - initializeStatsForValue(element, elementMongoType, itemEntry); - } else { - // if we've already encountered this type, we'll just add the type to the existing entry - itemEntry = encounteredMongoTypes.get(elementMongoType) as JSONSchema; - - if (itemEntry === undefined) continue; // unexpected, but let's try to continue - - if (itemEntry['x-typeOccurrence'] !== undefined) { - itemEntry['x-typeOccurrence'] += 1; - } - - // Aggregate stats with the new value - aggregateStatsForValue(element, elementMongoType, itemEntry); - } - - // an imporant exception for arrays as we have to start adding them already now to the schema - // (if we want to avoid more iterations over the data) - if (elementMongoType === BSONTypes.Object || elementMongoType === BSONTypes.Array) { - fifoQueue.push({ - fieldName: '[]', // Array items don't have a field name - fieldMongoType: elementMongoType, - propertyTypeEntry: itemEntry, - fieldValue: element, - pathSoFar: `${item.pathSoFar}.${item.fieldName}.items`, - }); - } - } - - break; - } - - default: { - // For all other types, update stats for the value - initializeStatsForValue(item.fieldValue, item.fieldMongoType, item.propertyTypeEntry); - break; - } - } - } - - return schema; -} - /** * Helper function to compute stats for a value based on its MongoDB data type * Updates the provided propertyTypeEntry with the computed stats From bd708657f5c4686e5abf3a2e2949e06cf01707dc Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Feb 2026 20:31:32 +0100 Subject: [PATCH 003/128] refactor: update JSONSchema interface with typed x- properties and fix properties type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Group C of SchemaAnalyzer refactor: - C1: Add typed x-minValue, x-maxValue, x-minLength, x-maxLength, x-minDate, x-maxDate, x-trueCount, x-falseCount, x-minItems, x-maxItems, x-minProperties, x-maxProperties to JSONSchema interface - C2: Fix properties type: properties?: JSONSchema → properties?: JSONSchemaMap - C3: Fix downstream type errors in SchemaAnalyzer.test.ts (JSONSchemaRef casts) --- src/utils/json/JSONSchema.ts | 34 ++++++--- .../json/data-api/SchemaAnalyzer.test.ts | 72 ++++++++++--------- 2 files changed, 64 insertions(+), 42 deletions(-) diff --git a/src/utils/json/JSONSchema.ts b/src/utils/json/JSONSchema.ts index 467669ed5..3127932d6 100644 --- a/src/utils/json/JSONSchema.ts +++ b/src/utils/json/JSONSchema.ts @@ -24,16 +24,14 @@ export interface JSONSchema { $id?: string; $schema?: string; type?: string | string[]; - 'x-documentsInspected'?: number; - 'x-occurrence'?: number; - 'x-typeOccurrence'?: number; - 'x-bsonType'?: string; // Explicitly declare the key with a dash using quotes title?: string; + description?: string; definitions?: { [name: string]: JSONSchema; }; - description?: string; - properties?: JSONSchema; // changed from: JSONSchemaMap; + + // Structure + properties?: JSONSchemaMap; patternProperties?: JSONSchemaMap; additionalProperties?: JSONSchemaRef; minProperties?: number; @@ -44,7 +42,6 @@ export interface JSONSchema { [prop: string]: string[]; }; items?: JSONSchemaRef | JSONSchemaRef[]; - required?: string[]; $ref?: string; anyOf?: JSONSchemaRef[]; @@ -58,14 +55,35 @@ export interface JSONSchema { propertyNames?: JSONSchemaRef; examples?: undefined[]; $comment?: string; - $defs?: { [name: string]: JSONSchema; }; + + // Monaco extensions markdownEnumDescriptions?: string[]; markdownDescription?: string; doNotSuggest?: boolean; suggestSortText?: string; + + // SchemaAnalyzer extensions — document/field level + 'x-documentsInspected'?: number; + 'x-occurrence'?: number; + + // SchemaAnalyzer extensions — type entry level (on entries in anyOf) + 'x-bsonType'?: string; + 'x-typeOccurrence'?: number; + 'x-minValue'?: number; + 'x-maxValue'?: number; + 'x-minLength'?: number; + 'x-maxLength'?: number; + 'x-minDate'?: number; + 'x-maxDate'?: number; + 'x-trueCount'?: number; + 'x-falseCount'?: number; + 'x-minItems'?: number; + 'x-maxItems'?: number; + 'x-minProperties'?: number; + 'x-maxProperties'?: number; } export interface JSONSchemaMap { [name: string]: JSONSchemaRef; diff --git a/src/utils/json/data-api/SchemaAnalyzer.test.ts b/src/utils/json/data-api/SchemaAnalyzer.test.ts index f8da609b9..33d2c5156 100644 --- a/src/utils/json/data-api/SchemaAnalyzer.test.ts +++ b/src/utils/json/data-api/SchemaAnalyzer.test.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { type JSONSchema, type JSONSchemaRef } from '../JSONSchema'; +import { type JSONSchema, type JSONSchemaMap, type JSONSchemaRef } from '../JSONSchema'; import { SchemaAnalyzer, getPropertyNamesAtLevel } from './SchemaAnalyzer'; import { arraysWithDifferentDataTypes, @@ -39,28 +39,28 @@ describe('DocumentDB Schema Analyzer', () => { ); // Check that the 'name' field is detected correctly - const nameField: JSONSchema = schema.properties?.['name']; + const nameField = schema.properties?.['name'] as JSONSchema; expect(nameField).toBeDefined(); expect(nameField?.['x-occurrence']).toBeGreaterThan(0); // Access 'anyOf' to get the type entries - const nameFieldTypes = nameField.anyOf?.map((typeEntry) => typeEntry['type']); + const nameFieldTypes = nameField.anyOf?.map((typeEntry) => (typeEntry as JSONSchema)['type']); expect(nameFieldTypes).toContain('string'); // Check that the 'age' field has the correct type - const ageField: JSONSchema = schema.properties?.['age']; + const ageField = schema.properties?.['age'] as JSONSchema; expect(ageField).toBeDefined(); - const ageFieldTypes = ageField.anyOf?.map((typeEntry) => typeEntry['type']); + const ageFieldTypes = ageField.anyOf?.map((typeEntry) => (typeEntry as JSONSchema)['type']); expect(ageFieldTypes).toContain('number'); // Check that the 'isActive' field is a boolean - const isActiveField: JSONSchema = schema.properties?.['isActive']; + const isActiveField = schema.properties?.['isActive'] as JSONSchema; expect(isActiveField).toBeDefined(); - const isActiveTypes = isActiveField.anyOf?.map((typeEntry) => typeEntry['type']); + const isActiveTypes = isActiveField.anyOf?.map((typeEntry) => (typeEntry as JSONSchema)['type']); expect(isActiveTypes).toContain('boolean'); // Check that the 'description' field is optional (occurs in some documents) - const descriptionField = schema.properties?.['description']; + const descriptionField = schema.properties?.['description'] as JSONSchema | undefined; expect(descriptionField).toBeDefined(); expect(descriptionField?.['x-occurrence']).toBeLessThan(sparseDocumentsArray.length); }); @@ -75,9 +75,9 @@ describe('DocumentDB Schema Analyzer', () => { // Helper function to get the 'x-bsonType' from a field function getBsonType(fieldName: string): string | undefined { - const field = schema.properties?.[fieldName]; + const field = schema.properties?.[fieldName] as JSONSchema | undefined; const anyOf = field?.anyOf; - return anyOf && anyOf[0]?.['x-bsonType']; + return anyOf && (anyOf[0] as JSONSchema | undefined)?.['x-bsonType']; } // Check that specific BSON types are correctly identified @@ -100,8 +100,8 @@ describe('DocumentDB Schema Analyzer', () => { expect(schema.properties).toHaveProperty('jobInfo'); // Access 'personalInfo' properties - const personalInfoAnyOf = schema.properties && schema.properties['personalInfo']?.anyOf; - const personalInfoProperties = personalInfoAnyOf?.[0]?.properties; + const personalInfoAnyOf = schema.properties && (schema.properties['personalInfo'] as JSONSchema | undefined)?.anyOf; + const personalInfoProperties = (personalInfoAnyOf?.[0] as JSONSchema | undefined)?.properties; expect(personalInfoProperties).toBeDefined(); expect(personalInfoProperties).toHaveProperty('name'); expect(personalInfoProperties).toHaveProperty('age'); @@ -109,8 +109,8 @@ describe('DocumentDB Schema Analyzer', () => { expect(personalInfoProperties).toHaveProperty('address'); // Access 'address' properties within 'personalInfo' - const addressAnyOf = personalInfoProperties['address'].anyOf; - const addressProperties = addressAnyOf?.[0]?.properties; + const addressAnyOf = ((personalInfoProperties as JSONSchemaMap)['address'] as JSONSchema).anyOf; + const addressProperties = (addressAnyOf?.[0] as JSONSchema | undefined)?.properties; expect(addressProperties).toBeDefined(); expect(addressProperties).toHaveProperty('street'); expect(addressProperties).toHaveProperty('city'); @@ -130,10 +130,10 @@ describe('DocumentDB Schema Analyzer', () => { // Helper function to get item types from an array field function getArrayItemTypes(fieldName: string): string[] | undefined { - const field = schema.properties?.[fieldName]; + const field = schema.properties?.[fieldName] as JSONSchema | undefined; const anyOf = field?.anyOf; - const itemsAnyOf: JSONSchemaRef[] = anyOf?.[0]?.items?.anyOf; - return itemsAnyOf?.map((typeEntry) => typeEntry['type']); + const itemsAnyOf: JSONSchemaRef[] | undefined = ((anyOf?.[0] as JSONSchema | undefined)?.items as JSONSchema | undefined)?.anyOf; + return itemsAnyOf?.map((typeEntry) => (typeEntry as JSONSchema)['type'] as string); } // Check that 'integersArray' has elements of type 'number' @@ -154,27 +154,29 @@ describe('DocumentDB Schema Analyzer', () => { const schema = analyzer.getSchema(); // Access 'user.profile.hobbies' - const userProfile = schema.properties && schema.properties['user'].anyOf?.[0]?.properties?.['profile']; - const hobbies = userProfile?.anyOf?.[0]?.properties?.['hobbies']; - // eslint-disable-next-line @typescript-eslint/no-unsafe-call - const hobbiesItemTypes = hobbies?.anyOf?.[0]?.items?.anyOf?.map((typeEntry) => typeEntry['type']); + const user = schema.properties?.['user'] as JSONSchema | undefined; + const userProfile = (user?.anyOf?.[0] as JSONSchema | undefined)?.properties?.['profile'] as JSONSchema | undefined; + const hobbies = (userProfile?.anyOf?.[0] as JSONSchema | undefined)?.properties?.['hobbies'] as JSONSchema | undefined; + const hobbiesItems = (hobbies?.anyOf?.[0] as JSONSchema | undefined)?.items as JSONSchema | undefined; + const hobbiesItemTypes = hobbiesItems?.anyOf?.map((typeEntry) => (typeEntry as JSONSchema).type); expect(hobbiesItemTypes).toContain('string'); // Access 'user.profile.addresses' - const addresses = userProfile?.anyOf?.[0]?.properties?.['addresses']; - // eslint-disable-next-line @typescript-eslint/no-unsafe-call - const addressItemTypes = addresses?.anyOf?.[0]?.items?.anyOf?.map((typeEntry) => typeEntry['type']); + const addresses = (userProfile?.anyOf?.[0] as JSONSchema | undefined)?.properties?.['addresses'] as JSONSchema | undefined; + const addressesItems = (addresses?.anyOf?.[0] as JSONSchema | undefined)?.items as JSONSchema | undefined; + const addressItemTypes = addressesItems?.anyOf?.map((typeEntry) => (typeEntry as JSONSchema).type); expect(addressItemTypes).toContain('object'); // Check that 'orders' is an array - const orders = schema.properties && schema.properties['orders']; + const orders = schema.properties?.['orders'] as JSONSchema | undefined; expect(orders).toBeDefined(); - const ordersType = orders.anyOf?.[0]?.type; + const ordersType = (orders?.anyOf?.[0] as JSONSchema | undefined)?.type; expect(ordersType).toBe('array'); // Access 'items' within 'orders' - const orderItems = orders.anyOf?.[0]?.items?.anyOf?.[0]?.properties?.['items']; - const orderItemsType = orderItems?.anyOf?.[0]?.type; + const orderItemsParent = (orders?.anyOf?.[0] as JSONSchema | undefined)?.items as JSONSchema | undefined; + const orderItems = (orderItemsParent?.anyOf?.[0] as JSONSchema | undefined)?.properties?.['items'] as JSONSchema | undefined; + const orderItemsType = (orderItems?.anyOf?.[0] as JSONSchema | undefined)?.type; expect(orderItemsType).toBe('array'); }); @@ -192,16 +194,18 @@ describe('DocumentDB Schema Analyzer', () => { expect(schema.properties).toHaveProperty('user'); // Check that 'integersArray' has correct min and max values - const integersArray = schema.properties && schema.properties['integersArray']; - const integerItemType = integersArray.anyOf?.[0]?.items?.anyOf?.[0]; + const integersArray = schema.properties?.['integersArray'] as JSONSchema | undefined; + const integerItemType = ((integersArray?.anyOf?.[0] as JSONSchema | undefined)?.items as JSONSchema | undefined)?.anyOf?.[0] as JSONSchema | undefined; expect(integerItemType?.['x-minValue']).toBe(1); expect(integerItemType?.['x-maxValue']).toBe(5); // Check that 'orders.items.price' is detected as Decimal128 - const orders = schema.properties && schema.properties['orders']; - const orderItems = orders.anyOf?.[0]?.items?.anyOf?.[0]?.properties?.['items']; - const priceField = orderItems?.anyOf?.[0]?.items?.anyOf?.[0]?.properties?.['price']; - const priceFieldType = priceField?.anyOf?.[0]; + const orders2 = schema.properties?.['orders'] as JSONSchema | undefined; + const orderItemsParent2 = (orders2?.anyOf?.[0] as JSONSchema | undefined)?.items as JSONSchema | undefined; + const orderItems = (orderItemsParent2?.anyOf?.[0] as JSONSchema | undefined)?.properties?.['items'] as JSONSchema | undefined; + const priceFieldParent = ((orderItems?.anyOf?.[0] as JSONSchema | undefined)?.items as JSONSchema | undefined)?.anyOf?.[0] as JSONSchema | undefined; + const priceField = priceFieldParent?.properties?.['price'] as JSONSchema | undefined; + const priceFieldType = priceField?.anyOf?.[0] as JSONSchema | undefined; expect(priceFieldType?.['x-bsonType']).toBe('decimal128'); }); From 99c0234d9d8958eee43a8bea1791121d7da049e0 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Feb 2026 20:35:58 +0100 Subject: [PATCH 004/128] feat: enhance FieldEntry with bsonType, bsonTypes, isOptional, arrayItemBsonType Group D of SchemaAnalyzer refactor: - D1: Add bsonType to FieldEntry (dominant BSON type from x-bsonType) - D2: Add bsonTypes[] for polymorphic fields (2+ distinct types) - D3: Add isOptional flag (x-occurrence < parent x-documentsInspected) - D4: Add arrayItemBsonType for array fields (dominant element BSON type) - D5: Sort results: _id first, then alphabetical by path - D6: Verified generateMongoFindJsonSchema still works (additive changes) - G4: Add 7 getKnownFields tests covering all new fields --- .../autocomplete/getKnownFields.test.ts | 131 ++++++++++++++++++ .../data-api/autocomplete/getKnownFields.ts | 116 +++++++++++++++- 2 files changed, 241 insertions(+), 6 deletions(-) create mode 100644 src/utils/json/data-api/autocomplete/getKnownFields.test.ts diff --git a/src/utils/json/data-api/autocomplete/getKnownFields.test.ts b/src/utils/json/data-api/autocomplete/getKnownFields.test.ts new file mode 100644 index 000000000..ffa8a0976 --- /dev/null +++ b/src/utils/json/data-api/autocomplete/getKnownFields.test.ts @@ -0,0 +1,131 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ObjectId } from 'bson'; +import { SchemaAnalyzer } from '../SchemaAnalyzer'; +import { getKnownFields, type FieldEntry } from './getKnownFields'; + +describe('getKnownFields', () => { + it('returns bsonType for primitive fields', () => { + const analyzer = SchemaAnalyzer.fromDocument({ + _id: new ObjectId(), + name: 'Alice', + age: 42, + score: 3.14, + active: true, + }); + const fields = getKnownFields(analyzer.getSchema()); + + const nameField = fields.find((f: FieldEntry) => f.path === 'name'); + expect(nameField?.type).toBe('string'); + expect(nameField?.bsonType).toBe('string'); + + const ageField = fields.find((f: FieldEntry) => f.path === 'age'); + expect(ageField?.type).toBe('number'); + // bsonType could be 'double' or 'int32' depending on JS runtime + expect(['double', 'int32']).toContain(ageField?.bsonType); + + const activeField = fields.find((f: FieldEntry) => f.path === 'active'); + expect(activeField?.type).toBe('boolean'); + expect(activeField?.bsonType).toBe('boolean'); + }); + + it('returns _id first and sorts alphabetically', () => { + const analyzer = SchemaAnalyzer.fromDocument({ + _id: new ObjectId(), + zebra: 1, + apple: 2, + mango: 3, + }); + const fields = getKnownFields(analyzer.getSchema()); + const paths = fields.map((f: FieldEntry) => f.path); + + expect(paths[0]).toBe('_id'); + // Remaining should be alphabetical + expect(paths.slice(1)).toEqual(['apple', 'mango', 'zebra']); + }); + + it('detects optional fields', () => { + const analyzer = new SchemaAnalyzer(); + analyzer.addDocument({ _id: new ObjectId(), name: 'Alice', age: 30 }); + analyzer.addDocument({ _id: new ObjectId(), name: 'Bob' }); // no 'age' + + const fields = getKnownFields(analyzer.getSchema()); + + const nameField = fields.find((f: FieldEntry) => f.path === 'name'); + expect(nameField?.isOptional).toBeUndefined(); // present in all docs + + const ageField = fields.find((f: FieldEntry) => f.path === 'age'); + expect(ageField?.isOptional).toBe(true); // missing in doc2 + }); + + it('returns bsonTypes for polymorphic fields', () => { + const analyzer = new SchemaAnalyzer(); + analyzer.addDocument({ _id: new ObjectId(), value: 'hello' }); + analyzer.addDocument({ _id: new ObjectId(), value: 42 }); + + const fields = getKnownFields(analyzer.getSchema()); + const valueField = fields.find((f: FieldEntry) => f.path === 'value'); + + expect(valueField?.bsonTypes).toBeDefined(); + expect(valueField?.bsonTypes).toHaveLength(2); + expect(valueField?.bsonTypes).toContain('string'); + // Could be 'double' or 'int32' + expect(valueField?.bsonTypes?.some((t: string) => ['double', 'int32'].includes(t))).toBe( + true, + ); + }); + + it('returns arrayItemBsonType for array fields', () => { + const analyzer = SchemaAnalyzer.fromDocument({ + _id: new ObjectId(), + tags: ['a', 'b', 'c'], + scores: [10, 20, 30], + }); + const fields = getKnownFields(analyzer.getSchema()); + + const tagsField = fields.find((f: FieldEntry) => f.path === 'tags'); + expect(tagsField?.type).toBe('array'); + expect(tagsField?.bsonType).toBe('array'); + expect(tagsField?.arrayItemBsonType).toBe('string'); + + const scoresField = fields.find((f: FieldEntry) => f.path === 'scores'); + expect(scoresField?.type).toBe('array'); + expect(scoresField?.arrayItemBsonType).toBeDefined(); + }); + + it('handles nested object fields', () => { + const analyzer = SchemaAnalyzer.fromDocument({ + _id: new ObjectId(), + user: { + name: 'Alice', + profile: { + bio: 'hello', + }, + }, + }); + const fields = getKnownFields(analyzer.getSchema()); + const paths = fields.map((f: FieldEntry) => f.path); + + // Objects are expanded, not leaf nodes + expect(paths).not.toContain('user'); + expect(paths).toContain('user.name'); + expect(paths).toContain('user.profile.bio'); + }); + + it('detects optional nested fields', () => { + const analyzer = new SchemaAnalyzer(); + analyzer.addDocument({ _id: new ObjectId(), user: { name: 'Alice', age: 30 } }); + analyzer.addDocument({ _id: new ObjectId(), user: { name: 'Bob' } }); // no age in nested obj + + const fields = getKnownFields(analyzer.getSchema()); + + const nameField = fields.find((f: FieldEntry) => f.path === 'user.name'); + expect(nameField?.isOptional).toBeUndefined(); // present in both objects + + const ageField = fields.find((f: FieldEntry) => f.path === 'user.age'); + expect(ageField?.isOptional).toBe(true); // missing in doc2's user object + }); +}); diff --git a/src/utils/json/data-api/autocomplete/getKnownFields.ts b/src/utils/json/data-api/autocomplete/getKnownFields.ts index a82277a73..811e74224 100644 --- a/src/utils/json/data-api/autocomplete/getKnownFields.ts +++ b/src/utils/json/data-api/autocomplete/getKnownFields.ts @@ -7,8 +7,18 @@ import Denque from 'denque'; import { type JSONSchema } from '../../JSONSchema'; export interface FieldEntry { + /** Dot-notated path (e.g., "user.profile.name") */ path: string; + /** JSON type of the dominant type entry ("string", "number", "object", "array", etc.) */ type: string; + /** Dominant BSON type from x-bsonType on the most common type entry ("date", "objectid", "int32", etc.) */ + bsonType: string; + /** All observed BSON types for this field (for polymorphic fields) */ + bsonTypes?: string[]; + /** true if the field is optional (x-occurrence < parent x-documentsInspected) */ + isOptional?: boolean; + /** If the field is an array, the dominant element BSON type */ + arrayItemBsonType?: string; } /** @@ -30,19 +40,26 @@ export interface FieldEntry { * - Return the result array containing objects with 'path' and 'type' for each leaf property. */ export function getKnownFields(schema: JSONSchema): FieldEntry[] { - const result: Array<{ path: string; type: string }> = []; + const result: FieldEntry[] = []; + type QueueItem = { path: string; schemaNode: JSONSchema; + parentDocumentsInspected: number; }; + const rootDocumentsInspected = (schema['x-documentsInspected'] as number) ?? 0; const queue: Denque = new Denque(); // Initialize the queue with root properties if (schema.properties) { for (const propName of Object.keys(schema.properties)) { const propSchema = schema.properties[propName] as JSONSchema; - queue.push({ path: propName, schemaNode: propSchema }); + queue.push({ + path: propName, + schemaNode: propSchema, + parentDocumentsInspected: rootDocumentsInspected, + }); } } @@ -50,23 +67,66 @@ export function getKnownFields(schema: JSONSchema): FieldEntry[] { const item = queue.shift(); if (!item) continue; - const { path, schemaNode } = item; + const { path, schemaNode, parentDocumentsInspected } = item; const mostCommonTypeEntry = getMostCommonTypeEntry(schemaNode); if (mostCommonTypeEntry) { if (mostCommonTypeEntry.type === 'object' && mostCommonTypeEntry.properties) { // Not a leaf node, enqueue its properties + const objectDocumentsInspected = + (mostCommonTypeEntry['x-documentsInspected'] as number) ?? 0; for (const childName of Object.keys(mostCommonTypeEntry.properties)) { const childSchema = mostCommonTypeEntry.properties[childName] as JSONSchema; - queue.push({ path: `${path}.${childName}`, schemaNode: childSchema }); + queue.push({ + path: `${path}.${childName}`, + schemaNode: childSchema, + parentDocumentsInspected: objectDocumentsInspected, + }); } } else { - // Leaf node, add to result - result.push({ path: path, type: mostCommonTypeEntry.type as string }); + // Leaf node, build the FieldEntry + const bsonType = + (mostCommonTypeEntry['x-bsonType'] as string) ?? + (mostCommonTypeEntry.type as string); + + const entry: FieldEntry = { + path, + type: mostCommonTypeEntry.type as string, + bsonType, + }; + + // bsonTypes: collect all distinct x-bsonType values from anyOf entries + const allBsonTypes = collectBsonTypes(schemaNode); + if (allBsonTypes.length >= 2) { + entry.bsonTypes = allBsonTypes; + } + + // isOptional: compare x-occurrence against parent's x-documentsInspected + const occurrence = (schemaNode['x-occurrence'] as number) ?? 0; + if (parentDocumentsInspected > 0 && occurrence < parentDocumentsInspected) { + entry.isOptional = true; + } + + // arrayItemBsonType: for array fields, find the dominant element type + if (mostCommonTypeEntry.type === 'array') { + const itemBsonType = getDominantArrayItemBsonType(mostCommonTypeEntry); + if (itemBsonType) { + entry.arrayItemBsonType = itemBsonType; + } + } + + result.push(entry); } } } + // Sort: _id first, then alphabetical by path + result.sort((a, b) => { + if (a.path === '_id') return -1; + if (b.path === '_id') return 1; + return a.path.localeCompare(b.path); + }); + return result; } @@ -93,3 +153,47 @@ function getMostCommonTypeEntry(schemaNode: JSONSchema): JSONSchema | null { } return null; } + +/** + * Collects all distinct x-bsonType values from a schema node's anyOf entries. + * Returns them sorted alphabetically for determinism. + */ +function collectBsonTypes(schemaNode: JSONSchema): string[] { + if (!schemaNode.anyOf || schemaNode.anyOf.length === 0) { + return []; + } + + const bsonTypes = new Set(); + for (const entry of schemaNode.anyOf as JSONSchema[]) { + const bsonType = entry['x-bsonType'] as string | undefined; + if (bsonType) { + bsonTypes.add(bsonType); + } + } + + return Array.from(bsonTypes).sort(); +} + +/** + * For an array type entry, finds the dominant element BSON type by looking at + * items.anyOf and selecting the entry with the highest x-typeOccurrence. + */ +function getDominantArrayItemBsonType(arrayTypeEntry: JSONSchema): string | undefined { + const itemsSchema = arrayTypeEntry.items as JSONSchema | undefined; + if (!itemsSchema?.anyOf || itemsSchema.anyOf.length === 0) { + return undefined; + } + + let maxOccurrence = -1; + let dominantBsonType: string | undefined; + + for (const entry of itemsSchema.anyOf as JSONSchema[]) { + const occurrence = (entry['x-typeOccurrence'] as number) ?? 0; + if (occurrence > maxOccurrence) { + maxOccurrence = occurrence; + dominantBsonType = entry['x-bsonType'] as string | undefined; + } + } + + return dominantBsonType; +} From 48914635796ef13c425d53e66a144a9839616539 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Feb 2026 20:47:38 +0100 Subject: [PATCH 005/128] feat: add transformers (generateDescriptions, toTypeScriptDefinition, toFieldCompletionItems) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Group E of SchemaAnalyzer refactor: - E1: generateDescriptions() — post-processor adding human-readable description strings with type info, occurrence percentage, and min/max stats - E2: toTypeScriptDefinition() — generates TypeScript interface strings from JSONSchema for shell addExtraLib() integration - E3: toFieldCompletionItems() — converts FieldEntry[] to CompletionItemProvider- ready FieldCompletionData[] with insert text escaping and $ references Also: - Rename isOptional → isSparse in FieldEntry and FieldCompletionData (all fields are implicitly optional in MongoDB API / DocumentDB API; isSparse is a statistical observation, not a constraint) - Fix lint errors (inline type specifiers) - 18 new tests for transformers + updated existing tests --- src/utils/json/data-api/BSONTypes.ts | 3 +- .../json/data-api/SchemaAnalyzer.test.ts | 35 ++- .../autocomplete/generateDescriptions.test.ts | 210 ++++++++++++++++ .../autocomplete/generateDescriptions.ts | 219 +++++++++++++++++ .../autocomplete/getKnownFields.test.ts | 12 +- .../data-api/autocomplete/getKnownFields.ts | 21 +- .../toFieldCompletionItems.test.ts | 85 +++++++ .../autocomplete/toFieldCompletionItems.ts | 52 ++++ .../toTypeScriptDefinition.test.ts | 209 ++++++++++++++++ .../autocomplete/toTypeScriptDefinition.ts | 232 ++++++++++++++++++ 10 files changed, 1050 insertions(+), 28 deletions(-) create mode 100644 src/utils/json/data-api/autocomplete/generateDescriptions.test.ts create mode 100644 src/utils/json/data-api/autocomplete/generateDescriptions.ts create mode 100644 src/utils/json/data-api/autocomplete/toFieldCompletionItems.test.ts create mode 100644 src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts create mode 100644 src/utils/json/data-api/autocomplete/toTypeScriptDefinition.test.ts create mode 100644 src/utils/json/data-api/autocomplete/toTypeScriptDefinition.ts diff --git a/src/utils/json/data-api/BSONTypes.ts b/src/utils/json/data-api/BSONTypes.ts index ef52911e7..17c8ff45d 100644 --- a/src/utils/json/data-api/BSONTypes.ts +++ b/src/utils/json/data-api/BSONTypes.ts @@ -177,8 +177,7 @@ export namespace BSONTypes { if (value instanceof DBRef) return BSONTypes.DBRef; if (value instanceof Map) return BSONTypes.Map; if (value instanceof UUID && value.sub_type === Binary.SUBTYPE_UUID) return BSONTypes.UUID; - if (value instanceof UUID && value.sub_type === Binary.SUBTYPE_UUID_OLD) - return BSONTypes.UUID_LEGACY; + if (value instanceof UUID && value.sub_type === Binary.SUBTYPE_UUID_OLD) return BSONTypes.UUID_LEGACY; if (value instanceof Buffer || value instanceof Binary) return BSONTypes.Binary; if (value instanceof RegExp) return BSONTypes.RegExp; if (value instanceof Code) { diff --git a/src/utils/json/data-api/SchemaAnalyzer.test.ts b/src/utils/json/data-api/SchemaAnalyzer.test.ts index 33d2c5156..477c843db 100644 --- a/src/utils/json/data-api/SchemaAnalyzer.test.ts +++ b/src/utils/json/data-api/SchemaAnalyzer.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { type JSONSchema, type JSONSchemaMap, type JSONSchemaRef } from '../JSONSchema'; -import { SchemaAnalyzer, getPropertyNamesAtLevel } from './SchemaAnalyzer'; +import { getPropertyNamesAtLevel, SchemaAnalyzer } from './SchemaAnalyzer'; import { arraysWithDifferentDataTypes, complexDocument, @@ -100,7 +100,8 @@ describe('DocumentDB Schema Analyzer', () => { expect(schema.properties).toHaveProperty('jobInfo'); // Access 'personalInfo' properties - const personalInfoAnyOf = schema.properties && (schema.properties['personalInfo'] as JSONSchema | undefined)?.anyOf; + const personalInfoAnyOf = + schema.properties && (schema.properties['personalInfo'] as JSONSchema | undefined)?.anyOf; const personalInfoProperties = (personalInfoAnyOf?.[0] as JSONSchema | undefined)?.properties; expect(personalInfoProperties).toBeDefined(); expect(personalInfoProperties).toHaveProperty('name'); @@ -132,7 +133,9 @@ describe('DocumentDB Schema Analyzer', () => { function getArrayItemTypes(fieldName: string): string[] | undefined { const field = schema.properties?.[fieldName] as JSONSchema | undefined; const anyOf = field?.anyOf; - const itemsAnyOf: JSONSchemaRef[] | undefined = ((anyOf?.[0] as JSONSchema | undefined)?.items as JSONSchema | undefined)?.anyOf; + const itemsAnyOf: JSONSchemaRef[] | undefined = ( + (anyOf?.[0] as JSONSchema | undefined)?.items as JSONSchema | undefined + )?.anyOf; return itemsAnyOf?.map((typeEntry) => (typeEntry as JSONSchema)['type'] as string); } @@ -155,14 +158,20 @@ describe('DocumentDB Schema Analyzer', () => { // Access 'user.profile.hobbies' const user = schema.properties?.['user'] as JSONSchema | undefined; - const userProfile = (user?.anyOf?.[0] as JSONSchema | undefined)?.properties?.['profile'] as JSONSchema | undefined; - const hobbies = (userProfile?.anyOf?.[0] as JSONSchema | undefined)?.properties?.['hobbies'] as JSONSchema | undefined; + const userProfile = (user?.anyOf?.[0] as JSONSchema | undefined)?.properties?.['profile'] as + | JSONSchema + | undefined; + const hobbies = (userProfile?.anyOf?.[0] as JSONSchema | undefined)?.properties?.['hobbies'] as + | JSONSchema + | undefined; const hobbiesItems = (hobbies?.anyOf?.[0] as JSONSchema | undefined)?.items as JSONSchema | undefined; const hobbiesItemTypes = hobbiesItems?.anyOf?.map((typeEntry) => (typeEntry as JSONSchema).type); expect(hobbiesItemTypes).toContain('string'); // Access 'user.profile.addresses' - const addresses = (userProfile?.anyOf?.[0] as JSONSchema | undefined)?.properties?.['addresses'] as JSONSchema | undefined; + const addresses = (userProfile?.anyOf?.[0] as JSONSchema | undefined)?.properties?.['addresses'] as + | JSONSchema + | undefined; const addressesItems = (addresses?.anyOf?.[0] as JSONSchema | undefined)?.items as JSONSchema | undefined; const addressItemTypes = addressesItems?.anyOf?.map((typeEntry) => (typeEntry as JSONSchema).type); expect(addressItemTypes).toContain('object'); @@ -175,7 +184,9 @@ describe('DocumentDB Schema Analyzer', () => { // Access 'items' within 'orders' const orderItemsParent = (orders?.anyOf?.[0] as JSONSchema | undefined)?.items as JSONSchema | undefined; - const orderItems = (orderItemsParent?.anyOf?.[0] as JSONSchema | undefined)?.properties?.['items'] as JSONSchema | undefined; + const orderItems = (orderItemsParent?.anyOf?.[0] as JSONSchema | undefined)?.properties?.['items'] as + | JSONSchema + | undefined; const orderItemsType = (orderItems?.anyOf?.[0] as JSONSchema | undefined)?.type; expect(orderItemsType).toBe('array'); }); @@ -195,15 +206,19 @@ describe('DocumentDB Schema Analyzer', () => { // Check that 'integersArray' has correct min and max values const integersArray = schema.properties?.['integersArray'] as JSONSchema | undefined; - const integerItemType = ((integersArray?.anyOf?.[0] as JSONSchema | undefined)?.items as JSONSchema | undefined)?.anyOf?.[0] as JSONSchema | undefined; + const integerItemType = ((integersArray?.anyOf?.[0] as JSONSchema | undefined)?.items as JSONSchema | undefined) + ?.anyOf?.[0] as JSONSchema | undefined; expect(integerItemType?.['x-minValue']).toBe(1); expect(integerItemType?.['x-maxValue']).toBe(5); // Check that 'orders.items.price' is detected as Decimal128 const orders2 = schema.properties?.['orders'] as JSONSchema | undefined; const orderItemsParent2 = (orders2?.anyOf?.[0] as JSONSchema | undefined)?.items as JSONSchema | undefined; - const orderItems = (orderItemsParent2?.anyOf?.[0] as JSONSchema | undefined)?.properties?.['items'] as JSONSchema | undefined; - const priceFieldParent = ((orderItems?.anyOf?.[0] as JSONSchema | undefined)?.items as JSONSchema | undefined)?.anyOf?.[0] as JSONSchema | undefined; + const orderItems = (orderItemsParent2?.anyOf?.[0] as JSONSchema | undefined)?.properties?.['items'] as + | JSONSchema + | undefined; + const priceFieldParent = ((orderItems?.anyOf?.[0] as JSONSchema | undefined)?.items as JSONSchema | undefined) + ?.anyOf?.[0] as JSONSchema | undefined; const priceField = priceFieldParent?.properties?.['price'] as JSONSchema | undefined; const priceFieldType = priceField?.anyOf?.[0] as JSONSchema | undefined; expect(priceFieldType?.['x-bsonType']).toBe('decimal128'); diff --git a/src/utils/json/data-api/autocomplete/generateDescriptions.test.ts b/src/utils/json/data-api/autocomplete/generateDescriptions.test.ts new file mode 100644 index 000000000..7500cc95c --- /dev/null +++ b/src/utils/json/data-api/autocomplete/generateDescriptions.test.ts @@ -0,0 +1,210 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { type JSONSchema } from '../../JSONSchema'; +import { generateDescriptions } from './generateDescriptions'; + +describe('generateDescriptions', () => { + it('adds descriptions with type and percentage for simple document', () => { + const schema: JSONSchema = { + 'x-documentsInspected': 100, + properties: { + name: { + 'x-occurrence': 100, + anyOf: [ + { + type: 'string', + 'x-bsonType': 'string', + 'x-typeOccurrence': 100, + }, + ], + }, + }, + }; + + generateDescriptions(schema); + + const nameSchema = schema.properties?.name as JSONSchema; + expect(nameSchema.description).toBe('String · 100%'); + }); + + it('includes min/max stats for numeric fields', () => { + const schema: JSONSchema = { + 'x-documentsInspected': 100, + properties: { + age: { + 'x-occurrence': 95, + anyOf: [ + { + type: 'number', + 'x-bsonType': 'int32', + 'x-typeOccurrence': 95, + 'x-minValue': 18, + 'x-maxValue': 95, + }, + ], + }, + }, + }; + + generateDescriptions(schema); + + const ageSchema = schema.properties?.age as JSONSchema; + expect(ageSchema.description).toBe('Int32 · 95% · range: 18–95'); + }); + + it('includes length stats for string fields', () => { + const schema: JSONSchema = { + 'x-documentsInspected': 100, + properties: { + name: { + 'x-occurrence': 100, + anyOf: [ + { + type: 'string', + 'x-bsonType': 'string', + 'x-typeOccurrence': 100, + 'x-minLength': 3, + 'x-maxLength': 50, + }, + ], + }, + }, + }; + + generateDescriptions(schema); + + const nameSchema = schema.properties?.name as JSONSchema; + expect(nameSchema.description).toBe('String · 100% · length: 3–50'); + }); + + it('includes date range stats for date fields', () => { + const minDate = new Date('2020-01-01T00:00:00.000Z').getTime(); + const maxDate = new Date('2024-12-31T00:00:00.000Z').getTime(); + + const schema: JSONSchema = { + 'x-documentsInspected': 100, + properties: { + createdAt: { + 'x-occurrence': 80, + anyOf: [ + { + type: 'string', + 'x-bsonType': 'date', + 'x-typeOccurrence': 80, + 'x-minDate': minDate, + 'x-maxDate': maxDate, + }, + ], + }, + }, + }; + + generateDescriptions(schema); + + const createdAtSchema = schema.properties?.createdAt as JSONSchema; + expect(createdAtSchema.description).toBe('Date · 80% · range: 2020-01-01 – 2024-12-31'); + }); + + it('includes true/false counts for boolean fields', () => { + const schema: JSONSchema = { + 'x-documentsInspected': 100, + properties: { + active: { + 'x-occurrence': 100, + anyOf: [ + { + type: 'boolean', + 'x-bsonType': 'boolean', + 'x-typeOccurrence': 100, + 'x-trueCount': 80, + 'x-falseCount': 20, + }, + ], + }, + }, + }; + + generateDescriptions(schema); + + const activeSchema = schema.properties?.active as JSONSchema; + expect(activeSchema.description).toBe('Boolean · 100% · true: 80, false: 20'); + }); + + it('handles nested object fields (descriptions at nested level)', () => { + const schema: JSONSchema = { + 'x-documentsInspected': 100, + properties: { + address: { + 'x-occurrence': 100, + anyOf: [ + { + type: 'object', + 'x-bsonType': 'object', + 'x-typeOccurrence': 100, + 'x-documentsInspected': 100, + properties: { + city: { + 'x-occurrence': 100, + anyOf: [ + { + type: 'string', + 'x-bsonType': 'string', + 'x-typeOccurrence': 100, + 'x-minLength': 2, + 'x-maxLength': 30, + }, + ], + }, + }, + }, + ], + }, + }, + }; + + generateDescriptions(schema); + + // The parent (address) should also get a description + const addressSchema = schema.properties?.address as JSONSchema; + expect(addressSchema.description).toBe('Object · 100%'); + + // The nested city should get its own description + const addressTypeEntry = (addressSchema.anyOf as JSONSchema[])[0]; + const citySchema = addressTypeEntry.properties?.city as JSONSchema; + expect(citySchema.description).toBe('String · 100% · length: 2–30'); + }); + + it('handles polymorphic fields (shows multiple types)', () => { + const schema: JSONSchema = { + 'x-documentsInspected': 100, + properties: { + value: { + 'x-occurrence': 95, + anyOf: [ + { + type: 'number', + 'x-bsonType': 'int32', + 'x-typeOccurrence': 60, + 'x-minValue': 1, + 'x-maxValue': 100, + }, + { + type: 'string', + 'x-bsonType': 'string', + 'x-typeOccurrence': 35, + }, + ], + }, + }, + }; + + generateDescriptions(schema); + + const valueSchema = schema.properties?.value as JSONSchema; + // Dominant type first, then secondary + expect(valueSchema.description).toBe('Int32 | String · 95% · range: 1–100'); + }); +}); diff --git a/src/utils/json/data-api/autocomplete/generateDescriptions.ts b/src/utils/json/data-api/autocomplete/generateDescriptions.ts new file mode 100644 index 000000000..261549bc2 --- /dev/null +++ b/src/utils/json/data-api/autocomplete/generateDescriptions.ts @@ -0,0 +1,219 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import Denque from 'denque'; +import { type JSONSchema } from '../../JSONSchema'; +import { BSONTypes } from '../BSONTypes'; + +/** + * Work item for BFS traversal of the schema tree. + */ +interface WorkItem { + schemaNode: JSONSchema; + parentDocumentsInspected: number; +} + +/** + * Post-processor that mutates the schema in-place, adding human-readable + * `description` strings to each property node. Descriptions include: + * - Dominant type name(s) + * - Occurrence percentage (based on `x-occurrence / parentDocumentsInspected`) + * - Type-specific stats (length, range, true/false counts, etc.) + * + * Uses BFS to traverse all property levels. + */ +export function generateDescriptions(schema: JSONSchema): void { + const rootDocumentsInspected = (schema['x-documentsInspected'] as number) ?? 0; + + const queue = new Denque(); + + // Seed the queue with root-level properties + if (schema.properties) { + for (const propName of Object.keys(schema.properties)) { + const propSchema = schema.properties[propName] as JSONSchema; + if (typeof propSchema === 'boolean') continue; + + queue.push({ + schemaNode: propSchema, + parentDocumentsInspected: rootDocumentsInspected, + }); + } + } + + while (queue.length > 0) { + const item = queue.shift(); + if (!item) continue; + + const { schemaNode, parentDocumentsInspected } = item; + + // Collect type display names from anyOf entries + const typeNames = collectTypeDisplayNames(schemaNode); + + // Build description parts + const parts: string[] = []; + + // Part 1: Type info + if (typeNames.length > 0) { + parts.push(typeNames.join(' | ')); + } + + // Part 2: Occurrence percentage + if (parentDocumentsInspected > 0) { + const occurrence = (schemaNode['x-occurrence'] as number) ?? 0; + const percentage = ((occurrence / parentDocumentsInspected) * 100).toFixed(0); + parts.push(`${percentage}%`); + } + + // Part 3: Stats from the dominant type entry + const dominantEntry = getDominantTypeEntry(schemaNode); + if (dominantEntry) { + const statString = getStatString(dominantEntry); + if (statString) { + parts.push(statString); + } + + // If the dominant entry is an object with properties, enqueue children + if (dominantEntry.type === 'object' && dominantEntry.properties) { + const objectDocumentsInspected = (dominantEntry['x-documentsInspected'] as number) ?? 0; + for (const childName of Object.keys(dominantEntry.properties)) { + const childSchema = dominantEntry.properties[childName] as JSONSchema; + if (typeof childSchema === 'boolean') continue; + + queue.push({ + schemaNode: childSchema, + parentDocumentsInspected: objectDocumentsInspected, + }); + } + } + } + + // Set the description + if (parts.length > 0) { + schemaNode.description = parts.join(' · '); + } + } +} + +/** + * Collects display names for all types in a schema node's `anyOf` entries. + * Returns them ordered by descending `x-typeOccurrence`. + */ +function collectTypeDisplayNames(schemaNode: JSONSchema): string[] { + if (!schemaNode.anyOf || schemaNode.anyOf.length === 0) { + return []; + } + + const entries: Array<{ name: string; occurrence: number }> = []; + for (const entry of schemaNode.anyOf) { + if (typeof entry === 'boolean') continue; + const bsonType = (entry['x-bsonType'] as string) ?? ''; + const occurrence = (entry['x-typeOccurrence'] as number) ?? 0; + const name = bsonType + ? BSONTypes.toDisplayString(bsonType as BSONTypes) + : ((entry.type as string) ?? 'Unknown'); + entries.push({ name, occurrence }); + } + + // Sort by occurrence descending so dominant type comes first + entries.sort((a, b) => b.occurrence - a.occurrence); + return entries.map((e) => e.name); +} + +/** + * Returns the anyOf entry with the highest `x-typeOccurrence`. + */ +function getDominantTypeEntry(schemaNode: JSONSchema): JSONSchema | null { + if (!schemaNode.anyOf || schemaNode.anyOf.length === 0) { + return null; + } + + let maxOccurrence = -1; + let dominant: JSONSchema | null = null; + + for (const entry of schemaNode.anyOf) { + if (typeof entry === 'boolean') continue; + const occurrence = (entry['x-typeOccurrence'] as number) ?? 0; + if (occurrence > maxOccurrence) { + maxOccurrence = occurrence; + dominant = entry; + } + } + + return dominant; +} + +/** + * Returns a type-specific stats string for the given type entry, or undefined if + * no relevant stats are available. + */ +function getStatString(typeEntry: JSONSchema): string | undefined { + const bsonType = (typeEntry['x-bsonType'] as string) ?? ''; + + switch (bsonType) { + case 'string': + case 'binary': { + const minLen = typeEntry['x-minLength'] as number | undefined; + const maxLen = typeEntry['x-maxLength'] as number | undefined; + if (minLen !== undefined && maxLen !== undefined) { + return `length: ${String(minLen)}–${String(maxLen)}`; + } + return undefined; + } + + case 'int32': + case 'double': + case 'long': + case 'decimal128': + case 'number': { + const minVal = typeEntry['x-minValue'] as number | undefined; + const maxVal = typeEntry['x-maxValue'] as number | undefined; + if (minVal !== undefined && maxVal !== undefined) { + return `range: ${String(minVal)}–${String(maxVal)}`; + } + return undefined; + } + + case 'date': { + const minDate = typeEntry['x-minDate'] as number | undefined; + const maxDate = typeEntry['x-maxDate'] as number | undefined; + if (minDate !== undefined && maxDate !== undefined) { + const minISO = new Date(minDate).toISOString().split('T')[0]; + const maxISO = new Date(maxDate).toISOString().split('T')[0]; + return `range: ${minISO} – ${maxISO}`; + } + return undefined; + } + + case 'boolean': { + const trueCount = typeEntry['x-trueCount'] as number | undefined; + const falseCount = typeEntry['x-falseCount'] as number | undefined; + if (trueCount !== undefined && falseCount !== undefined) { + return `true: ${String(trueCount)}, false: ${String(falseCount)}`; + } + return undefined; + } + + case 'array': { + const minItems = typeEntry['x-minItems'] as number | undefined; + const maxItems = typeEntry['x-maxItems'] as number | undefined; + if (minItems !== undefined && maxItems !== undefined) { + return `items: ${String(minItems)}–${String(maxItems)}`; + } + return undefined; + } + + case 'object': { + const minProps = typeEntry['x-minProperties'] as number | undefined; + const maxProps = typeEntry['x-maxProperties'] as number | undefined; + if (minProps !== undefined && maxProps !== undefined) { + return `properties: ${String(minProps)}–${String(maxProps)}`; + } + return undefined; + } + + default: + return undefined; + } +} diff --git a/src/utils/json/data-api/autocomplete/getKnownFields.test.ts b/src/utils/json/data-api/autocomplete/getKnownFields.test.ts index ffa8a0976..351dab7ff 100644 --- a/src/utils/json/data-api/autocomplete/getKnownFields.test.ts +++ b/src/utils/json/data-api/autocomplete/getKnownFields.test.ts @@ -55,10 +55,10 @@ describe('getKnownFields', () => { const fields = getKnownFields(analyzer.getSchema()); const nameField = fields.find((f: FieldEntry) => f.path === 'name'); - expect(nameField?.isOptional).toBeUndefined(); // present in all docs + expect(nameField?.isSparse).toBeUndefined(); // present in all docs const ageField = fields.find((f: FieldEntry) => f.path === 'age'); - expect(ageField?.isOptional).toBe(true); // missing in doc2 + expect(ageField?.isSparse).toBe(true); // missing in doc2 }); it('returns bsonTypes for polymorphic fields', () => { @@ -73,9 +73,7 @@ describe('getKnownFields', () => { expect(valueField?.bsonTypes).toHaveLength(2); expect(valueField?.bsonTypes).toContain('string'); // Could be 'double' or 'int32' - expect(valueField?.bsonTypes?.some((t: string) => ['double', 'int32'].includes(t))).toBe( - true, - ); + expect(valueField?.bsonTypes?.some((t: string) => ['double', 'int32'].includes(t))).toBe(true); }); it('returns arrayItemBsonType for array fields', () => { @@ -123,9 +121,9 @@ describe('getKnownFields', () => { const fields = getKnownFields(analyzer.getSchema()); const nameField = fields.find((f: FieldEntry) => f.path === 'user.name'); - expect(nameField?.isOptional).toBeUndefined(); // present in both objects + expect(nameField?.isSparse).toBeUndefined(); // present in both objects const ageField = fields.find((f: FieldEntry) => f.path === 'user.age'); - expect(ageField?.isOptional).toBe(true); // missing in doc2's user object + expect(ageField?.isSparse).toBe(true); // missing in doc2's user object }); }); diff --git a/src/utils/json/data-api/autocomplete/getKnownFields.ts b/src/utils/json/data-api/autocomplete/getKnownFields.ts index 811e74224..006c57f94 100644 --- a/src/utils/json/data-api/autocomplete/getKnownFields.ts +++ b/src/utils/json/data-api/autocomplete/getKnownFields.ts @@ -15,8 +15,14 @@ export interface FieldEntry { bsonType: string; /** All observed BSON types for this field (for polymorphic fields) */ bsonTypes?: string[]; - /** true if the field is optional (x-occurrence < parent x-documentsInspected) */ - isOptional?: boolean; + /** + * True if this field was not present in every inspected document + * (x-occurrence < parent x-documentsInspected). + * + * This is a statistical observation, not a schema constraint — in the + * MongoDB API / DocumentDB API all fields are implicitly optional. + */ + isSparse?: boolean; /** If the field is an array, the dominant element BSON type */ arrayItemBsonType?: string; } @@ -73,8 +79,7 @@ export function getKnownFields(schema: JSONSchema): FieldEntry[] { if (mostCommonTypeEntry) { if (mostCommonTypeEntry.type === 'object' && mostCommonTypeEntry.properties) { // Not a leaf node, enqueue its properties - const objectDocumentsInspected = - (mostCommonTypeEntry['x-documentsInspected'] as number) ?? 0; + const objectDocumentsInspected = (mostCommonTypeEntry['x-documentsInspected'] as number) ?? 0; for (const childName of Object.keys(mostCommonTypeEntry.properties)) { const childSchema = mostCommonTypeEntry.properties[childName] as JSONSchema; queue.push({ @@ -85,9 +90,7 @@ export function getKnownFields(schema: JSONSchema): FieldEntry[] { } } else { // Leaf node, build the FieldEntry - const bsonType = - (mostCommonTypeEntry['x-bsonType'] as string) ?? - (mostCommonTypeEntry.type as string); + const bsonType = (mostCommonTypeEntry['x-bsonType'] as string) ?? (mostCommonTypeEntry.type as string); const entry: FieldEntry = { path, @@ -101,10 +104,10 @@ export function getKnownFields(schema: JSONSchema): FieldEntry[] { entry.bsonTypes = allBsonTypes; } - // isOptional: compare x-occurrence against parent's x-documentsInspected + // isSparse: field was not observed in every document const occurrence = (schemaNode['x-occurrence'] as number) ?? 0; if (parentDocumentsInspected > 0 && occurrence < parentDocumentsInspected) { - entry.isOptional = true; + entry.isSparse = true; } // arrayItemBsonType: for array fields, find the dominant element type diff --git a/src/utils/json/data-api/autocomplete/toFieldCompletionItems.test.ts b/src/utils/json/data-api/autocomplete/toFieldCompletionItems.test.ts new file mode 100644 index 000000000..307b0c9d5 --- /dev/null +++ b/src/utils/json/data-api/autocomplete/toFieldCompletionItems.test.ts @@ -0,0 +1,85 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { type FieldEntry } from './getKnownFields'; +import { toFieldCompletionItems } from './toFieldCompletionItems'; + +describe('toFieldCompletionItems', () => { + it('converts simple fields', () => { + const fields: FieldEntry[] = [ + { path: 'name', type: 'string', bsonType: 'string' }, + { path: 'age', type: 'number', bsonType: 'int32' }, + ]; + + const result = toFieldCompletionItems(fields); + + expect(result).toHaveLength(2); + expect(result[0].fieldName).toBe('name'); + expect(result[0].displayType).toBe('String'); + expect(result[0].bsonType).toBe('string'); + expect(result[0].insertText).toBe('name'); + + expect(result[1].fieldName).toBe('age'); + expect(result[1].displayType).toBe('Int32'); + expect(result[1].bsonType).toBe('int32'); + expect(result[1].insertText).toBe('age'); + }); + + it('escapes dotted paths in insertText', () => { + const fields: FieldEntry[] = [ + { path: 'address.city', type: 'string', bsonType: 'string' }, + { path: 'user.profile.bio', type: 'string', bsonType: 'string' }, + ]; + + const result = toFieldCompletionItems(fields); + + expect(result[0].insertText).toBe('"address.city"'); + expect(result[1].insertText).toBe('"user.profile.bio"'); + }); + + it('adds $ prefix to referenceText', () => { + const fields: FieldEntry[] = [ + { path: 'age', type: 'number', bsonType: 'int32' }, + { path: 'address.city', type: 'string', bsonType: 'string' }, + ]; + + const result = toFieldCompletionItems(fields); + + expect(result[0].referenceText).toBe('$age'); + expect(result[1].referenceText).toBe('$address.city'); + }); + + it('preserves isSparse', () => { + const fields: FieldEntry[] = [ + { path: 'name', type: 'string', bsonType: 'string', isSparse: false }, + { path: 'nickname', type: 'string', bsonType: 'string', isSparse: true }, + { path: 'email', type: 'string', bsonType: 'string' }, // undefined → false + ]; + + const result = toFieldCompletionItems(fields); + + expect(result[0].isSparse).toBe(false); + expect(result[1].isSparse).toBe(true); + expect(result[2].isSparse).toBe(false); + }); + + it('uses correct displayType', () => { + const fields: FieldEntry[] = [ + { path: '_id', type: 'string', bsonType: 'objectid' }, + { path: 'createdAt', type: 'string', bsonType: 'date' }, + { path: 'active', type: 'boolean', bsonType: 'boolean' }, + { path: 'score', type: 'number', bsonType: 'double' }, + { path: 'tags', type: 'array', bsonType: 'array' }, + ]; + + const result = toFieldCompletionItems(fields); + + expect(result[0].displayType).toBe('ObjectId'); + expect(result[1].displayType).toBe('Date'); + expect(result[2].displayType).toBe('Boolean'); + expect(result[3].displayType).toBe('Double'); + expect(result[4].displayType).toBe('Array'); + }); +}); diff --git a/src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts b/src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts new file mode 100644 index 000000000..af68908a2 --- /dev/null +++ b/src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts @@ -0,0 +1,52 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { BSONTypes } from '../BSONTypes'; +import { type FieldEntry } from './getKnownFields'; + +/** + * Completion-ready data for a single field entry. + */ +export interface FieldCompletionData { + /** The full dot-notated field name, e.g., "address.city" */ + fieldName: string; + /** Human-readable type display, e.g., "String", "Date", "ObjectId" */ + displayType: string; + /** Raw BSON type from FieldEntry */ + bsonType: string; + /** Whether the field was not present in every inspected document (statistical observation, not a constraint) */ + isSparse: boolean; + /** Text to insert — escaped if field name contains dots or special chars */ + insertText: string; + /** Field reference for aggregation expressions, e.g., "$age", "$address.city" */ + referenceText: string; +} + +/** + * Characters that require quoting in a field name for insert text. + */ +const SPECIAL_CHARS_PATTERN = /[.$\s]/; + +/** + * Converts an array of FieldEntry objects into completion-ready FieldCompletionData items. + * + * @param fields - Array of FieldEntry objects from getKnownFields + * @returns Array of FieldCompletionData ready for use in editor completions + */ +export function toFieldCompletionItems(fields: FieldEntry[]): FieldCompletionData[] { + return fields.map((entry) => { + const displayType = BSONTypes.toDisplayString(entry.bsonType as BSONTypes); + const needsQuoting = SPECIAL_CHARS_PATTERN.test(entry.path); + + return { + fieldName: entry.path, + displayType, + bsonType: entry.bsonType, + isSparse: entry.isSparse ?? false, + insertText: needsQuoting ? `"${entry.path}"` : entry.path, + referenceText: `$${entry.path}`, + }; + }); +} diff --git a/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.test.ts b/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.test.ts new file mode 100644 index 000000000..00a112536 --- /dev/null +++ b/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.test.ts @@ -0,0 +1,209 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { type JSONSchema } from '../../JSONSchema'; +import { toTypeScriptDefinition } from './toTypeScriptDefinition'; + +describe('toTypeScriptDefinition', () => { + it('generates basic interface with primitive types', () => { + const schema: JSONSchema = { + 'x-documentsInspected': 100, + properties: { + _id: { + 'x-occurrence': 100, + anyOf: [ + { + type: 'string', + 'x-bsonType': 'objectid', + 'x-typeOccurrence': 100, + }, + ], + }, + name: { + 'x-occurrence': 100, + anyOf: [ + { + type: 'string', + 'x-bsonType': 'string', + 'x-typeOccurrence': 100, + }, + ], + }, + age: { + 'x-occurrence': 100, + anyOf: [ + { + type: 'number', + 'x-bsonType': 'int32', + 'x-typeOccurrence': 100, + }, + ], + }, + }, + }; + + const result = toTypeScriptDefinition(schema, 'users'); + + expect(result).toContain('interface UsersDocument {'); + expect(result).toContain(' _id: ObjectId;'); + expect(result).toContain(' name: string;'); + expect(result).toContain(' age: number;'); + expect(result).toContain('}'); + }); + + it('marks optional fields with ?', () => { + const schema: JSONSchema = { + 'x-documentsInspected': 100, + properties: { + name: { + 'x-occurrence': 100, + anyOf: [ + { + type: 'string', + 'x-bsonType': 'string', + 'x-typeOccurrence': 100, + }, + ], + }, + nickname: { + 'x-occurrence': 50, + anyOf: [ + { + type: 'string', + 'x-bsonType': 'string', + 'x-typeOccurrence': 50, + }, + ], + }, + }, + }; + + const result = toTypeScriptDefinition(schema, 'users'); + + expect(result).toContain(' name: string;'); + expect(result).toContain(' nickname?: string;'); + }); + + it('handles nested objects as inline blocks', () => { + const schema: JSONSchema = { + 'x-documentsInspected': 100, + properties: { + address: { + 'x-occurrence': 100, + anyOf: [ + { + type: 'object', + 'x-bsonType': 'object', + 'x-typeOccurrence': 100, + 'x-documentsInspected': 100, + properties: { + city: { + 'x-occurrence': 100, + anyOf: [ + { + type: 'string', + 'x-bsonType': 'string', + 'x-typeOccurrence': 100, + }, + ], + }, + zip: { + 'x-occurrence': 100, + anyOf: [ + { + type: 'string', + 'x-bsonType': 'string', + 'x-typeOccurrence': 100, + }, + ], + }, + }, + }, + ], + }, + }, + }; + + const result = toTypeScriptDefinition(schema, 'users'); + + expect(result).toContain(' address: {'); + expect(result).toContain(' city: string;'); + expect(result).toContain(' zip: string;'); + expect(result).toContain(' };'); + }); + + it('handles arrays with element types', () => { + const schema: JSONSchema = { + 'x-documentsInspected': 100, + properties: { + tags: { + 'x-occurrence': 100, + anyOf: [ + { + type: 'array', + 'x-bsonType': 'array', + 'x-typeOccurrence': 100, + items: { + anyOf: [ + { + type: 'string', + 'x-bsonType': 'string', + 'x-typeOccurrence': 100, + }, + ], + }, + }, + ], + }, + }, + }; + + const result = toTypeScriptDefinition(schema, 'posts'); + + expect(result).toContain(' tags: string[];'); + }); + + it('handles polymorphic fields as unions', () => { + const schema: JSONSchema = { + 'x-documentsInspected': 100, + properties: { + metadata: { + 'x-occurrence': 80, + anyOf: [ + { + type: 'string', + 'x-bsonType': 'string', + 'x-typeOccurrence': 50, + }, + { + type: 'number', + 'x-bsonType': 'int32', + 'x-typeOccurrence': 20, + }, + { + type: 'null', + 'x-bsonType': 'null', + 'x-typeOccurrence': 10, + }, + ], + }, + }, + }; + + const result = toTypeScriptDefinition(schema, 'items'); + + expect(result).toContain(' metadata?: string | number | null;'); + }); + + it('PascalCase conversion for collection name', () => { + expect(toTypeScriptDefinition({ 'x-documentsInspected': 0 }, 'users')).toContain('interface UsersDocument'); + expect(toTypeScriptDefinition({ 'x-documentsInspected': 0 }, 'order_items')).toContain( + 'interface OrderItemsDocument', + ); + expect(toTypeScriptDefinition({ 'x-documentsInspected': 0 }, 'my-awesome-collection')).toContain( + 'interface MyAwesomeCollectionDocument', + ); + }); +}); diff --git a/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.ts b/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.ts new file mode 100644 index 000000000..92bef8a9c --- /dev/null +++ b/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.ts @@ -0,0 +1,232 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { type JSONSchema } from '../../JSONSchema'; +import { BSONTypes } from '../BSONTypes'; + +/** + * Maps a BSON type string to the corresponding TypeScript type representation. + */ +const bsonToTypeScriptMap: Record = { + [BSONTypes.String]: 'string', + [BSONTypes.Int32]: 'number', + [BSONTypes.Double]: 'number', + [BSONTypes.Long]: 'number', + [BSONTypes.Decimal128]: 'number', + [BSONTypes.Number]: 'number', + [BSONTypes.Boolean]: 'boolean', + [BSONTypes.Date]: 'Date', + [BSONTypes.ObjectId]: 'ObjectId', + [BSONTypes.Null]: 'null', + [BSONTypes.Undefined]: 'undefined', + [BSONTypes.Binary]: 'Binary', + [BSONTypes.RegExp]: 'RegExp', + [BSONTypes.UUID]: 'UUID', + [BSONTypes.UUID_LEGACY]: 'UUID', + [BSONTypes.Timestamp]: 'Timestamp', + [BSONTypes.MinKey]: 'MinKey', + [BSONTypes.MaxKey]: 'MaxKey', + [BSONTypes.Code]: 'Code', + [BSONTypes.CodeWithScope]: 'Code', + [BSONTypes.DBRef]: 'DBRef', + [BSONTypes.Map]: 'Map', + [BSONTypes.Symbol]: 'symbol', +}; + +/** + * Converts a BSON type string to a TypeScript type string. + */ +function bsonTypeToTS(bsonType: string): string { + return bsonToTypeScriptMap[bsonType] ?? 'unknown'; +} + +/** + * Converts a collection name to PascalCase and appends "Document". + * Examples: + * - "users" → "UsersDocument" + * - "order_items" → "OrderItemsDocument" + */ +function toInterfaceName(collectionName: string): string { + const pascal = collectionName + .split(/[_\-\s]+/) + .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1)) + .join(''); + return `${pascal}Document`; +} + +/** + * Generates a TypeScript interface definition string from a JSONSchema + * produced by the SchemaAnalyzer. + * + * @param schema - The JSON Schema with x- extensions from SchemaAnalyzer + * @param collectionName - The MongoDB collection name, used to derive the interface name + * @returns A formatted TypeScript interface definition string + */ +export function toTypeScriptDefinition(schema: JSONSchema, collectionName: string): string { + const interfaceName = toInterfaceName(collectionName); + const rootDocumentsInspected = (schema['x-documentsInspected'] as number) ?? 0; + + const lines: string[] = []; + lines.push(`interface ${interfaceName} {`); + + if (schema.properties) { + renderProperties(schema.properties, rootDocumentsInspected, 1, lines); + } + + lines.push('}'); + return lines.join('\n'); +} + +/** + * Renders property lines for a set of JSON Schema properties at a given indent level. + */ +function renderProperties( + properties: Record, + parentDocumentsInspected: number, + indentLevel: number, + lines: string[], +): void { + const indent = ' '.repeat(indentLevel); + + for (const [propName, propSchema] of Object.entries(properties)) { + if (typeof propSchema === 'boolean') continue; + + const isOptional = isFieldOptional(propSchema, parentDocumentsInspected); + const optionalMarker = isOptional ? '?' : ''; + const tsType = resolveTypeString(propSchema, indentLevel); + + lines.push(`${indent}${propName}${optionalMarker}: ${tsType};`); + } +} + +/** + * Returns true if the field's occurrence is less than the parent's document count. + */ +function isFieldOptional(schemaNode: JSONSchema, parentDocumentsInspected: number): boolean { + const occurrence = (schemaNode['x-occurrence'] as number) ?? 0; + return parentDocumentsInspected > 0 && occurrence < parentDocumentsInspected; +} + +/** + * Resolves a full TypeScript type string for a schema node by examining its + * `anyOf` entries. Handles primitives, objects (inline blocks), and arrays. + */ +function resolveTypeString(schemaNode: JSONSchema, indentLevel: number): string { + if (!schemaNode.anyOf || schemaNode.anyOf.length === 0) { + return 'unknown'; + } + + const typeStrings: string[] = []; + + for (const entry of schemaNode.anyOf) { + if (typeof entry === 'boolean') continue; + const ts = singleEntryToTS(entry, indentLevel); + if (ts && !typeStrings.includes(ts)) { + typeStrings.push(ts); + } + } + + if (typeStrings.length === 0) { + return 'unknown'; + } + + return typeStrings.join(' | '); +} + +/** + * Converts a single `anyOf` type entry to a TypeScript type string. + */ +function singleEntryToTS(entry: JSONSchema, indentLevel: number): string { + const bsonType = (entry['x-bsonType'] as string) ?? ''; + + // Object with nested properties → inline block + if (entry.type === 'object' && entry.properties) { + return renderInlineObject(entry, indentLevel); + } + + // Array → determine element types + if (entry.type === 'array' || bsonType === (BSONTypes.Array as string)) { + return renderArrayType(entry, indentLevel); + } + + // Primitive or mapped type + if (bsonType) { + return bsonTypeToTS(bsonType); + } + + // Fallback to JSON type + const jsonType = entry.type as string | undefined; + if (jsonType) { + return jsonType; + } + + return 'unknown'; +} + +/** + * Renders an inline object type `{ field: type; ... }`. + */ +function renderInlineObject(entry: JSONSchema, indentLevel: number): string { + const lines: string[] = []; + const objectDocumentsInspected = (entry['x-documentsInspected'] as number) ?? 0; + + lines.push('{'); + + if (entry.properties) { + renderProperties(entry.properties, objectDocumentsInspected, indentLevel + 1, lines); + } + + const closingIndent = ' '.repeat(indentLevel); + lines.push(`${closingIndent}}`); + + return lines.join('\n'); +} + +/** + * Renders an array type, e.g., `string[]` or `(string | number)[]`. + */ +function renderArrayType(entry: JSONSchema, indentLevel: number): string { + const itemsSchema = entry.items; + + if (!itemsSchema || typeof itemsSchema === 'boolean') { + return 'unknown[]'; + } + + // Items specified as a single schema (not an array of schemas) + if (!Array.isArray(itemsSchema)) { + const itemSchema = itemsSchema as JSONSchema; + + if (itemSchema.anyOf && itemSchema.anyOf.length > 0) { + const elementTypes: string[] = []; + for (const itemEntry of itemSchema.anyOf) { + if (typeof itemEntry === 'boolean') continue; + const ts = singleEntryToTS(itemEntry, indentLevel); + if (ts && !elementTypes.includes(ts)) { + elementTypes.push(ts); + } + } + + if (elementTypes.length === 0) { + return 'unknown[]'; + } + + if (elementTypes.length === 1) { + return `${elementTypes[0]}[]`; + } + + return `(${elementTypes.join(' | ')})[]`; + } + + // Single item type without anyOf + const bsonType = (itemSchema['x-bsonType'] as string) ?? ''; + if (bsonType) { + return `${bsonTypeToTS(bsonType)}[]`; + } + + return 'unknown[]'; + } + + return 'unknown[]'; +} From 7a54b8c7cc378010999a8c2028e8ce8f8a9a4c58 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Feb 2026 21:00:40 +0100 Subject: [PATCH 006/128] test: add SchemaAnalyzer class method tests + update plan checklist MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add 5 tests for clone(), reset(), fromDocument(), fromDocuments(), addDocuments() - Mark all checklist items A-G as complete, F1-F2 as deferred - Add Manual Test Plan section (§14) with 5 end-to-end test scenarios - Document clone() limitation with BSON Binary types (structuredClone) --- .../json/data-api/SchemaAnalyzer.test.ts | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/src/utils/json/data-api/SchemaAnalyzer.test.ts b/src/utils/json/data-api/SchemaAnalyzer.test.ts index 477c843db..fe4d83629 100644 --- a/src/utils/json/data-api/SchemaAnalyzer.test.ts +++ b/src/utils/json/data-api/SchemaAnalyzer.test.ts @@ -272,4 +272,79 @@ describe('DocumentDB Schema Analyzer', () => { expect(propertiesAtRoot).toHaveLength(6); }); }); + + describe('SchemaAnalyzer class methods', () => { + it('clone() creates an independent deep copy', () => { + // Use embeddedDocumentOnly (plain JS types) to avoid structuredClone issues with BSON types + const original = SchemaAnalyzer.fromDocument(embeddedDocumentOnly); + const cloned = original.clone(); + + // Clone has the same document count + expect(cloned.getDocumentCount()).toBe(1); + + // Clone has the same properties + const originalProps = Object.keys(original.getSchema().properties || {}); + const clonedProps = Object.keys(cloned.getSchema().properties || {}); + expect(clonedProps).toEqual(originalProps); + + // Add another document to the original only + original.addDocument(arraysWithDifferentDataTypes); + expect(original.getDocumentCount()).toBe(2); + expect(cloned.getDocumentCount()).toBe(1); + + // Clone's schema was NOT affected by the mutation + const originalPropsAfter = Object.keys(original.getSchema().properties || {}); + const clonedPropsAfter = Object.keys(cloned.getSchema().properties || {}); + expect(originalPropsAfter).toContain('integersArray'); + expect(originalPropsAfter).toContain('stringsArray'); + expect(clonedPropsAfter).not.toContain('integersArray'); + expect(clonedPropsAfter).not.toContain('stringsArray'); + }); + + it('reset() clears all accumulated state', () => { + const analyzer = SchemaAnalyzer.fromDocument(flatDocument); + expect(analyzer.getDocumentCount()).toBeGreaterThan(0); + expect(Object.keys(analyzer.getSchema().properties || {})).not.toHaveLength(0); + + analyzer.reset(); + + expect(analyzer.getDocumentCount()).toBe(0); + const schema = analyzer.getSchema(); + expect(schema.properties).toBeUndefined(); + expect(schema['x-documentsInspected']).toBeUndefined(); + }); + + it('fromDocument() creates analyzer with single document', () => { + const analyzer = SchemaAnalyzer.fromDocument(flatDocument); + expect(analyzer.getDocumentCount()).toBe(1); + + const schema = analyzer.getSchema(); + const expectedFields = Object.keys(flatDocument); + expect(Object.keys(schema.properties || {})).toEqual(expect.arrayContaining(expectedFields)); + }); + + it('fromDocuments() creates analyzer with multiple documents', () => { + const analyzer = SchemaAnalyzer.fromDocuments(sparseDocumentsArray); + expect(analyzer.getDocumentCount()).toBe(sparseDocumentsArray.length); + + // Compare with manually-built analyzer + const manual = new SchemaAnalyzer(); + manual.addDocuments(sparseDocumentsArray); + + expect(JSON.stringify(analyzer.getSchema())).toBe(JSON.stringify(manual.getSchema())); + }); + + it('addDocuments() is equivalent to multiple addDocument() calls', () => { + const batch = new SchemaAnalyzer(); + batch.addDocuments(complexDocumentsArray); + + const sequential = new SchemaAnalyzer(); + for (const doc of complexDocumentsArray) { + sequential.addDocument(doc); + } + + expect(batch.getDocumentCount()).toBe(sequential.getDocumentCount()); + expect(JSON.stringify(batch.getSchema())).toBe(JSON.stringify(sequential.getSchema())); + }); + }); }); From d4380f448dd5997672a30a2a6280ef613077aa2e Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Feb 2026 21:19:11 +0100 Subject: [PATCH 007/128] feat: add version-based caching to SchemaAnalyzer + trace logging - Add monotonic version counter to SchemaAnalyzer (incremented on mutations) - Cache getKnownFields() with version-based staleness check - Add ClusterSession.getKnownFields() accessor (delegates to cached analyzer) - Wire collectionViewRouter to use session.getKnownFields() instead of standalone function - Add ext.outputChannel.trace for schema accumulation and reset events --- src/documentdb/ClusterSession.ts | 16 ++++++++++ src/utils/json/data-api/SchemaAnalyzer.ts | 32 ++++++++++++++++++- .../collectionView/collectionViewRouter.ts | 5 ++- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/documentdb/ClusterSession.ts b/src/documentdb/ClusterSession.ts index 53ae67c7e..cfa065196 100644 --- a/src/documentdb/ClusterSession.ts +++ b/src/documentdb/ClusterSession.ts @@ -6,8 +6,10 @@ import * as l10n from '@vscode/l10n'; import { EJSON } from 'bson'; import { ObjectId, type Document, type Filter, type WithId } from 'mongodb'; +import { ext } from '../extensionVariables'; import { type JSONSchema } from '../utils/json/JSONSchema'; import { SchemaAnalyzer, getPropertyNamesAtLevel } from '../utils/json/data-api/SchemaAnalyzer'; +import { type FieldEntry } from '../utils/json/data-api/autocomplete/getKnownFields'; import { getDataAtPath } from '../utils/slickgrid/mongo/toSlickGridTable'; import { toSlickGridTree, type TreeData } from '../utils/slickgrid/mongo/toSlickGridTree'; import { ClustersClient, type FindQueryParams } from './ClustersClient'; @@ -163,6 +165,7 @@ export class ClusterSession { // The user's query has changed, invalidate all caches this._schemaAnalyzer.reset(); + ext.outputChannel.trace('[SchemaAnalyzer] Reset — query changed'); this._highestPageAccumulated = 0; this._currentPageSize = null; this._currentRawDocuments = []; @@ -186,6 +189,7 @@ export class ClusterSession { if (this._currentPageSize !== null && this._currentPageSize !== newPageSize) { // Page size changed, reset accumulation tracking this._schemaAnalyzer.reset(); + ext.outputChannel.trace('[SchemaAnalyzer] Reset — page size changed'); this._highestPageAccumulated = 0; } this._currentPageSize = newPageSize; @@ -300,6 +304,10 @@ export class ClusterSession { if (pageNumber > this._highestPageAccumulated) { this._schemaAnalyzer.addDocuments(this._currentRawDocuments); this._highestPageAccumulated = pageNumber; + + ext.outputChannel.trace( + `[SchemaAnalyzer] Analyzed ${String(this._schemaAnalyzer.getDocumentCount())} documents, ${String(this._schemaAnalyzer.getKnownFields().length)} known fields`, + ); } return documents.length; @@ -366,6 +374,14 @@ export class ClusterSession { return this._schemaAnalyzer.getSchema(); } + /** + * Returns the cached list of known fields from the accumulated schema. + * Uses SchemaAnalyzer's version-based caching — only recomputed when the schema changes. + */ + public getKnownFields(): FieldEntry[] { + return this._schemaAnalyzer.getKnownFields(); + } + // ============================================================================ // Query Insights Methods // ============================================================================ diff --git a/src/utils/json/data-api/SchemaAnalyzer.ts b/src/utils/json/data-api/SchemaAnalyzer.ts index c340172a9..93b73a36a 100644 --- a/src/utils/json/data-api/SchemaAnalyzer.ts +++ b/src/utils/json/data-api/SchemaAnalyzer.ts @@ -9,6 +9,7 @@ import Denque from 'denque'; import { type Document, type WithId } from 'mongodb'; import { type JSONSchema } from '../JSONSchema'; import { BSONTypes } from './BSONTypes'; +import { type FieldEntry, getKnownFields as getKnownFieldsFromSchema } from './autocomplete/getKnownFields'; /** * Incremental schema analyzer for documents from the MongoDB API / DocumentDB API. @@ -20,6 +21,18 @@ import { BSONTypes } from './BSONTypes'; */ export class SchemaAnalyzer { private _schema: JSONSchema = {}; + private _version: number = 0; + private _knownFieldsCache: FieldEntry[] | null = null; + private _knownFieldsCacheVersion: number = -1; + + /** + * A monotonically increasing version counter. Incremented on every mutation + * (addDocument, addDocuments, reset). Adapters can store this value alongside + * their cached derived data and recompute only when it changes. + */ + get version(): number { + return this._version; + } /** * Adds a single document to the accumulated schema. @@ -27,16 +40,19 @@ export class SchemaAnalyzer { */ addDocument(document: WithId): void { updateSchemaWithDocumentInternal(this._schema, document); + this._version++; } /** * Adds multiple documents to the accumulated schema. * Convenience method equivalent to calling addDocument() for each. + * Increments version once for the entire batch — not per document. */ addDocuments(documents: ReadonlyArray>): void { for (const doc of documents) { - this.addDocument(doc); + updateSchemaWithDocumentInternal(this._schema, doc); } + this._version++; } /** @@ -59,11 +75,13 @@ export class SchemaAnalyzer { */ reset(): void { this._schema = {}; + this._version++; } /** * Creates a deep copy of this analyzer, including all accumulated schema data. * Useful for aggregation stage branching where each stage needs its own schema state. + * The clone starts with version 0, independent from the original. */ clone(): SchemaAnalyzer { const copy = new SchemaAnalyzer(); @@ -71,6 +89,18 @@ export class SchemaAnalyzer { return copy; } + /** + * Returns the cached list of known fields (all nesting levels, sorted). + * Recomputed only when the schema version has changed since the last call. + */ + getKnownFields(): FieldEntry[] { + if (this._knownFieldsCacheVersion !== this._version || this._knownFieldsCache === null) { + this._knownFieldsCache = getKnownFieldsFromSchema(this._schema); + this._knownFieldsCacheVersion = this._version; + } + return this._knownFieldsCache; + } + /** * Creates a SchemaAnalyzer from a single document. * Equivalent to creating an instance and calling addDocument() once. diff --git a/src/webviews/documentdb/collectionView/collectionViewRouter.ts b/src/webviews/documentdb/collectionView/collectionViewRouter.ts index c2d71e1d9..0e4b6a81b 100644 --- a/src/webviews/documentdb/collectionView/collectionViewRouter.ts +++ b/src/webviews/documentdb/collectionView/collectionViewRouter.ts @@ -12,7 +12,7 @@ import { type JSONSchema } from 'vscode-json-languageservice'; import { z } from 'zod'; import { ClusterSession } from '../../../documentdb/ClusterSession'; import { getConfirmationAsInSettings } from '../../../utils/dialogs/getConfirmation'; -import { getKnownFields, type FieldEntry } from '../../../utils/json/data-api/autocomplete/getKnownFields'; +import { type FieldEntry } from '../../../utils/json/data-api/autocomplete/getKnownFields'; import { publicProcedureWithTelemetry, router, type WithTelemetry } from '../../api/extension-server/trpc'; import * as l10n from '@vscode/l10n'; @@ -241,8 +241,7 @@ export const collectionsViewRouter = router({ const session: ClusterSession = ClusterSession.getSession(myCtx.sessionId); - const _currentJsonSchema = session.getCurrentSchema(); - const autoCompletionData: FieldEntry[] = getKnownFields(_currentJsonSchema); + const autoCompletionData: FieldEntry[] = session.getKnownFields(); let querySchema: JSONSchema; From 633f0b4370e0551b5c9c6c1e893209c0f2e2deed Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Feb 2026 07:39:35 +0000 Subject: [PATCH 008/128] Initial plan From 74eeeac88cd4b4118c1839487922b46c42b11b89 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Feb 2026 07:42:40 +0000 Subject: [PATCH 009/128] refactor: remove debug console.log statements from tests Co-authored-by: tnaum-ms <171359267+tnaum-ms@users.noreply.github.com> --- src/utils/json/data-api/SchemaAnalyzer.arrayStats.test.ts | 4 ---- src/utils/json/data-api/SchemaAnalyzer.test.ts | 1 - 2 files changed, 5 deletions(-) diff --git a/src/utils/json/data-api/SchemaAnalyzer.arrayStats.test.ts b/src/utils/json/data-api/SchemaAnalyzer.arrayStats.test.ts index 1f0ce7a3e..00f53d98f 100644 --- a/src/utils/json/data-api/SchemaAnalyzer.arrayStats.test.ts +++ b/src/utils/json/data-api/SchemaAnalyzer.arrayStats.test.ts @@ -274,10 +274,6 @@ describe('Array element occurrence analysis', () => { // doc2 second element (15): aggregateStatsForValue → max becomes 15 // final: min=5, max=15 ← WRONG (lost 30 from doc1) - // Let's check what actually happens: - console.log('numEntry x-minValue:', numEntry['x-minValue']); - console.log('numEntry x-maxValue:', numEntry['x-maxValue']); - // This test documents the actual behavior (might be buggy): expect(numEntry['x-minValue']).toBe(5); // If the bug exists, this will be 15 instead of 30: diff --git a/src/utils/json/data-api/SchemaAnalyzer.test.ts b/src/utils/json/data-api/SchemaAnalyzer.test.ts index fe4d83629..cb2b362c7 100644 --- a/src/utils/json/data-api/SchemaAnalyzer.test.ts +++ b/src/utils/json/data-api/SchemaAnalyzer.test.ts @@ -19,7 +19,6 @@ describe('DocumentDB Schema Analyzer', () => { it('prints out schema for testing', () => { const analyzer = SchemaAnalyzer.fromDocument(embeddedDocumentOnly); const schema = analyzer.getSchema(); - console.log(JSON.stringify(schema, null, 2)); expect(schema).toBeDefined(); }); From d8d07095af3a26f39d29472dbad3041cf853efaf Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Feb 2026 09:58:59 +0100 Subject: [PATCH 010/128] test: add comprehensive tests for SchemaAnalyzer versioning and caching behavior --- .../SchemaAnalyzer.versioning.test.ts | 663 ++++++++++++++++++ 1 file changed, 663 insertions(+) create mode 100644 src/utils/json/data-api/SchemaAnalyzer.versioning.test.ts diff --git a/src/utils/json/data-api/SchemaAnalyzer.versioning.test.ts b/src/utils/json/data-api/SchemaAnalyzer.versioning.test.ts new file mode 100644 index 000000000..91a6fbddc --- /dev/null +++ b/src/utils/json/data-api/SchemaAnalyzer.versioning.test.ts @@ -0,0 +1,663 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ObjectId, type Document, type WithId } from 'mongodb'; +import { type JSONSchema } from '../JSONSchema'; +import { SchemaAnalyzer } from './SchemaAnalyzer'; + +// ------------------------------------------------------------------ +// Test fixtures +// ------------------------------------------------------------------ + +function makeDoc(fields: Record = {}): WithId { + return { _id: new ObjectId(), ...fields }; +} + +// ------------------------------------------------------------------ +// Version counter +// ------------------------------------------------------------------ +describe('SchemaAnalyzer version counter', () => { + it('starts at 0 for a new analyzer', () => { + const analyzer = new SchemaAnalyzer(); + expect(analyzer.version).toBe(0); + }); + + it('increments on addDocument()', () => { + const analyzer = new SchemaAnalyzer(); + analyzer.addDocument(makeDoc({ a: 1 })); + expect(analyzer.version).toBe(1); + + analyzer.addDocument(makeDoc({ b: 2 })); + expect(analyzer.version).toBe(2); + }); + + it('increments only once for addDocuments() (batch)', () => { + const analyzer = new SchemaAnalyzer(); + const docs = [makeDoc({ a: 1 }), makeDoc({ b: 2 }), makeDoc({ c: 3 })]; + + analyzer.addDocuments(docs); + expect(analyzer.version).toBe(1); + }); + + it('increments on reset()', () => { + const analyzer = SchemaAnalyzer.fromDocument(makeDoc({ x: 1 })); + expect(analyzer.version).toBe(1); + + analyzer.reset(); + expect(analyzer.version).toBe(2); + }); + + it('cloned analyzer starts with version 0 (independent from original)', () => { + const original = new SchemaAnalyzer(); + original.addDocument(makeDoc({ a: 1 })); + original.addDocument(makeDoc({ b: 2 })); + expect(original.version).toBe(2); + + const cloned = original.clone(); + expect(cloned.version).toBe(0); + + // Mutating the clone does not affect the original's version + cloned.addDocument(makeDoc({ c: 3 })); + expect(cloned.version).toBe(1); + expect(original.version).toBe(2); + }); + + it('accumulates across mixed operations', () => { + const analyzer = new SchemaAnalyzer(); + // addDocument +1 + analyzer.addDocument(makeDoc()); + expect(analyzer.version).toBe(1); + + // addDocuments +1 (batch) + analyzer.addDocuments([makeDoc(), makeDoc()]); + expect(analyzer.version).toBe(2); + + // reset +1 + analyzer.reset(); + expect(analyzer.version).toBe(3); + + // addDocument after reset +1 + analyzer.addDocument(makeDoc()); + expect(analyzer.version).toBe(4); + }); + + it('fromDocument() factory yields version 1', () => { + const analyzer = SchemaAnalyzer.fromDocument(makeDoc({ a: 1 })); + expect(analyzer.version).toBe(1); + }); + + it('fromDocuments() factory yields version 1', () => { + const analyzer = SchemaAnalyzer.fromDocuments([makeDoc(), makeDoc(), makeDoc()]); + expect(analyzer.version).toBe(1); + }); +}); + +// ------------------------------------------------------------------ +// Version-based caching (getKnownFields cache) +// ------------------------------------------------------------------ +describe('SchemaAnalyzer getKnownFields cache', () => { + it('is populated on first call to getKnownFields()', () => { + const analyzer = SchemaAnalyzer.fromDocument(makeDoc({ name: 'Alice', age: 30 })); + const fields = analyzer.getKnownFields(); + + expect(fields.length).toBeGreaterThan(0); + // Should contain _id, age, name + const paths = fields.map((f) => f.path); + expect(paths).toContain('_id'); + expect(paths).toContain('name'); + expect(paths).toContain('age'); + }); + + it('is reused when version has not changed (same reference)', () => { + const analyzer = SchemaAnalyzer.fromDocument(makeDoc({ name: 'Alice' })); + const first = analyzer.getKnownFields(); + const second = analyzer.getKnownFields(); + + // Same array reference — cache was reused, not recomputed + expect(second).toBe(first); + }); + + it('is invalidated when addDocument() is called', () => { + const analyzer = SchemaAnalyzer.fromDocument(makeDoc({ name: 'Alice' })); + const before = analyzer.getKnownFields(); + + analyzer.addDocument(makeDoc({ name: 'Bob', email: 'bob@test.com' })); + const after = analyzer.getKnownFields(); + + // Different reference — cache was recomputed + expect(after).not.toBe(before); + // New field should be present + expect(after.map((f) => f.path)).toContain('email'); + }); + + it('is invalidated when addDocuments() is called', () => { + const analyzer = SchemaAnalyzer.fromDocument(makeDoc({ name: 'Alice' })); + const before = analyzer.getKnownFields(); + + analyzer.addDocuments([makeDoc({ score: 42 }), makeDoc({ level: 7 })]); + const after = analyzer.getKnownFields(); + + expect(after).not.toBe(before); + const paths = after.map((f) => f.path); + expect(paths).toContain('score'); + expect(paths).toContain('level'); + }); + + it('is invalidated when reset() is called', () => { + const analyzer = SchemaAnalyzer.fromDocument(makeDoc({ name: 'Alice' })); + const before = analyzer.getKnownFields(); + expect(before.length).toBeGreaterThan(0); + + analyzer.reset(); + const after = analyzer.getKnownFields(); + + expect(after).not.toBe(before); + // After reset the schema is empty so no fields + expect(after).toHaveLength(0); + }); + + it('returns updated results after cache invalidation', () => { + const analyzer = new SchemaAnalyzer(); + // Empty analyzer → no known fields + expect(analyzer.getKnownFields()).toHaveLength(0); + + // Add first doc + analyzer.addDocument(makeDoc({ x: 1 })); + const fields1 = analyzer.getKnownFields(); + expect(fields1.map((f) => f.path)).toEqual(expect.arrayContaining(['_id', 'x'])); + + // Add second doc with new field + analyzer.addDocument(makeDoc({ x: 2, y: 'hello' })); + const fields2 = analyzer.getKnownFields(); + expect(fields2).not.toBe(fields1); + expect(fields2.map((f) => f.path)).toContain('y'); + }); + + it('clone gets its own independent cache', () => { + const original = SchemaAnalyzer.fromDocument(makeDoc({ name: 'Alice' })); + const originalFields = original.getKnownFields(); + + const cloned = original.clone(); + const clonedFields = cloned.getKnownFields(); + + // Both should have the same content but be independent objects + expect(clonedFields).not.toBe(originalFields); + expect(clonedFields.map((f) => f.path)).toEqual(originalFields.map((f) => f.path)); + + // Mutating the clone should not affect the original cache + cloned.addDocument(makeDoc({ extra: true })); + const clonedFieldsAfter = cloned.getKnownFields(); + expect(clonedFieldsAfter.map((f) => f.path)).toContain('extra'); + expect(original.getKnownFields().map((f) => f.path)).not.toContain('extra'); + }); +}); + +// ------------------------------------------------------------------ +// Instances and types counting +// ------------------------------------------------------------------ +describe('SchemaAnalyzer instances and types counting', () => { + describe('x-occurrence (field instance counting)', () => { + it('counts 1 for a field present in a single document', () => { + const analyzer = SchemaAnalyzer.fromDocument(makeDoc({ name: 'Alice' })); + const schema = analyzer.getSchema(); + const nameField = schema.properties?.['name'] as JSONSchema; + expect(nameField['x-occurrence']).toBe(1); + }); + + it('counts correctly across multiple documents', () => { + const analyzer = new SchemaAnalyzer(); + analyzer.addDocument(makeDoc({ name: 'Alice', age: 30 })); + analyzer.addDocument(makeDoc({ name: 'Bob', age: 25 })); + analyzer.addDocument(makeDoc({ name: 'Carol' })); // no age + + const schema = analyzer.getSchema(); + expect((schema.properties?.['name'] as JSONSchema)['x-occurrence']).toBe(3); + expect((schema.properties?.['age'] as JSONSchema)['x-occurrence']).toBe(2); + }); + + it('counts sparse fields correctly (field missing in some documents)', () => { + const analyzer = new SchemaAnalyzer(); + analyzer.addDocument(makeDoc({ a: 1, b: 2, c: 3 })); + analyzer.addDocument(makeDoc({ a: 10 })); // only 'a' + analyzer.addDocument(makeDoc({ a: 100, c: 300 })); // 'a' and 'c' + + const schema = analyzer.getSchema(); + expect((schema.properties?.['a'] as JSONSchema)['x-occurrence']).toBe(3); + expect((schema.properties?.['b'] as JSONSchema)['x-occurrence']).toBe(1); + expect((schema.properties?.['c'] as JSONSchema)['x-occurrence']).toBe(2); + }); + + it('counts occurrences for nested object properties', () => { + const analyzer = new SchemaAnalyzer(); + analyzer.addDocument(makeDoc({ user: { name: 'Alice', age: 30 } })); + analyzer.addDocument(makeDoc({ user: { name: 'Bob' } })); // no age + + const schema = analyzer.getSchema(); + const userField = schema.properties?.['user'] as JSONSchema; + const objectEntry = userField.anyOf?.find((e) => (e as JSONSchema).type === 'object') as JSONSchema; + + expect((objectEntry.properties?.['name'] as JSONSchema)['x-occurrence']).toBe(2); + expect((objectEntry.properties?.['age'] as JSONSchema)['x-occurrence']).toBe(1); + }); + }); + + describe('x-typeOccurrence (type counting)', () => { + it('counts type occurrences for a single-type field', () => { + const analyzer = new SchemaAnalyzer(); + analyzer.addDocument(makeDoc({ name: 'Alice' })); + analyzer.addDocument(makeDoc({ name: 'Bob' })); + analyzer.addDocument(makeDoc({ name: 'Carol' })); + + const schema = analyzer.getSchema(); + const nameField = schema.properties?.['name'] as JSONSchema; + const stringEntry = nameField.anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'string', + ) as JSONSchema; + + expect(stringEntry['x-typeOccurrence']).toBe(3); + }); + + it('counts type occurrences for polymorphic fields', () => { + const analyzer = new SchemaAnalyzer(); + analyzer.addDocument(makeDoc({ value: 'hello' })); + analyzer.addDocument(makeDoc({ value: 42 })); + analyzer.addDocument(makeDoc({ value: 'world' })); + analyzer.addDocument(makeDoc({ value: true })); + + const schema = analyzer.getSchema(); + const valueField = schema.properties?.['value'] as JSONSchema; + + const stringEntry = valueField.anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'string', + ) as JSONSchema; + const booleanEntry = valueField.anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'boolean', + ) as JSONSchema; + + // 2 strings, 1 number, 1 boolean + expect(stringEntry['x-typeOccurrence']).toBe(2); + expect(booleanEntry['x-typeOccurrence']).toBe(1); + + // total x-occurrence should equal sum of x-typeOccurrence values + const totalTypeOccurrence = (valueField.anyOf as JSONSchema[]).reduce( + (sum, entry) => sum + ((entry['x-typeOccurrence'] as number) ?? 0), + 0, + ); + expect(valueField['x-occurrence']).toBe(totalTypeOccurrence); + }); + + it('counts array element types across documents', () => { + const analyzer = new SchemaAnalyzer(); + analyzer.addDocument(makeDoc({ tags: ['a', 'b'] })); // 2 strings + analyzer.addDocument(makeDoc({ tags: ['c', 42] })); // 1 string + 1 number + analyzer.addDocument(makeDoc({ tags: [true] })); // 1 boolean + + const schema = analyzer.getSchema(); + const tagsField = schema.properties?.['tags'] as JSONSchema; + const arrayEntry = tagsField.anyOf?.find((e) => (e as JSONSchema)['x-bsonType'] === 'array') as JSONSchema; + const itemsSchema = arrayEntry.items as JSONSchema; + + const stringEntry = itemsSchema.anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'string', + ) as JSONSchema; + const booleanEntry = itemsSchema.anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'boolean', + ) as JSONSchema; + + // 3 string elements total: "a", "b", "c" + expect(stringEntry['x-typeOccurrence']).toBe(3); + + // 1 boolean element + expect(booleanEntry['x-typeOccurrence']).toBe(1); + }); + + it('type occurrence count equals field occurrence for a single-type field', () => { + const analyzer = new SchemaAnalyzer(); + for (let i = 0; i < 5; i++) { + analyzer.addDocument(makeDoc({ score: i * 10 })); + } + + const schema = analyzer.getSchema(); + const scoreField = schema.properties?.['score'] as JSONSchema; + const typeEntries = scoreField.anyOf as JSONSchema[]; + + // Only one type, so its typeOccurrence should equal the field occurrence + expect(typeEntries).toHaveLength(1); + expect(typeEntries[0]['x-typeOccurrence']).toBe(scoreField['x-occurrence']); + }); + }); + + describe('x-documentsInspected counting', () => { + it('tracks document count at root level', () => { + const analyzer = new SchemaAnalyzer(); + analyzer.addDocument(makeDoc({ a: 1 })); + analyzer.addDocument(makeDoc({ b: 2 })); + analyzer.addDocument(makeDoc({ c: 3 })); + + expect(analyzer.getSchema()['x-documentsInspected']).toBe(3); + expect(analyzer.getDocumentCount()).toBe(3); + }); + + it('tracks object instances for nested objects', () => { + const analyzer = new SchemaAnalyzer(); + analyzer.addDocument(makeDoc({ info: { x: 1 } })); + analyzer.addDocument(makeDoc({ info: { x: 2, y: 3 } })); + + const schema = analyzer.getSchema(); + const infoField = schema.properties?.['info'] as JSONSchema; + const objectEntry = infoField.anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'object', + ) as JSONSchema; + + expect(objectEntry['x-documentsInspected']).toBe(2); + }); + + it('tracks object instances inside arrays accurately', () => { + const analyzer = new SchemaAnalyzer(); + // doc1: array with 2 objects + analyzer.addDocument(makeDoc({ items: [{ a: 1 }, { a: 2 }] })); + // doc2: array with 1 object + analyzer.addDocument(makeDoc({ items: [{ a: 3, b: 4 }] })); + + const schema = analyzer.getSchema(); + const itemsField = schema.properties?.['items'] as JSONSchema; + const arrayEntry = itemsField.anyOf?.find((e) => (e as JSONSchema)['x-bsonType'] === 'array') as JSONSchema; + const objectEntry = (arrayEntry.items as JSONSchema).anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'object', + ) as JSONSchema; + + // 3 objects total (2 from doc1, 1 from doc2) + expect(objectEntry['x-documentsInspected']).toBe(3); + // "a" appears in all 3 objects + expect((objectEntry.properties?.['a'] as JSONSchema)['x-occurrence']).toBe(3); + // "b" appears in 1 of 3 objects + expect((objectEntry.properties?.['b'] as JSONSchema)['x-occurrence']).toBe(1); + }); + + it('resets to 0 after reset()', () => { + const analyzer = SchemaAnalyzer.fromDocuments([makeDoc({ a: 1 }), makeDoc({ b: 2 })]); + expect(analyzer.getDocumentCount()).toBe(2); + + analyzer.reset(); + expect(analyzer.getDocumentCount()).toBe(0); + }); + }); + + describe('probability correctness (occurrence / documentsInspected)', () => { + it('yields 100% for fields present in every document', () => { + const analyzer = new SchemaAnalyzer(); + for (let i = 0; i < 10; i++) { + analyzer.addDocument(makeDoc({ name: `user-${i}` })); + } + + const schema = analyzer.getSchema(); + const occurrence = (schema.properties?.['name'] as JSONSchema)['x-occurrence'] as number; + const total = schema['x-documentsInspected'] as number; + expect(occurrence / total).toBe(1); + }); + + it('yields correct fraction for sparse fields', () => { + const analyzer = new SchemaAnalyzer(); + // 3 docs with 'a', 1 doc with 'b' + analyzer.addDocument(makeDoc({ a: 1, b: 10 })); + analyzer.addDocument(makeDoc({ a: 2 })); + analyzer.addDocument(makeDoc({ a: 3 })); + + const schema = analyzer.getSchema(); + const total = schema['x-documentsInspected'] as number; + const aOccurrence = (schema.properties?.['a'] as JSONSchema)['x-occurrence'] as number; + const bOccurrence = (schema.properties?.['b'] as JSONSchema)['x-occurrence'] as number; + + expect(aOccurrence / total).toBe(1); // 3/3 + expect(bOccurrence / total).toBeCloseTo(1 / 3); // 1/3 + }); + + it('yields correct fraction for nested objects inside arrays', () => { + const analyzer = new SchemaAnalyzer(); + analyzer.addDocument( + makeDoc({ + items: [ + { name: 'A', price: 10 }, + { name: 'B' }, // no price + ], + }), + ); + analyzer.addDocument(makeDoc({ items: [{ name: 'C', price: 20 }] })); + + const schema = analyzer.getSchema(); + const itemsField = schema.properties?.['items'] as JSONSchema; + const arrayEntry = itemsField.anyOf?.find((e) => (e as JSONSchema)['x-bsonType'] === 'array') as JSONSchema; + const objectEntry = (arrayEntry.items as JSONSchema).anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'object', + ) as JSONSchema; + + const denominator = objectEntry['x-documentsInspected'] as number; + const nameOccurrence = (objectEntry.properties?.['name'] as JSONSchema)['x-occurrence'] as number; + const priceOccurrence = (objectEntry.properties?.['price'] as JSONSchema)['x-occurrence'] as number; + + expect(denominator).toBe(3); // 3 objects total + expect(nameOccurrence / denominator).toBe(1); // 3/3 + expect(priceOccurrence / denominator).toBeCloseTo(2 / 3); // 2/3 + }); + }); + + describe('array and nested array counting', () => { + it('counts x-typeOccurrence for the array type entry across documents', () => { + const analyzer = new SchemaAnalyzer(); + analyzer.addDocument(makeDoc({ tags: ['a'] })); + analyzer.addDocument(makeDoc({ tags: ['b', 'c'] })); + analyzer.addDocument(makeDoc({ tags: 42 })); // not an array + + const schema = analyzer.getSchema(); + const tagsField = schema.properties?.['tags'] as JSONSchema; + + // Field seen 3 times total + expect(tagsField['x-occurrence']).toBe(3); + + const arrayEntry = tagsField.anyOf?.find((e) => (e as JSONSchema)['x-bsonType'] === 'array') as JSONSchema; + + // Array type seen 2 out of 3 times + expect(arrayEntry['x-typeOccurrence']).toBe(2); + + // x-minItems / x-maxItems tracked across array instances + expect(arrayEntry['x-minItems']).toBe(1); + expect(arrayEntry['x-maxItems']).toBe(2); + }); + + it('counts x-minItems / x-maxItems for arrays across documents', () => { + const analyzer = new SchemaAnalyzer(); + analyzer.addDocument(makeDoc({ nums: [1, 2, 3] })); // length 3 + analyzer.addDocument(makeDoc({ nums: [10] })); // length 1 + analyzer.addDocument(makeDoc({ nums: [4, 5, 6, 7, 8] })); // length 5 + + const schema = analyzer.getSchema(); + const numsField = schema.properties?.['nums'] as JSONSchema; + const arrayEntry = numsField.anyOf?.find((e) => (e as JSONSchema)['x-bsonType'] === 'array') as JSONSchema; + + expect(arrayEntry['x-minItems']).toBe(1); + expect(arrayEntry['x-maxItems']).toBe(5); + expect(arrayEntry['x-typeOccurrence']).toBe(3); + }); + + it('counts nested arrays (arrays within arrays)', () => { + const analyzer = new SchemaAnalyzer(); + // matrix is an array of arrays of numbers + analyzer.addDocument( + makeDoc({ + matrix: [ + [1, 2], + [3, 4, 5], + ], + }), + ); + analyzer.addDocument(makeDoc({ matrix: [[10]] })); + + const schema = analyzer.getSchema(); + const matrixField = schema.properties?.['matrix'] as JSONSchema; + const outerArrayEntry = matrixField.anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'array', + ) as JSONSchema; + + // Outer array seen in 2 documents + expect(outerArrayEntry['x-typeOccurrence']).toBe(2); + // doc1 has 2 inner arrays, doc2 has 1 + expect(outerArrayEntry['x-minItems']).toBe(1); + expect(outerArrayEntry['x-maxItems']).toBe(2); + + // Inner arrays: items type should be 'array' + const innerArrayEntry = (outerArrayEntry.items as JSONSchema).anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'array', + ) as JSONSchema; + expect(innerArrayEntry).toBeDefined(); + // 3 inner arrays total: [1,2], [3,4,5], [10] + expect(innerArrayEntry['x-typeOccurrence']).toBe(3); + // inner array lengths: 2, 3, 1 + expect(innerArrayEntry['x-minItems']).toBe(1); + expect(innerArrayEntry['x-maxItems']).toBe(3); + + // Elements inside inner arrays are numbers + const numberEntry = (innerArrayEntry.items as JSONSchema).anyOf?.find( + (e) => (e as JSONSchema).type === 'number', + ) as JSONSchema; + expect(numberEntry).toBeDefined(); + // 6 numbers total: 1,2,3,4,5,10 + expect(numberEntry['x-typeOccurrence']).toBe(6); + }); + + it('counts objects within arrays within objects (deep nesting)', () => { + const analyzer = new SchemaAnalyzer(); + analyzer.addDocument( + makeDoc({ + company: { + departments: [ + { name: 'Eng', employees: [{ role: 'Dev' }, { role: 'QA', level: 3 }] }, + { name: 'Sales' }, + ], + }, + }), + ); + analyzer.addDocument( + makeDoc({ + company: { + departments: [{ name: 'HR', employees: [{ role: 'Recruiter' }] }], + }, + }), + ); + + const schema = analyzer.getSchema(); + + // company is an object + const companyField = schema.properties?.['company'] as JSONSchema; + const companyObj = companyField.anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'object', + ) as JSONSchema; + expect(companyObj['x-documentsInspected']).toBe(2); + + // departments is an array inside company + const deptField = companyObj.properties?.['departments'] as JSONSchema; + const deptArrayEntry = deptField.anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'array', + ) as JSONSchema; + expect(deptArrayEntry['x-typeOccurrence']).toBe(2); + + // department objects: 2 from doc1 + 1 from doc2 = 3 + const deptObjEntry = (deptArrayEntry.items as JSONSchema).anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'object', + ) as JSONSchema; + expect(deptObjEntry['x-documentsInspected']).toBe(3); + expect(deptObjEntry['x-typeOccurrence']).toBe(3); + + // "name" in all 3 department objects, "employees" in 2 of 3 + expect((deptObjEntry.properties?.['name'] as JSONSchema)['x-occurrence']).toBe(3); + expect((deptObjEntry.properties?.['employees'] as JSONSchema)['x-occurrence']).toBe(2); + + // employees is an array inside department objects + const empField = deptObjEntry.properties?.['employees'] as JSONSchema; + const empArrayEntry = empField.anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'array', + ) as JSONSchema; + expect(empArrayEntry['x-typeOccurrence']).toBe(2); + + // employee objects: 2 from first dept + 1 from HR = 3 + const empObjEntry = (empArrayEntry.items as JSONSchema).anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'object', + ) as JSONSchema; + expect(empObjEntry['x-documentsInspected']).toBe(3); + + // "role" in all 3 employee objects, "level" in 1 + expect((empObjEntry.properties?.['role'] as JSONSchema)['x-occurrence']).toBe(3); + expect((empObjEntry.properties?.['level'] as JSONSchema)['x-occurrence']).toBe(1); + }); + + it('tracks mixed types inside arrays (objects + primitives)', () => { + const analyzer = new SchemaAnalyzer(); + analyzer.addDocument(makeDoc({ data: ['hello', { key: 'val' }, 42] })); + analyzer.addDocument(makeDoc({ data: [{ key: 'v2', extra: true }] })); + + const schema = analyzer.getSchema(); + const dataField = schema.properties?.['data'] as JSONSchema; + const arrayEntry = dataField.anyOf?.find((e) => (e as JSONSchema)['x-bsonType'] === 'array') as JSONSchema; + const itemsSchema = arrayEntry.items as JSONSchema; + + // string: 1, object: 2, number: 1 + const stringEntry = itemsSchema.anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'string', + ) as JSONSchema; + const objectEntry = itemsSchema.anyOf?.find( + (e) => (e as JSONSchema)['x-bsonType'] === 'object', + ) as JSONSchema; + + expect(stringEntry['x-typeOccurrence']).toBe(1); + expect(objectEntry['x-typeOccurrence']).toBe(2); + expect(objectEntry['x-documentsInspected']).toBe(2); + + // "key" in both objects, "extra" in 1 + expect((objectEntry.properties?.['key'] as JSONSchema)['x-occurrence']).toBe(2); + expect((objectEntry.properties?.['extra'] as JSONSchema)['x-occurrence']).toBe(1); + }); + }); + + describe('addDocuments vs sequential addDocument equivalence', () => { + it('produces identical occurrence counts', () => { + const docs = [makeDoc({ a: 1, b: 'x' }), makeDoc({ a: 2 }), makeDoc({ a: 3, c: true })]; + + const batch = new SchemaAnalyzer(); + batch.addDocuments(docs); + + const sequential = new SchemaAnalyzer(); + for (const doc of docs) { + sequential.addDocument(doc); + } + + const batchSchema = batch.getSchema(); + const seqSchema = sequential.getSchema(); + + // Root counts match + expect(batchSchema['x-documentsInspected']).toBe(seqSchema['x-documentsInspected']); + + // Field-level occurrence counts match + for (const key of Object.keys(batchSchema.properties ?? {})) { + const batchField = batchSchema.properties?.[key] as JSONSchema; + const seqField = seqSchema.properties?.[key] as JSONSchema; + expect(batchField['x-occurrence']).toBe(seqField['x-occurrence']); + } + }); + + it('produces identical type occurrence counts', () => { + const docs = [makeDoc({ value: 'hello' }), makeDoc({ value: 42 }), makeDoc({ value: 'world' })]; + + const batch = new SchemaAnalyzer(); + batch.addDocuments(docs); + + const sequential = new SchemaAnalyzer(); + for (const doc of docs) { + sequential.addDocument(doc); + } + + // Stringify the schemas to compare their full type entry structures + expect(JSON.stringify(batch.getSchema())).toBe(JSON.stringify(sequential.getSchema())); + }); + }); +}); From ebdde30042241bfe0b9b6019e566face77e4054e Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Feb 2026 10:03:18 +0100 Subject: [PATCH 011/128] refactor: remove console.log statements from test files for cleaner output --- src/utils/slickgrid/mongo/toSlickGridTable.test.ts | 1 - test/mongoGetCommand.test.ts | 4 ---- 2 files changed, 5 deletions(-) diff --git a/src/utils/slickgrid/mongo/toSlickGridTable.test.ts b/src/utils/slickgrid/mongo/toSlickGridTable.test.ts index 69156bf1b..4b1d0af3f 100644 --- a/src/utils/slickgrid/mongo/toSlickGridTable.test.ts +++ b/src/utils/slickgrid/mongo/toSlickGridTable.test.ts @@ -76,7 +76,6 @@ describe('toSlickGridTable', () => { it('at a nested level', () => { const tableData = getDataAtPath(mongoDocuments, ['nestedDocument']); - console.log(tableData); expect(tableData).toHaveLength(5); expect(tableData[0]['key']).toBeDefined(); diff --git a/test/mongoGetCommand.test.ts b/test/mongoGetCommand.test.ts index 7b4ce3f4d..bf34fa867 100644 --- a/test/mongoGetCommand.test.ts +++ b/test/mongoGetCommand.test.ts @@ -797,7 +797,6 @@ suite('scrapbook parsing Tests', () => { const commands: MongoCommand[] = getAllCommandsFromText(text); const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - console.log('generatedRegExp', generatedRegExp); assert.deepEqual(generatedRegExp.options, 'i'); assert.deepEqual(generatedRegExp.pattern, '789$'); }); @@ -838,11 +837,8 @@ suite('scrapbook parsing Tests', () => { // The regex parsing tests following this test should help zero-in on which case isn't handled properly. test('test regular expression parsing - with many special cases', () => { const text = `db.test1.beep.find({ sku: /^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$/ })`; - console.log(text); const commands: MongoCommand[] = getAllCommandsFromText(text); - console.log('commands', commands); const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - console.log('command', command); const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; assert.deepEqual(generatedRegExp.options, ''); assert.deepEqual(generatedRegExp.pattern, '^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$'); From c23b604f64add8fba6a50ae8fa89e9ee485da0c3 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Feb 2026 10:42:45 +0100 Subject: [PATCH 012/128] refactor: enhance handling of special characters in field names for TypeScript definitions and completion items --- .../json/data-api/autocomplete/future-work.md | 140 ++++++++++++++++++ .../data-api/autocomplete/getKnownFields.ts | 10 ++ .../autocomplete/toFieldCompletionItems.ts | 30 +++- .../toTypeScriptDefinition.test.ts | 91 ++++++++++++ .../autocomplete/toTypeScriptDefinition.ts | 30 +++- 5 files changed, 297 insertions(+), 4 deletions(-) create mode 100644 src/utils/json/data-api/autocomplete/future-work.md diff --git a/src/utils/json/data-api/autocomplete/future-work.md b/src/utils/json/data-api/autocomplete/future-work.md new file mode 100644 index 000000000..6e77d2913 --- /dev/null +++ b/src/utils/json/data-api/autocomplete/future-work.md @@ -0,0 +1,140 @@ +# Autocomplete — Future Work + +Outstanding TODOs flagged in code during the schema transformer implementation (PR #506). +These must be resolved before the completion providers ship to users. + +--- + +## 1. `SPECIAL_CHARS_PATTERN` is incomplete + `insertText` quoting doesn't escape + +**Severity:** Medium — will produce broken query expressions for real-world field names +**File:** `toFieldCompletionItems.ts` — `SPECIAL_CHARS_PATTERN` and `insertText` construction +**When to fix:** Before the `CompletionItemProvider` is wired up + +### Problem + +`SPECIAL_CHARS_PATTERN` (`/[.$\s]/`) only catches dots, `$`, and whitespace. MongoDB field names can also contain: + +| Character | Example field name | Current behavior | +| ---------------- | ------------------ | ----------------------------------------------- | +| Dash `-` | `order-items` | Inserted unquoted → breaks JSON key context | +| Brackets `[]` | `items[0]` | Inserted unquoted | +| Double quote `"` | `say"hi"` | Wrapped as `"say"hi""` → broken string | +| Single quote `'` | `it's` | Inserted unquoted (may break some contexts) | +| Backslash `\` | `back\slash` | Wrapped as `"back\slash"` → unescaped backslash | + +Additionally, when quoting _is_ triggered, the current logic (`"${entry.path}"`) does not escape embedded `"` or `\` inside the value. + +### Proposed fix + +1. Replace `SPECIAL_CHARS_PATTERN` with an identifier check (same as `safePropertyName` in `toTypeScriptDefinition.ts`): + ```typescript + const JS_IDENTIFIER = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/; + const needsQuoting = !JS_IDENTIFIER.test(entry.path); + ``` +2. When quoting, escape the content: + ```typescript + const escaped = entry.path.replace(/\\/g, '\\\\').replace(/"/g, '\\"'); + insertText: needsQuoting ? `"${escaped}"` : entry.path, + ``` + +### Note on display vs insert + +The `fieldName` property intentionally stays unescaped (human-readable) for the completion list label. Only `insertText` gets escaped — this is by design, so users see clean names in the dropdown and the escaped form is inserted on selection. + +--- + +## 2. `referenceText` is invalid MQL for special field names + +**Severity:** Medium — will generate broken aggregation expressions +**File:** `toFieldCompletionItems.ts` — `referenceText` construction +**When to fix:** Before the aggregation completion provider is wired up + +### Problem + +`referenceText` is always `$${entry.path}` (e.g., `$address.city`). In MQL, the `$field.path` syntax only works when every segment is a valid identifier without dots, spaces, or `$`. For field names like `order-items`, `a.b`, or `my field`, the `$` prefix syntax produces invalid references. + +### Examples + +| Field name | Current `referenceText` | Valid? | Correct MQL | +| ------------------- | ----------------------- | -------------- | ------------------------------------ | +| `age` | `$age` | ✅ | `$age` | +| `address.city` | `$address.city` | ✅ (nested) | `$address.city` | +| `order-items` | `$order-items` | ❌ | `{ $getField: "order-items" }` | +| `a.b` (literal dot) | `$a.b` | ❌ (ambiguous) | `{ $getField: { $literal: "a.b" } }` | +| `my field` | `$my field` | ❌ | `{ $getField: "my field" }` | + +### Proposed approaches + +**Option A — Make `referenceText` optional:** Return `undefined` for fields that can't use `$`-prefix syntax. The completion provider would omit the reference suggestion for those fields. + +**Option B — Use `$getField` for special names:** + +```typescript +referenceText: needsQuoting + ? `{ $getField: "${escaped}" }` + : `$${entry.path}`, +``` + +**Option C — Provide both forms:** Add a `referenceTextRaw` (always `$path`) and `referenceTextSafe` (uses `$getField` when needed). Let the completion provider choose based on context. + +**Recommendation:** Option B is pragmatic. Option C is more flexible if we later need to support both forms in different contexts (e.g., `$match` vs `$project`). + +--- + +## 3. `FieldEntry.path` dot-concatenation is ambiguous for literal dots + +**Severity:** Low (rare in practice) — fields with literal dots were prohibited before MongoDB 3.6 +**File:** `getKnownFields.ts` — path concatenation at `path: \`${path}.${childName}\``**When to fix:** When we encounter real-world schemas with literal dots, or during the next`FieldEntry` interface revision + +### Problem + +Paths are built by concatenating segments with `.` as separator. A root-level field named `"a.b"` produces `path: "a.b"`, which is indistinguishable from a nested field `{ a: { b: ... } }`. + +This ambiguity flows downstream to all consumers: `toTypeScriptDefinition`, `toFieldCompletionItems`, `generateDescriptions`, and any future completion provider. + +### Examples + +| Document shape | Resulting `path` | Ambiguous? | +| --------------------- | ---------------- | ----------------------------- | +| `{ a: { b: 1 } }` | `"a.b"` | — | +| `{ "a.b": 1 }` | `"a.b"` | ✅ Same as above | +| `{ x: { "y.z": 1 } }` | `"x.y.z"` | ✅ Looks like 3-level nesting | + +### Proposed fix + +Change `FieldEntry.path` from `string` to `string[]` (segment array): + +```typescript +// Before +interface FieldEntry { + path: string; // "address.city" + ... +} + +// After +interface FieldEntry { + path: string[]; // ["address", "city"] + ... +} +``` + +Each consumer then formats the path for its own context: + +- **TypeScript definitions:** Already use schema `properties` keys directly (no change needed there) +- **Completion items:** `entry.path.join('.')` for display, bracket notation for special segments +- **Aggregation references:** `$` + segments joined with `.`, or `$getField` chains for special segments + +### Impact + +This is a **breaking change** to the `FieldEntry` interface. Affected consumers: + +- `toFieldCompletionItems.ts` +- `toTypeScriptDefinition.ts` (indirect — uses schema, not FieldEntry paths) +- `generateDescriptions.ts` (uses schema, not FieldEntry paths) +- `collectionViewRouter.ts` (imports `FieldEntry` type) +- `ClusterSession.ts` (imports `FieldEntry` type) +- `generateMongoFindJsonSchema.ts` (imports `FieldEntry` type) +- `SchemaAnalyzer.ts` (returns `FieldEntry[]` via `getKnownFields`) + +**Recommendation:** Defer until the completion provider is built. The ambiguity only matters for fields with literal dots, which are uncommon. When fixing, do it as a single atomic change across all consumers. diff --git a/src/utils/json/data-api/autocomplete/getKnownFields.ts b/src/utils/json/data-api/autocomplete/getKnownFields.ts index 006c57f94..63a53fc99 100644 --- a/src/utils/json/data-api/autocomplete/getKnownFields.ts +++ b/src/utils/json/data-api/autocomplete/getKnownFields.ts @@ -82,6 +82,16 @@ export function getKnownFields(schema: JSONSchema): FieldEntry[] { const objectDocumentsInspected = (mostCommonTypeEntry['x-documentsInspected'] as number) ?? 0; for (const childName of Object.keys(mostCommonTypeEntry.properties)) { const childSchema = mostCommonTypeEntry.properties[childName] as JSONSchema; + // TODO: Dot-delimited path concatenation is ambiguous when a field name + // itself contains a literal dot. For example, a root-level field named + // "a.b" produces path "a.b", indistinguishable from a nested field + // { a: { b: ... } }. Fields with literal dots in their names were + // prohibited before MongoDB 3.6 and remain rare in practice. + // + // Future improvement: change `path` from `string` to `string[]` + // (segment array) to preserve the distinction between nesting and + // literal dots, pushing escaping/formatting decisions to consumers + // (TS definitions, completion items, aggregation references, etc.). queue.push({ path: `${path}.${childName}`, schemaNode: childSchema, diff --git a/src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts b/src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts index af68908a2..03d1a9a89 100644 --- a/src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts +++ b/src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts @@ -8,9 +8,17 @@ import { type FieldEntry } from './getKnownFields'; /** * Completion-ready data for a single field entry. + * + * Design intent: + * - `fieldName` is the human-readable, unescaped field path shown in the completion list. + * Users see clean names like "address.city" or "order-items" without quotes or escaping. + * - `insertText` is the escaped/quoted form that gets inserted when the user selects a + * completion item. For simple identifiers it matches `fieldName`; for names containing + * special characters (dots, spaces, `$`, etc.) it is wrapped in double quotes. + * - `referenceText` is the `$`-prefixed aggregation field reference (e.g., "$age"). */ export interface FieldCompletionData { - /** The full dot-notated field name, e.g., "address.city" */ + /** The full dot-notated field name, e.g., "address.city" — kept unescaped for display */ fieldName: string; /** Human-readable type display, e.g., "String", "Date", "ObjectId" */ displayType: string; @@ -18,14 +26,30 @@ export interface FieldCompletionData { bsonType: string; /** Whether the field was not present in every inspected document (statistical observation, not a constraint) */ isSparse: boolean; - /** Text to insert — escaped if field name contains dots or special chars */ + /** Text to insert when the user selects this completion — quoted/escaped if the field name contains special chars */ insertText: string; - /** Field reference for aggregation expressions, e.g., "$age", "$address.city" */ + /** + * Field reference for aggregation expressions, e.g., "$age", "$address.city". + * + * TODO: The simple `$field.path` syntax is invalid MQL for field names containing dots, + * spaces, or `$` characters. For such fields, the correct MQL syntax is + * `{ $getField: "fieldName" }`. This should be addressed when the aggregation + * completion provider is wired up — either by using `$getField` for special names + * or by making `referenceText` optional for fields that cannot use the `$` prefix syntax. + */ referenceText: string; } /** * Characters that require quoting in a field name for insert text. + * + * TODO: This pattern currently only catches dots, `$`, and whitespace. It misses other + * characters that are valid in MongoDB field names but problematic in query expressions: + * dashes (`-`), brackets (`[`, `]`), quotes (`"`, `'`), and backslashes (`\`). + * Additionally, the quoting logic (`"${path}"`) does not escape embedded double quotes + * or backslashes inside the field name. Both gaps should be addressed when the + * CompletionItemProvider is wired up — the fix is to (1) widen this to a "is valid + * unquoted identifier" check and (2) escape `"` → `\"` and `\` → `\\` in insertText. */ const SPECIAL_CHARS_PATTERN = /[.$\s]/; diff --git a/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.test.ts b/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.test.ts index 00a112536..256d59a27 100644 --- a/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.test.ts +++ b/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.test.ts @@ -206,4 +206,95 @@ describe('toTypeScriptDefinition', () => { 'interface MyAwesomeCollectionDocument', ); }); + + describe('special character field names', () => { + function makeSchemaWithField(fieldName: string): JSONSchema { + return { + 'x-documentsInspected': 100, + properties: { + [fieldName]: { + 'x-occurrence': 100, + anyOf: [ + { + type: 'string', + 'x-bsonType': 'string', + 'x-typeOccurrence': 100, + }, + ], + }, + }, + }; + } + + it('leaves valid identifiers unquoted', () => { + const result = toTypeScriptDefinition(makeSchemaWithField('age'), 'test'); + expect(result).toContain(' age: string;'); + }); + + it('leaves underscore-prefixed identifiers unquoted', () => { + const result = toTypeScriptDefinition(makeSchemaWithField('_id'), 'test'); + expect(result).toContain(' _id: string;'); + }); + + it('leaves dollar-prefixed identifiers unquoted', () => { + const result = toTypeScriptDefinition(makeSchemaWithField('$type'), 'test'); + expect(result).toContain(' $type: string;'); + }); + + it('quotes field names with dashes', () => { + const result = toTypeScriptDefinition(makeSchemaWithField('order-items'), 'test'); + expect(result).toContain(' "order-items": string;'); + }); + + it('quotes field names with dots', () => { + const result = toTypeScriptDefinition(makeSchemaWithField('a.b'), 'test'); + expect(result).toContain(' "a.b": string;'); + }); + + it('quotes field names with spaces', () => { + const result = toTypeScriptDefinition(makeSchemaWithField('my field'), 'test'); + expect(result).toContain(' "my field": string;'); + }); + + it('quotes field names with brackets', () => { + const result = toTypeScriptDefinition(makeSchemaWithField('items[0]'), 'test'); + expect(result).toContain(' "items[0]": string;'); + }); + + it('escapes embedded double quotes in field names', () => { + const result = toTypeScriptDefinition(makeSchemaWithField('say"hi"'), 'test'); + expect(result).toContain(' "say\\"hi\\"": string;'); + }); + + it('escapes backslashes in field names', () => { + const result = toTypeScriptDefinition(makeSchemaWithField('back\\slash'), 'test'); + expect(result).toContain(' "back\\\\slash": string;'); + }); + + it('quotes field names that start with a digit', () => { + const result = toTypeScriptDefinition(makeSchemaWithField('123abc'), 'test'); + expect(result).toContain(' "123abc": string;'); + }); + + it('preserves optionality with quoted field names', () => { + const schema: JSONSchema = { + 'x-documentsInspected': 100, + properties: { + 'order-items': { + 'x-occurrence': 50, + anyOf: [ + { + type: 'string', + 'x-bsonType': 'string', + 'x-typeOccurrence': 50, + }, + ], + }, + }, + }; + + const result = toTypeScriptDefinition(schema, 'test'); + expect(result).toContain(' "order-items"?: string;'); + }); + }); }); diff --git a/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.ts b/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.ts index 92bef8a9c..588eb6987 100644 --- a/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.ts +++ b/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.ts @@ -42,6 +42,33 @@ function bsonTypeToTS(bsonType: string): string { return bsonToTypeScriptMap[bsonType] ?? 'unknown'; } +/** + * Matches valid JavaScript/TypeScript identifiers. + * A valid identifier starts with a letter, underscore, or dollar sign, + * followed by zero or more letters, digits, underscores, or dollar signs. + */ +const JS_IDENTIFIER_PATTERN = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/; + +/** + * Returns a safe TypeScript property name for use in interface definitions. + * If the name is a valid JS identifier, it is returned as-is. + * Otherwise, it is wrapped in double quotes with internal quotes and backslashes escaped. + * + * Examples: + * - "age" → "age" (valid identifier, unchanged) + * - "order-items" → '"order-items"' (dash) + * - "a.b" → '"a.b"' (dot) + * - "my field" → '"my field"' (space) + * - 'say"hi"' → '"say\\"hi\\""' (embedded quotes escaped) + */ +function safePropertyName(name: string): string { + if (JS_IDENTIFIER_PATTERN.test(name)) { + return name; + } + const escaped = name.replace(/\\/g, '\\\\').replace(/"/g, '\\"'); + return `"${escaped}"`; +} + /** * Converts a collection name to PascalCase and appends "Document". * Examples: @@ -96,8 +123,9 @@ function renderProperties( const isOptional = isFieldOptional(propSchema, parentDocumentsInspected); const optionalMarker = isOptional ? '?' : ''; const tsType = resolveTypeString(propSchema, indentLevel); + const safeName = safePropertyName(propName); - lines.push(`${indent}${propName}${optionalMarker}: ${tsType};`); + lines.push(`${indent}${safeName}${optionalMarker}: ${tsType};`); } } From 3ca695103ca17a451de95719d4de6d331c5f952b Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Feb 2026 11:35:57 +0100 Subject: [PATCH 013/128] refactor: extract schema-analyzer into standalone npm workspace package Move SchemaAnalyzer, JSONSchema types, BSONTypes, ValueFormatters, and getKnownFields into packages/schema-analyzer as @vscode-documentdb/schema-analyzer. - Set up npm workspaces (packages/*) and TS project references - Update all extension-side imports to use the new package - Configure Jest multi-project for both extension and package tests - Remove @vscode/l10n dependency from core (replaced with plain Error) - Fix strict-mode type issues (localeCompare bug, index signatures) - Update .gitignore to include root packages/ directory - Add packages/ to prettier glob --- .gitignore | 3 ++ jest.config.js | 16 +++++++--- l10n/bundle.l10n.json | 1 - package-lock.json | 19 ++++++++++++ package.json | 6 +++- packages/schema-analyzer/jest.config.js | 8 +++++ packages/schema-analyzer/package.json | 27 ++++++++++++++++ .../schema-analyzer/src}/BSONTypes.ts | 0 .../schema-analyzer/src}/JSONSchema.ts | 0 .../schema-analyzer/src}/SchemaAnalyzer.ts | 31 +++++++++---------- .../schema-analyzer/src}/ValueFormatters.ts | 0 .../schema-analyzer/src}/getKnownFields.ts | 2 +- packages/schema-analyzer/src/index.ts | 10 ++++++ .../test}/SchemaAnalyzer.arrayStats.test.ts | 14 ++++----- .../test}/SchemaAnalyzer.test.ts | 4 +-- .../test}/SchemaAnalyzer.versioning.test.ts | 4 +-- .../test}/mongoTestDocuments.ts | 0 packages/schema-analyzer/tsconfig.json | 20 ++++++++++++ packages/schema-analyzer/tsconfig.tsbuildinfo | 1 + src/documentdb/ClusterSession.ts | 9 ++++-- .../autocomplete/generateDescriptions.test.ts | 2 +- .../autocomplete/generateDescriptions.ts | 3 +- .../generateMongoFindJsonSchema.ts | 2 +- .../autocomplete/getKnownFields.test.ts | 3 +- .../toFieldCompletionItems.test.ts | 2 +- .../autocomplete/toFieldCompletionItems.ts | 3 +- .../toTypeScriptDefinition.test.ts | 2 +- .../autocomplete/toTypeScriptDefinition.ts | 3 +- src/utils/slickgrid/mongo/toSlickGridTable.ts | 3 +- src/utils/slickgrid/mongo/toSlickGridTree.ts | 3 +- .../collectionView/collectionViewRouter.ts | 2 +- tsconfig.json | 3 +- 32 files changed, 149 insertions(+), 57 deletions(-) create mode 100644 packages/schema-analyzer/jest.config.js create mode 100644 packages/schema-analyzer/package.json rename {src/utils/json/data-api => packages/schema-analyzer/src}/BSONTypes.ts (100%) rename {src/utils/json => packages/schema-analyzer/src}/JSONSchema.ts (100%) rename {src/utils/json/data-api => packages/schema-analyzer/src}/SchemaAnalyzer.ts (96%) rename {src/utils/json/data-api => packages/schema-analyzer/src}/ValueFormatters.ts (100%) rename {src/utils/json/data-api/autocomplete => packages/schema-analyzer/src}/getKnownFields.ts (99%) create mode 100644 packages/schema-analyzer/src/index.ts rename {src/utils/json/data-api => packages/schema-analyzer/test}/SchemaAnalyzer.arrayStats.test.ts (97%) rename {src/utils/json/data-api => packages/schema-analyzer/test}/SchemaAnalyzer.test.ts (99%) rename {src/utils/json/data-api => packages/schema-analyzer/test}/SchemaAnalyzer.versioning.test.ts (99%) rename {src/utils/json/data-api => packages/schema-analyzer/test}/mongoTestDocuments.ts (100%) create mode 100644 packages/schema-analyzer/tsconfig.json create mode 100644 packages/schema-analyzer/tsconfig.tsbuildinfo diff --git a/.gitignore b/.gitignore index ea5798951..a234ba0aa 100644 --- a/.gitignore +++ b/.gitignore @@ -160,6 +160,9 @@ PublishScripts/ **/packages/* # except build/, which is used as an MSBuild target. !**/packages/build/ +# Include our monorepo packages at the root +!/packages/ +!/packages/** # Uncomment if necessary however generally it will be regenerated when needed #!**/packages/repositories.config # NuGet v3's project.json files produces more ignoreable files diff --git a/jest.config.js b/jest.config.js index 7ad26361a..6db24cd52 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,11 +1,17 @@ /** @type {import('ts-jest').JestConfigWithTsJest} **/ module.exports = { - testEnvironment: 'node', - testMatch: ['/src/**/*.test.ts'], - transform: { - '^.+.tsx?$': ['ts-jest', {}], - }, // Limit workers to avoid OOM kills on machines with many cores. // Each ts-jest worker loads the TypeScript compiler and consumes ~500MB+. maxWorkers: '50%', + projects: [ + { + displayName: 'extension', + testEnvironment: 'node', + testMatch: ['/src/**/*.test.ts'], + transform: { + '^.+\\.tsx?$': ['ts-jest', {}], + }, + }, + '/packages/schema-analyzer', + ], }; diff --git a/l10n/bundle.l10n.json b/l10n/bundle.l10n.json index bd7aca008..ef1cd63d9 100644 --- a/l10n/bundle.l10n.json +++ b/l10n/bundle.l10n.json @@ -721,7 +721,6 @@ "No matching resources found.": "No matching resources found.", "No node selected.": "No node selected.", "No parent folder selected.": "No parent folder selected.", - "No properties found in the schema at path \"{0}\"": "No properties found in the schema at path \"{0}\"", "No public connectivity": "No public connectivity", "No result returned from the MongoDB shell.": "No result returned from the MongoDB shell.", "No results found": "No results found", diff --git a/package-lock.json b/package-lock.json index 68ba135c7..2a0a6f451 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,9 @@ "name": "vscode-documentdb", "version": "0.7.0", "license": "SEE LICENSE IN LICENSE.md", + "workspaces": [ + "packages/*" + ], "dependencies": { "@azure/arm-compute": "^22.4.0", "@azure/arm-cosmosdb": "~16.4.0", @@ -26,6 +29,7 @@ "@mongodb-js/explain-plan-helper": "1.4.24", "@trpc/client": "~11.10.0", "@trpc/server": "~11.10.0", + "@vscode-documentdb/schema-analyzer": "*", "@vscode/l10n": "~0.0.18", "antlr4ts": "^0.5.0-alpha.4", "bson": "~7.0.0", @@ -7307,6 +7311,10 @@ "win32" ] }, + "node_modules/@vscode-documentdb/schema-analyzer": { + "resolved": "packages/schema-analyzer", + "link": true + }, "node_modules/@vscode/extension-telemetry": { "version": "0.9.9", "resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.9.9.tgz", @@ -22209,6 +22217,17 @@ "type": "github", "url": "https://github.com/sponsors/wooorm" } + }, + "packages/schema-analyzer": { + "name": "@vscode-documentdb/schema-analyzer", + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "denque": "~2.1.0" + }, + "peerDependencies": { + "mongodb": ">=6.0.0" + } } } } diff --git a/package.json b/package.json index 9a87a3fe5..887ba0ecd 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,9 @@ "type": "git", "url": "https://github.com/microsoft/vscode-documentdb" }, + "workspaces": [ + "packages/*" + ], "main": "./main", "l10n": "./l10n", "activationEvents": [ @@ -67,7 +70,7 @@ "lint": "eslint --quiet .", "lint-fix": "eslint . --fix", "prettier": "prettier -c \"(src|test|l10n|grammar|docs)/**/*.@(js|ts|jsx|tsx|json)\" \"./*.@(js|ts|jsx|tsx|json)\"", - "prettier-fix": "prettier -w \"(src|test|l10n|grammar|docs)/**/*.@(js|ts|jsx|tsx|json)\" \"./*.@(js|ts|jsx|tsx|json)\"", + "prettier-fix": "prettier -w \"(src|test|l10n|grammar|docs|packages)/**/*.@(js|ts|jsx|tsx|json)\" \"./*.@(js|ts|jsx|tsx|json)\"", "pretest": "npm run build", "test": "vscode-test", "jesttest": "jest", @@ -165,6 +168,7 @@ "@trpc/client": "~11.10.0", "@trpc/server": "~11.10.0", "@vscode/l10n": "~0.0.18", + "@vscode-documentdb/schema-analyzer": "*", "antlr4ts": "^0.5.0-alpha.4", "bson": "~7.0.0", "denque": "~2.1.0", diff --git a/packages/schema-analyzer/jest.config.js b/packages/schema-analyzer/jest.config.js new file mode 100644 index 000000000..388d1e1d1 --- /dev/null +++ b/packages/schema-analyzer/jest.config.js @@ -0,0 +1,8 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} **/ +module.exports = { + testEnvironment: 'node', + testMatch: ['/test/**/*.test.ts'], + transform: { + '^.+\\.tsx?$': ['ts-jest', {}], + }, +}; diff --git a/packages/schema-analyzer/package.json b/packages/schema-analyzer/package.json new file mode 100644 index 000000000..f5b10840b --- /dev/null +++ b/packages/schema-analyzer/package.json @@ -0,0 +1,27 @@ +{ + "name": "@vscode-documentdb/schema-analyzer", + "version": "0.1.0", + "description": "Incremental JSON Schema analyzer for MongoDB/DocumentDB documents with statistical extensions", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist" + ], + "scripts": { + "build": "tsc -p .", + "clean": "rimraf dist", + "test": "jest --config jest.config.js" + }, + "repository": { + "type": "git", + "url": "https://github.com/microsoft/vscode-documentdb", + "directory": "packages/schema-analyzer" + }, + "license": "MIT", + "peerDependencies": { + "mongodb": ">=6.0.0" + }, + "dependencies": { + "denque": "~2.1.0" + } +} diff --git a/src/utils/json/data-api/BSONTypes.ts b/packages/schema-analyzer/src/BSONTypes.ts similarity index 100% rename from src/utils/json/data-api/BSONTypes.ts rename to packages/schema-analyzer/src/BSONTypes.ts diff --git a/src/utils/json/JSONSchema.ts b/packages/schema-analyzer/src/JSONSchema.ts similarity index 100% rename from src/utils/json/JSONSchema.ts rename to packages/schema-analyzer/src/JSONSchema.ts diff --git a/src/utils/json/data-api/SchemaAnalyzer.ts b/packages/schema-analyzer/src/SchemaAnalyzer.ts similarity index 96% rename from src/utils/json/data-api/SchemaAnalyzer.ts rename to packages/schema-analyzer/src/SchemaAnalyzer.ts index 93b73a36a..b26f6fa76 100644 --- a/src/utils/json/data-api/SchemaAnalyzer.ts +++ b/packages/schema-analyzer/src/SchemaAnalyzer.ts @@ -3,13 +3,12 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as l10n from '@vscode/l10n'; import { assert } from 'console'; import Denque from 'denque'; import { type Document, type WithId } from 'mongodb'; -import { type JSONSchema } from '../JSONSchema'; import { BSONTypes } from './BSONTypes'; -import { type FieldEntry, getKnownFields as getKnownFieldsFromSchema } from './autocomplete/getKnownFields'; +import { type JSONSchema, type JSONSchemaRef } from './JSONSchema'; +import { type FieldEntry, getKnownFields as getKnownFieldsFromSchema } from './getKnownFields'; /** * Incremental schema analyzer for documents from the MongoDB API / DocumentDB API. @@ -369,11 +368,12 @@ function findTypeEntry(anyOfArray: JSONSchema[], bsonType: BSONTypes): JSONSchem * Helper function to update min and max stats */ function updateMinMaxStats(schema: JSONSchema, minKey: string, maxKey: string, value: number): void { - if (schema[minKey] === undefined || value < schema[minKey]) { - schema[minKey] = value; + const record = schema as Record; + if (record[minKey] === undefined || value < (record[minKey] as number)) { + record[minKey] = value; } - if (schema[maxKey] === undefined || value > schema[maxKey]) { - schema[maxKey] = value; + if (record[maxKey] === undefined || value > (record[maxKey] as number)) { + record[maxKey] = value; } } @@ -534,17 +534,12 @@ function aggregateStatsForValue(value: unknown, mongoType: BSONTypes, propertyTy } } -function getSchemaAtPath(schema: JSONSchema, path: string[]): JSONSchema { - let currentNode = schema; +function getSchemaAtPath(schema: JSONSchema, path: string[]): JSONSchema | undefined { + let currentNode: JSONSchema | undefined = schema; for (let i = 0; i < path.length; i++) { const key = path[i]; - // If the current node is an array, we should move to its `items` - // if (currentNode.type === 'array' && currentNode.items) { - // currentNode = currentNode.items; - // } - // Move to the next property in the schema if (currentNode && currentNode.properties && currentNode.properties[key]) { const nextNode: JSONSchema = currentNode.properties[key] as JSONSchema; @@ -553,13 +548,15 @@ function getSchemaAtPath(schema: JSONSchema, path: string[]): JSONSchema { * We're looking at the "Object"-one, because these have the properties we're interested in. */ if (nextNode.anyOf && nextNode.anyOf.length > 0) { - currentNode = nextNode.anyOf.find((entry: JSONSchema) => entry.type === 'object') as JSONSchema; + currentNode = nextNode.anyOf.find( + (entry: JSONSchemaRef): entry is JSONSchema => typeof entry === 'object' && entry.type === 'object', + ); } else { // we can't continue, as we're missing the next node, we abort at the last node we managed to extract return currentNode; } } else { - throw new Error(l10n.t('No properties found in the schema at path "{0}"', path.slice(0, i + 1).join('/'))); + throw new Error(`No properties found in the schema at path "${path.slice(0, i + 1).join('/')}"`); } } @@ -570,7 +567,7 @@ export function getPropertyNamesAtLevel(jsonSchema: JSONSchema, path: string[]): const headers = new Set(); // Explore the schema and apply the callback to collect headers at the specified path - const selectedSchema: JSONSchema = getSchemaAtPath(jsonSchema, path); + const selectedSchema = getSchemaAtPath(jsonSchema, path); if (selectedSchema && selectedSchema.properties) { Object.keys(selectedSchema.properties).forEach((key) => { diff --git a/src/utils/json/data-api/ValueFormatters.ts b/packages/schema-analyzer/src/ValueFormatters.ts similarity index 100% rename from src/utils/json/data-api/ValueFormatters.ts rename to packages/schema-analyzer/src/ValueFormatters.ts diff --git a/src/utils/json/data-api/autocomplete/getKnownFields.ts b/packages/schema-analyzer/src/getKnownFields.ts similarity index 99% rename from src/utils/json/data-api/autocomplete/getKnownFields.ts rename to packages/schema-analyzer/src/getKnownFields.ts index 63a53fc99..d3f12ee89 100644 --- a/src/utils/json/data-api/autocomplete/getKnownFields.ts +++ b/packages/schema-analyzer/src/getKnownFields.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import Denque from 'denque'; -import { type JSONSchema } from '../../JSONSchema'; +import { type JSONSchema } from './JSONSchema'; export interface FieldEntry { /** Dot-notated path (e.g., "user.profile.name") */ diff --git a/packages/schema-analyzer/src/index.ts b/packages/schema-analyzer/src/index.ts new file mode 100644 index 000000000..871fd61f8 --- /dev/null +++ b/packages/schema-analyzer/src/index.ts @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export { BSONTypes } from './BSONTypes'; +export { getKnownFields, type FieldEntry } from './getKnownFields'; +export { type JSONSchema, type JSONSchemaMap, type JSONSchemaRef } from './JSONSchema'; +export { SchemaAnalyzer, buildFullPaths, getPropertyNamesAtLevel } from './SchemaAnalyzer'; +export { valueToDisplayString } from './ValueFormatters'; diff --git a/src/utils/json/data-api/SchemaAnalyzer.arrayStats.test.ts b/packages/schema-analyzer/test/SchemaAnalyzer.arrayStats.test.ts similarity index 97% rename from src/utils/json/data-api/SchemaAnalyzer.arrayStats.test.ts rename to packages/schema-analyzer/test/SchemaAnalyzer.arrayStats.test.ts index 00f53d98f..2669d5214 100644 --- a/src/utils/json/data-api/SchemaAnalyzer.arrayStats.test.ts +++ b/packages/schema-analyzer/test/SchemaAnalyzer.arrayStats.test.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { ObjectId, type Document, type WithId } from 'mongodb'; -import { type JSONSchema } from '../JSONSchema'; -import { SchemaAnalyzer } from './SchemaAnalyzer'; +import { type JSONSchema } from '../src/JSONSchema'; +import { SchemaAnalyzer } from '../src/SchemaAnalyzer'; /** * This test file investigates the array element occurrence/stats problem. @@ -158,19 +158,19 @@ describe('Array element occurrence analysis', () => { (e) => (e as JSONSchema)['x-bsonType'] === 'object', ) as JSONSchema; - const props = objEntry.properties as JSONSchema; + const props = objEntry.properties as Record; // "name" appeared in all 3 object elements - expect((props['name'] as JSONSchema)['x-occurrence']).toBe(3); + expect(props['name']['x-occurrence']).toBe(3); // "price" appeared in 2 of 3 object elements - expect((props['price'] as JSONSchema)['x-occurrence']).toBe(2); + expect(props['price']['x-occurrence']).toBe(2); // "discount" appeared in 1 of 3 object elements - expect((props['discount'] as JSONSchema)['x-occurrence']).toBe(1); + expect(props['discount']['x-occurrence']).toBe(1); // "weight" appeared in 1 of 3 object elements - expect((props['weight'] as JSONSchema)['x-occurrence']).toBe(1); + expect(props['weight']['x-occurrence']).toBe(1); // Total object elements = 3 (2 from doc1 + 1 from doc2) expect(objEntry['x-typeOccurrence']).toBe(3); diff --git a/src/utils/json/data-api/SchemaAnalyzer.test.ts b/packages/schema-analyzer/test/SchemaAnalyzer.test.ts similarity index 99% rename from src/utils/json/data-api/SchemaAnalyzer.test.ts rename to packages/schema-analyzer/test/SchemaAnalyzer.test.ts index cb2b362c7..f23a97bdf 100644 --- a/src/utils/json/data-api/SchemaAnalyzer.test.ts +++ b/packages/schema-analyzer/test/SchemaAnalyzer.test.ts @@ -3,8 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { type JSONSchema, type JSONSchemaMap, type JSONSchemaRef } from '../JSONSchema'; -import { getPropertyNamesAtLevel, SchemaAnalyzer } from './SchemaAnalyzer'; +import { type JSONSchema, type JSONSchemaMap, type JSONSchemaRef } from '../src/JSONSchema'; +import { getPropertyNamesAtLevel, SchemaAnalyzer } from '../src/SchemaAnalyzer'; import { arraysWithDifferentDataTypes, complexDocument, diff --git a/src/utils/json/data-api/SchemaAnalyzer.versioning.test.ts b/packages/schema-analyzer/test/SchemaAnalyzer.versioning.test.ts similarity index 99% rename from src/utils/json/data-api/SchemaAnalyzer.versioning.test.ts rename to packages/schema-analyzer/test/SchemaAnalyzer.versioning.test.ts index 91a6fbddc..38ef144a6 100644 --- a/src/utils/json/data-api/SchemaAnalyzer.versioning.test.ts +++ b/packages/schema-analyzer/test/SchemaAnalyzer.versioning.test.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { ObjectId, type Document, type WithId } from 'mongodb'; -import { type JSONSchema } from '../JSONSchema'; -import { SchemaAnalyzer } from './SchemaAnalyzer'; +import { type JSONSchema } from '../src/JSONSchema'; +import { SchemaAnalyzer } from '../src/SchemaAnalyzer'; // ------------------------------------------------------------------ // Test fixtures diff --git a/src/utils/json/data-api/mongoTestDocuments.ts b/packages/schema-analyzer/test/mongoTestDocuments.ts similarity index 100% rename from src/utils/json/data-api/mongoTestDocuments.ts rename to packages/schema-analyzer/test/mongoTestDocuments.ts diff --git a/packages/schema-analyzer/tsconfig.json b/packages/schema-analyzer/tsconfig.json new file mode 100644 index 000000000..8688f97ff --- /dev/null +++ b/packages/schema-analyzer/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "composite": true, + "declaration": true, + "declarationMap": true, + "module": "commonjs", + "target": "ES2023", + "lib": ["ES2023"], + "rootDir": "./src", + "outDir": "./dist", + "strict": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "sourceMap": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/schema-analyzer/tsconfig.tsbuildinfo b/packages/schema-analyzer/tsconfig.tsbuildinfo new file mode 100644 index 000000000..bfaffb0b6 --- /dev/null +++ b/packages/schema-analyzer/tsconfig.tsbuildinfo @@ -0,0 +1 @@ +{"fileNames":["../../node_modules/typescript/lib/lib.es5.d.ts","../../node_modules/typescript/lib/lib.es2015.d.ts","../../node_modules/typescript/lib/lib.es2016.d.ts","../../node_modules/typescript/lib/lib.es2017.d.ts","../../node_modules/typescript/lib/lib.es2018.d.ts","../../node_modules/typescript/lib/lib.es2019.d.ts","../../node_modules/typescript/lib/lib.es2020.d.ts","../../node_modules/typescript/lib/lib.es2021.d.ts","../../node_modules/typescript/lib/lib.es2022.d.ts","../../node_modules/typescript/lib/lib.es2023.d.ts","../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../node_modules/typescript/lib/lib.es2016.intl.d.ts","../../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../node_modules/typescript/lib/lib.es2017.date.d.ts","../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../node_modules/typescript/lib/lib.es2021.promise.d.ts","../../node_modules/typescript/lib/lib.es2021.string.d.ts","../../node_modules/typescript/lib/lib.es2021.weakref.d.ts","../../node_modules/typescript/lib/lib.es2021.intl.d.ts","../../node_modules/typescript/lib/lib.es2022.array.d.ts","../../node_modules/typescript/lib/lib.es2022.error.d.ts","../../node_modules/typescript/lib/lib.es2022.intl.d.ts","../../node_modules/typescript/lib/lib.es2022.object.d.ts","../../node_modules/typescript/lib/lib.es2022.string.d.ts","../../node_modules/typescript/lib/lib.es2022.regexp.d.ts","../../node_modules/typescript/lib/lib.es2023.array.d.ts","../../node_modules/typescript/lib/lib.es2023.collection.d.ts","../../node_modules/typescript/lib/lib.es2023.intl.d.ts","../../node_modules/typescript/lib/lib.esnext.disposable.d.ts","../../node_modules/typescript/lib/lib.decorators.d.ts","../../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../../node_modules/bson/bson.d.ts","../../node_modules/mongodb/mongodb.d.ts","./src/BSONTypes.ts","./src/JSONSchema.ts","../../node_modules/denque/index.d.ts","./src/getKnownFields.ts","./src/SchemaAnalyzer.ts","./src/ValueFormatters.ts","./src/index.ts","../../node_modules/@babel/types/lib/index.d.ts","../../node_modules/@types/babel__generator/index.d.ts","../../node_modules/@babel/parser/typings/babel-parser.d.ts","../../node_modules/@types/babel__template/index.d.ts","../../node_modules/@types/babel__traverse/index.d.ts","../../node_modules/@types/babel__core/index.d.ts","../../node_modules/@types/node/compatibility/disposable.d.ts","../../node_modules/@types/node/compatibility/indexable.d.ts","../../node_modules/@types/node/compatibility/iterators.d.ts","../../node_modules/@types/node/compatibility/index.d.ts","../../node_modules/@types/node/globals.typedarray.d.ts","../../node_modules/@types/node/buffer.buffer.d.ts","../../node_modules/@types/node/globals.d.ts","../../node_modules/@types/node/web-globals/abortcontroller.d.ts","../../node_modules/@types/node/web-globals/domexception.d.ts","../../node_modules/@types/node/web-globals/events.d.ts","../../node_modules/buffer/index.d.ts","../../node_modules/undici-types/header.d.ts","../../node_modules/undici-types/readable.d.ts","../../node_modules/undici-types/file.d.ts","../../node_modules/undici-types/fetch.d.ts","../../node_modules/undici-types/formdata.d.ts","../../node_modules/undici-types/connector.d.ts","../../node_modules/undici-types/client.d.ts","../../node_modules/undici-types/errors.d.ts","../../node_modules/undici-types/dispatcher.d.ts","../../node_modules/undici-types/global-dispatcher.d.ts","../../node_modules/undici-types/global-origin.d.ts","../../node_modules/undici-types/pool-stats.d.ts","../../node_modules/undici-types/pool.d.ts","../../node_modules/undici-types/handlers.d.ts","../../node_modules/undici-types/balanced-pool.d.ts","../../node_modules/undici-types/agent.d.ts","../../node_modules/undici-types/mock-interceptor.d.ts","../../node_modules/undici-types/mock-agent.d.ts","../../node_modules/undici-types/mock-client.d.ts","../../node_modules/undici-types/mock-pool.d.ts","../../node_modules/undici-types/mock-errors.d.ts","../../node_modules/undici-types/proxy-agent.d.ts","../../node_modules/undici-types/env-http-proxy-agent.d.ts","../../node_modules/undici-types/retry-handler.d.ts","../../node_modules/undici-types/retry-agent.d.ts","../../node_modules/undici-types/api.d.ts","../../node_modules/undici-types/interceptors.d.ts","../../node_modules/undici-types/util.d.ts","../../node_modules/undici-types/cookies.d.ts","../../node_modules/undici-types/patch.d.ts","../../node_modules/undici-types/websocket.d.ts","../../node_modules/undici-types/eventsource.d.ts","../../node_modules/undici-types/filereader.d.ts","../../node_modules/undici-types/diagnostics-channel.d.ts","../../node_modules/undici-types/content-type.d.ts","../../node_modules/undici-types/cache.d.ts","../../node_modules/undici-types/index.d.ts","../../node_modules/@types/node/web-globals/fetch.d.ts","../../node_modules/@types/node/web-globals/navigator.d.ts","../../node_modules/@types/node/web-globals/storage.d.ts","../../node_modules/@types/node/assert.d.ts","../../node_modules/@types/node/assert/strict.d.ts","../../node_modules/@types/node/async_hooks.d.ts","../../node_modules/@types/node/buffer.d.ts","../../node_modules/@types/node/child_process.d.ts","../../node_modules/@types/node/cluster.d.ts","../../node_modules/@types/node/console.d.ts","../../node_modules/@types/node/constants.d.ts","../../node_modules/@types/node/crypto.d.ts","../../node_modules/@types/node/dgram.d.ts","../../node_modules/@types/node/diagnostics_channel.d.ts","../../node_modules/@types/node/dns.d.ts","../../node_modules/@types/node/dns/promises.d.ts","../../node_modules/@types/node/domain.d.ts","../../node_modules/@types/node/events.d.ts","../../node_modules/@types/node/fs.d.ts","../../node_modules/@types/node/fs/promises.d.ts","../../node_modules/@types/node/http.d.ts","../../node_modules/@types/node/http2.d.ts","../../node_modules/@types/node/https.d.ts","../../node_modules/@types/node/inspector.generated.d.ts","../../node_modules/@types/node/module.d.ts","../../node_modules/@types/node/net.d.ts","../../node_modules/@types/node/os.d.ts","../../node_modules/@types/node/path.d.ts","../../node_modules/@types/node/perf_hooks.d.ts","../../node_modules/@types/node/process.d.ts","../../node_modules/@types/node/punycode.d.ts","../../node_modules/@types/node/querystring.d.ts","../../node_modules/@types/node/readline.d.ts","../../node_modules/@types/node/readline/promises.d.ts","../../node_modules/@types/node/repl.d.ts","../../node_modules/@types/node/sea.d.ts","../../node_modules/@types/node/sqlite.d.ts","../../node_modules/@types/node/stream.d.ts","../../node_modules/@types/node/stream/promises.d.ts","../../node_modules/@types/node/stream/consumers.d.ts","../../node_modules/@types/node/stream/web.d.ts","../../node_modules/@types/node/string_decoder.d.ts","../../node_modules/@types/node/test.d.ts","../../node_modules/@types/node/timers.d.ts","../../node_modules/@types/node/timers/promises.d.ts","../../node_modules/@types/node/tls.d.ts","../../node_modules/@types/node/trace_events.d.ts","../../node_modules/@types/node/tty.d.ts","../../node_modules/@types/node/url.d.ts","../../node_modules/@types/node/util.d.ts","../../node_modules/@types/node/v8.d.ts","../../node_modules/@types/node/vm.d.ts","../../node_modules/@types/node/wasi.d.ts","../../node_modules/@types/node/worker_threads.d.ts","../../node_modules/@types/node/zlib.d.ts","../../node_modules/@types/node/index.d.ts","../../node_modules/@types/connect/index.d.ts","../../node_modules/@types/body-parser/index.d.ts","../../node_modules/@types/bonjour/index.d.ts","../../node_modules/@types/send/index.d.ts","../../node_modules/@types/qs/index.d.ts","../../node_modules/@types/range-parser/index.d.ts","../../node_modules/@types/express-serve-static-core/index.d.ts","../../node_modules/@types/connect-history-api-fallback/index.d.ts","../../node_modules/@types/ms/index.d.ts","../../node_modules/@types/debug/index.d.ts","../../node_modules/@types/documentdb/index.d.ts","../../node_modules/@types/estree/index.d.ts","../../node_modules/@types/json-schema/index.d.ts","../../node_modules/@types/eslint/use-at-your-own-risk.d.ts","../../node_modules/@types/eslint/index.d.ts","../../node_modules/@eslint/core/dist/esm/types.d.ts","../../node_modules/eslint/lib/types/use-at-your-own-risk.d.ts","../../node_modules/eslint/lib/types/index.d.ts","../../node_modules/@types/eslint-scope/index.d.ts","../../node_modules/@types/estree-jsx/index.d.ts","../../node_modules/@types/http-errors/index.d.ts","../../node_modules/@types/mime/index.d.ts","../../node_modules/@types/serve-static/node_modules/@types/send/index.d.ts","../../node_modules/@types/serve-static/index.d.ts","../../node_modules/@types/express/index.d.ts","../../node_modules/@types/unist/index.d.ts","../../node_modules/@types/hast/index.d.ts","../../node_modules/@types/http-cache-semantics/index.d.ts","../../node_modules/@types/http-proxy/index.d.ts","../../node_modules/@types/istanbul-lib-coverage/index.d.ts","../../node_modules/@types/istanbul-lib-report/index.d.ts","../../node_modules/@types/istanbul-reports/index.d.ts","../../node_modules/@jest/expect-utils/build/index.d.ts","../../node_modules/chalk/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/symbols/symbols.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/symbols/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/any/any.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/any/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/mapped/mapped-key.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/mapped/mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/async-iterator/async-iterator.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/async-iterator/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/readonly/readonly.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/readonly/readonly-from-mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/readonly/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/readonly-optional/readonly-optional.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/readonly-optional/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/constructor/constructor.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/constructor/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/literal/literal.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/literal/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/enum/enum.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/enum/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/function/function.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/function/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/computed/computed.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/computed/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/never/never.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/never/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/intersect/intersect-type.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/intersect/intersect-evaluated.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/intersect/intersect.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/intersect/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/union/union-type.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/union/union-evaluated.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/union/union.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/union/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/recursive/recursive.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/recursive/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/unsafe/unsafe.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/unsafe/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/ref/ref.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/ref/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/tuple/tuple.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/tuple/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/error/error.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/error/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/string/string.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/string/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/boolean/boolean.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/boolean/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/number/number.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/number/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/integer/integer.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/integer/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/bigint/bigint.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/bigint/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/template-literal/parse.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/template-literal/finite.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/template-literal/generate.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/template-literal/syntax.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/template-literal/pattern.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/template-literal/template-literal.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/template-literal/union.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/template-literal/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/indexed/indexed-property-keys.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/indexed/indexed-from-mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/indexed/indexed.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/indexed/indexed-from-mapped-key.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/indexed/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/iterator/iterator.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/iterator/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/promise/promise.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/promise/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/sets/set.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/sets/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/mapped/mapped.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/mapped/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/optional/optional.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/optional/optional-from-mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/optional/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/awaited/awaited.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/awaited/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/keyof/keyof-property-keys.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/keyof/keyof.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/keyof/keyof-from-mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/keyof/keyof-property-entries.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/keyof/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/omit/omit-from-mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/omit/omit.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/omit/omit-from-mapped-key.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/omit/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/pick/pick-from-mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/pick/pick.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/pick/pick-from-mapped-key.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/pick/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/null/null.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/null/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/symbol/symbol.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/symbol/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/undefined/undefined.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/undefined/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/partial/partial.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/partial/partial-from-mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/partial/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/regexp/regexp.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/regexp/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/record/record.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/record/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/required/required.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/required/required-from-mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/required/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/transform/transform.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/transform/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/module/compute.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/module/infer.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/module/module.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/module/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/not/not.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/not/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/static/static.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/static/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/object/object.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/object/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/helpers/helpers.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/helpers/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/array/array.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/array/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/date/date.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/date/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/uint8array/uint8array.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/uint8array/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/unknown/unknown.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/unknown/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/void/void.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/void/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/schema/schema.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/schema/anyschema.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/schema/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/clone/type.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/clone/value.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/clone/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/create/type.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/create/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/argument/argument.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/argument/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/guard/kind.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/guard/type.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/guard/value.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/guard/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/patterns/patterns.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/patterns/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/registry/format.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/registry/type.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/registry/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/composite/composite.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/composite/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/const/const.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/const/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/constructor-parameters/constructor-parameters.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/constructor-parameters/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/exclude/exclude-from-template-literal.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/exclude/exclude.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/exclude/exclude-from-mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/exclude/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/extends/extends-check.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/extends/extends-from-mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/extends/extends.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/extends/extends-from-mapped-key.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/extends/extends-undefined.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/extends/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/extract/extract-from-template-literal.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/extract/extract.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/extract/extract-from-mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/extract/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/instance-type/instance-type.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/instance-type/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/instantiate/instantiate.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/instantiate/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/intrinsic/intrinsic-from-mapped-key.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/intrinsic/intrinsic.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/intrinsic/capitalize.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/intrinsic/lowercase.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/intrinsic/uncapitalize.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/intrinsic/uppercase.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/intrinsic/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/parameters/parameters.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/parameters/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/rest/rest.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/rest/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/return-type/return-type.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/return-type/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/type/json.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/type/javascript.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/type/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/index.d.ts","../../node_modules/@jest/schemas/build/index.d.ts","../../node_modules/pretty-format/build/index.d.ts","../../node_modules/jest-diff/build/index.d.ts","../../node_modules/jest-matcher-utils/build/index.d.ts","../../node_modules/jest-mock/build/index.d.ts","../../node_modules/expect/build/index.d.ts","../../node_modules/@types/jest/index.d.ts","../../node_modules/@types/json5/index.d.ts","../../node_modules/@types/mdast/index.d.ts","../../node_modules/@types/mocha/index.d.ts","../../node_modules/@types/node-forge/index.d.ts","../../node_modules/@types/normalize-package-data/index.d.ts","../../node_modules/@types/react/global.d.ts","../../node_modules/csstype/index.d.ts","../../node_modules/@types/react/index.d.ts","../../node_modules/@types/react-dom/index.d.ts","../../node_modules/@types/retry/index.d.ts","../../node_modules/@types/sarif/index.d.ts","../../node_modules/@types/semver/functions/inc.d.ts","../../node_modules/@types/semver/classes/semver.d.ts","../../node_modules/@types/semver/functions/parse.d.ts","../../node_modules/@types/semver/functions/valid.d.ts","../../node_modules/@types/semver/functions/clean.d.ts","../../node_modules/@types/semver/functions/diff.d.ts","../../node_modules/@types/semver/functions/major.d.ts","../../node_modules/@types/semver/functions/minor.d.ts","../../node_modules/@types/semver/functions/patch.d.ts","../../node_modules/@types/semver/functions/prerelease.d.ts","../../node_modules/@types/semver/functions/compare.d.ts","../../node_modules/@types/semver/functions/rcompare.d.ts","../../node_modules/@types/semver/functions/compare-loose.d.ts","../../node_modules/@types/semver/functions/compare-build.d.ts","../../node_modules/@types/semver/functions/sort.d.ts","../../node_modules/@types/semver/functions/rsort.d.ts","../../node_modules/@types/semver/functions/gt.d.ts","../../node_modules/@types/semver/functions/lt.d.ts","../../node_modules/@types/semver/functions/eq.d.ts","../../node_modules/@types/semver/functions/neq.d.ts","../../node_modules/@types/semver/functions/gte.d.ts","../../node_modules/@types/semver/functions/lte.d.ts","../../node_modules/@types/semver/functions/cmp.d.ts","../../node_modules/@types/semver/functions/coerce.d.ts","../../node_modules/@types/semver/classes/comparator.d.ts","../../node_modules/@types/semver/classes/range.d.ts","../../node_modules/@types/semver/functions/satisfies.d.ts","../../node_modules/@types/semver/ranges/max-satisfying.d.ts","../../node_modules/@types/semver/ranges/min-satisfying.d.ts","../../node_modules/@types/semver/ranges/to-comparators.d.ts","../../node_modules/@types/semver/ranges/min-version.d.ts","../../node_modules/@types/semver/ranges/valid.d.ts","../../node_modules/@types/semver/ranges/outside.d.ts","../../node_modules/@types/semver/ranges/gtr.d.ts","../../node_modules/@types/semver/ranges/ltr.d.ts","../../node_modules/@types/semver/ranges/intersects.d.ts","../../node_modules/@types/semver/ranges/simplify.d.ts","../../node_modules/@types/semver/ranges/subset.d.ts","../../node_modules/@types/semver/internals/identifiers.d.ts","../../node_modules/@types/semver/index.d.ts","../../node_modules/@types/serve-index/index.d.ts","../../node_modules/@types/sockjs/index.d.ts","../../node_modules/@types/sortablejs/plugins.d.ts","../../node_modules/@types/sortablejs/index.d.ts","../../node_modules/@types/stack-utils/index.d.ts","../../node_modules/@types/trusted-types/lib/index.d.ts","../../node_modules/@types/trusted-types/index.d.ts","../../node_modules/@types/uuid/index.d.ts","../../node_modules/@types/vscode/index.d.ts","../../node_modules/@types/vscode-webview/index.d.ts","../../node_modules/@types/webidl-conversions/index.d.ts","../../node_modules/@types/whatwg-url/index.d.ts","../../node_modules/@types/ws/index.d.ts","../../node_modules/@types/yargs-parser/index.d.ts","../../node_modules/@types/yargs/index.d.ts"],"fileIdsList":[[72,83,132],[83,132],[83,132,194],[83,132,407],[83,132,217,219,223,226,228,230,232,234,236,240,244,248,250,252,254,256,258,260,262,264,266,268,276,281,283,285,287,289,292,294,299,303,307,309,311,313,316,318,320,323,325,329,331,333,335,337,339,341,343,345,347,350,353,355,357,361,363,366,368,370,372,376,382,386,388,390,397,399,401,403,406],[83,132,217,350],[83,132,218],[83,132,356],[83,132,217,333,337,350],[83,132,338],[83,132,217,333,350],[83,132,222],[83,132,238,244,248,254,285,337,350],[83,132,293],[83,132,267],[83,132,261],[83,132,351,352],[83,132,350],[83,132,240,244,281,287,299,335,337,350],[83,132,367],[83,132,216,350],[83,132,237],[83,132,219,226,232,236,240,256,268,309,311,313,335,337,341,343,345,350],[83,132,369],[83,132,230,240,256,350],[83,132,371],[83,132,217,226,228,292,333,337,350],[83,132,229],[83,132,354],[83,132,348],[83,132,340],[83,132,217,232,350],[83,132,233],[83,132,257],[83,132,289,335,350,374],[83,132,276,350,374],[83,132,240,248,276,289,333,337,350,373,375],[83,132,373,374,375],[83,132,258,350],[83,132,232,289,335,337,350,379],[83,132,289,335,350,379],[83,132,248,289,333,337,350,378,380],[83,132,377,378,379,380,381],[83,132,289,335,350,384],[83,132,276,350,384],[83,132,240,248,276,289,333,337,350,383,385],[83,132,383,384,385],[83,132,235],[83,132,358,359,360],[83,132,217,219,223,226,230,232,236,238,240,244,248,250,252,254,256,260,262,264,266,268,276,283,285,289,292,309,311,313,318,320,325,329,331,335,339,341,343,345,347,350,357],[83,132,217,219,223,226,230,232,236,238,240,244,248,250,252,254,256,258,260,262,264,266,268,276,283,285,289,292,309,311,313,318,320,325,329,331,335,339,341,343,345,347,350,357],[83,132,240,335,350],[83,132,336],[83,132,277,278,279,280],[83,132,279,289,335,337,350],[83,132,277,281,289,335,350],[83,132,232,248,264,266,276,350],[83,132,238,240,244,248,250,254,256,277,278,280,289,335,337,339,350],[83,132,387],[83,132,230,240,350],[83,132,389],[83,132,223,226,228,230,236,244,248,256,283,285,292,320,335,339,345,350,357],[83,132,265],[83,132,241,242,243],[83,132,226,240,241,292,350],[83,132,240,241,350],[83,132,350,392],[83,132,391,392,393,394,395,396],[83,132,232,289,335,337,350,392],[83,132,232,248,276,289,350,391],[83,132,282],[83,132,295,296,297,298],[83,132,289,296,335,337,350],[83,132,244,248,250,256,287,335,337,339,350],[83,132,232,238,248,254,264,289,295,297,337,350],[83,132,231],[83,132,220,221,288],[83,132,217,335,350],[83,132,220,221,223,226,230,232,234,236,244,248,256,281,283,285,287,292,335,337,339,350],[83,132,223,226,230,234,236,238,240,244,248,254,256,281,283,292,294,299,303,307,316,320,323,325,335,337,339,350],[83,132,328],[83,132,223,226,230,234,236,244,248,250,254,256,283,292,320,333,335,337,339,350],[83,132,217,326,327,333,335,350],[83,132,239],[83,132,330],[83,132,308],[83,132,263],[83,132,334],[83,132,217,226,292,333,337,350],[83,132,300,301,302],[83,132,289,301,335,350],[83,132,289,301,335,337,350],[83,132,232,238,244,248,250,254,281,289,300,302,335,337,350],[83,132,290,291],[83,132,289,290,335],[83,132,217,289,291,337,350],[83,132,398],[83,132,236,240,256,350],[83,132,314,315],[83,132,289,314,335,337,350],[83,132,226,228,232,238,244,248,250,254,260,262,264,266,268,289,292,309,311,313,315,335,337,350],[83,132,362],[83,132,304,305,306],[83,132,289,305,335,350],[83,132,289,305,335,337,350],[83,132,232,238,244,248,250,254,281,289,304,306,335,337,350],[83,132,284],[83,132,227],[83,132,226,292,350],[83,132,224,225],[83,132,224,289,335],[83,132,217,225,289,337,350],[83,132,319],[83,132,217,219,232,234,240,248,260,262,264,266,276,318,333,335,337,350],[83,132,249],[83,132,253],[83,132,217,252,333,350],[83,132,317],[83,132,364,365],[83,132,321,322],[83,132,289,321,335,337,350],[83,132,226,228,232,238,244,248,250,254,260,262,264,266,268,289,292,309,311,313,322,335,337,350],[83,132,400],[83,132,244,248,256,350],[83,132,402],[83,132,236,240,350],[83,132,219,223,230,232,234,236,244,248,250,254,256,260,262,264,266,268,276,283,285,309,311,313,318,320,331,335,339,341,343,345,347,348],[83,132,348,349],[83,132,217],[83,132,286],[83,132,332],[83,132,223,226,230,234,236,240,244,248,250,252,254,256,283,285,292,320,325,329,331,335,337,339,350],[83,132,259],[83,132,310],[83,132,216],[83,132,232,248,258,260,262,264,266,268,269,276],[83,132,232,248,258,262,269,270,276,337],[83,132,269,270,271,272,273,274,275],[83,132,258],[83,132,258,276],[83,132,232,248,260,262,264,268,276,337],[83,132,217,232,240,248,260,262,264,266,268,272,333,337,350],[83,132,232,248,274,333,337],[83,132,324],[83,132,255],[83,132,404,405],[83,132,223,230,236,268,283,285,294,311,313,318,341,343,347,350,357,372,388,390,399,403,404],[83,132,219,226,228,232,234,240,244,248,250,252,254,256,260,262,264,266,276,281,289,292,299,303,307,309,316,320,323,325,329,331,335,339,345,350,368,370,376,382,386,397,401],[83,132,342],[83,132,312],[83,132,245,246,247],[83,132,226,240,245,292,350],[83,132,240,245,350],[83,132,344],[83,132,251],[83,132,346],[72,73,74,75,76,83,132],[72,74,83,132],[83,132,146,181,182],[83,132,138,181],[83,132,174,181,188],[83,132,146,181],[83,132,190],[83,132,181],[83,132,193,199,201],[83,132,193,194,195,201],[83,132,196],[83,132,193,201],[83,132,143,146,181,185,186,187],[83,132,183,186,188,205],[83,132,207],[83,132,143,146,148,151,163,174,181],[83,132,211],[83,132,212],[83,132,409,413],[83,129,132],[83,131,132],[132],[83,132,137,166],[83,132,133,138,143,151,163,174],[83,132,133,134,143,151],[78,79,80,83,132],[83,132,135,175],[83,132,136,137,144,152],[83,132,137,163,171],[83,132,138,140,143,151],[83,131,132,139],[83,132,140,141],[83,132,142,143],[83,131,132,143],[83,132,143,144,145,163,174],[83,132,143,144,145,158,163,166],[83,125,132,140,143,146,151,163,174],[83,132,143,144,146,147,151,163,171,174],[83,132,146,148,163,171,174],[81,82,83,84,85,86,87,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180],[83,132,143,149],[83,132,150,174],[83,132,140,143,151,163],[83,132,152],[83,132,153],[83,131,132,154],[83,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180],[83,132,156],[83,132,157],[83,132,143,158,159],[83,132,158,160,175,177],[83,132,144],[83,132,143,163,164,166],[83,132,165,166],[83,132,163,164],[83,132,166],[83,132,167],[83,129,132,163,168],[83,132,143,169,170],[83,132,169,170],[83,132,137,151,163,171],[83,132,172],[83,132,151,173],[83,132,146,157,174],[83,132,137,175],[83,132,163,176],[83,132,150,177],[83,132,178],[83,125,132],[83,125,132,143,145,154,163,166,174,176,177,179],[83,132,163,180],[83,132,422],[83,132,420,421],[83,132,427,465],[83,132,427,450,465],[83,132,426,465],[83,132,465],[83,132,427],[83,132,427,451,465],[83,132,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464],[83,132,451,465],[83,132,144,163,181],[83,132,144,206],[83,132,146,181,202,204],[83,132,144,163,181,203],[83,132,468],[83,132,469],[83,132,471],[83,132,143,146,148,151,163,171,174,180,181],[83,132,479],[83,132,193,197,198,201],[83,132,199],[83,132,214,411,412],[83,132,409],[83,132,215,410],[63,83,132,140,143,151,163,171],[83,132,408],[83,97,101,132,174],[83,97,132,163,174],[83,92,132],[83,94,97,132,171,174],[83,132,151,171],[83,92,132,181],[83,94,97,132,151,174],[83,89,90,93,96,132,143,163,174],[83,97,104,132],[83,89,95,132],[83,97,118,119,132],[83,93,97,132,166,174,181],[83,118,132,181],[83,91,92,132,181],[83,97,132],[83,91,92,93,94,95,96,97,98,99,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,119,120,121,122,123,124,132],[83,97,112,132],[83,97,104,105,132],[83,95,97,105,106,132],[83,96,132],[83,89,92,97,132],[83,97,101,105,106,132],[83,101,132],[83,95,97,100,132,174],[83,89,94,97,104,132],[83,132,163],[83,92,97,118,132,179,181],[64,83,132],[64,65,66,67,68,83,132,135],[64,65,83,132],[66,67,83,132],[65,66,68,69,70,83,132]],"fileInfos":[{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"feecb1be483ed332fad555aff858affd90a48ab19ba7272ee084704eb7167569","impliedFormat":1},{"version":"ee7bad0c15b58988daa84371e0b89d313b762ab83cb5b31b8a2d1162e8eb41c2","impliedFormat":1},{"version":"27bdc30a0e32783366a5abeda841bc22757c1797de8681bbe81fbc735eeb1c10","impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb0f136d372979348d59b3f5020b4cdb81b5504192b1cacff5d1fbba29378aa1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a680117f487a4d2f30ea46f1b4b7f58bef1480456e18ba53ee85c2746eeca012","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"af3dd424cf267428f30ccfc376f47a2c0114546b55c44d8c0f1d57d841e28d74","affectsGlobalScope":true,"impliedFormat":1},{"version":"995c005ab91a498455ea8dfb63aa9f83fa2ea793c3d8aa344be4a1678d06d399","affectsGlobalScope":true,"impliedFormat":1},{"version":"959d36cddf5e7d572a65045b876f2956c973a586da58e5d26cde519184fd9b8a","affectsGlobalScope":true,"impliedFormat":1},{"version":"965f36eae237dd74e6cca203a43e9ca801ce38824ead814728a2807b1910117d","affectsGlobalScope":true,"impliedFormat":1},{"version":"3925a6c820dcb1a06506c90b1577db1fdbf7705d65b62b99dce4be75c637e26b","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a3d63ef2b853447ec4f749d3f368ce642264246e02911fcb1590d8c161b8005","affectsGlobalScope":true,"impliedFormat":1},{"version":"8cdf8847677ac7d20486e54dd3fcf09eda95812ac8ace44b4418da1bbbab6eb8","affectsGlobalScope":true,"impliedFormat":1},{"version":"8444af78980e3b20b49324f4a16ba35024fef3ee069a0eb67616ea6ca821c47a","affectsGlobalScope":true,"impliedFormat":1},{"version":"3287d9d085fbd618c3971944b65b4be57859f5415f495b33a6adc994edd2f004","affectsGlobalScope":true,"impliedFormat":1},{"version":"b4b67b1a91182421f5df999988c690f14d813b9850b40acd06ed44691f6727ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"df83c2a6c73228b625b0beb6669c7ee2a09c914637e2d35170723ad49c0f5cd4","affectsGlobalScope":true,"impliedFormat":1},{"version":"436aaf437562f276ec2ddbee2f2cdedac7664c1e4c1d2c36839ddd582eeb3d0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e3c06ea092138bf9fa5e874a1fdbc9d54805d074bee1de31b99a11e2fec239d","affectsGlobalScope":true,"impliedFormat":1},{"version":"51ad4c928303041605b4d7ae32e0c1ee387d43a24cd6f1ebf4a2699e1076d4fa","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"26db0a6b70d251b4b95101d8f58dbb8a5fe0643bf010fb69f1deed06a0cc33d2","impliedFormat":1},{"version":"683ab7efcc7cf6e47280404f2bf848a542e306a0ba42cabcd254b22e26de8366","impliedFormat":1},{"version":"c20b8ce38122db4689718a20fdf6d0b4cf15093dbe6d78d37d4e356a873957ef","signature":"044267f133d8dbc6c2dc45938fc8e461ef1ffad97b3c6d578350e519e4c03317"},{"version":"6d5904e3c33d51ca70c178233b3423e975d44fb4ad59e0441a4e84cae477b21f","signature":"923380dfd6d15329e7825751cd55100d7bf79053444d24bc3b3572703de44dc3"},{"version":"ed849d616865076f44a41c87f27698f7cdf230290c44bafc71d7c2bc6919b202","impliedFormat":1},{"version":"0c848b07fd0572ab734788358318459d068d60146b97359931abf6fe9fd17aab","signature":"6530b505e10569b7eed5b4d593175563872adbe29d1897eec015c8292871ddd5"},{"version":"3ca4d95a29ae030bb7ce79baa791bf788ba666a10db998abb776a7eb2cb5d156","signature":"183f4c08a7ba0ebd372749702c05e0c3454deb66b437a8448ac53747c13dbd84"},{"version":"bb9f1c2e030d9a92e814fc030e3c640eee615690ba04e8b8a0c6f09cfb0443de","signature":"ab2bbb6e2856bc23e0d289e364b8472e694c92552b9913d552dace15ceee922d"},{"version":"a3f1ad37c61f8dc9b59d8352259fbaf26ee2e4101347c886216206f1069a969f","signature":"5a03ca98612bedcc00eeae60c16279d58c0f40051a1197ddc56dcec1e645428c"},{"version":"c2c2a861a338244d7dd700d0c52a78916b4bb75b98fc8ca5e7c501899fc03796","impliedFormat":1},{"version":"b6d03c9cfe2cf0ba4c673c209fcd7c46c815b2619fd2aad59fc4229aaef2ed43","impliedFormat":1},{"version":"adb467429462e3891de5bb4a82a4189b92005d61c7f9367c089baf03997c104e","impliedFormat":1},{"version":"670a76db379b27c8ff42f1ba927828a22862e2ab0b0908e38b671f0e912cc5ed","impliedFormat":1},{"version":"13b77ab19ef7aadd86a1e54f2f08ea23a6d74e102909e3c00d31f231ed040f62","impliedFormat":1},{"version":"069bebfee29864e3955378107e243508b163e77ab10de6a5ee03ae06939f0bb9","impliedFormat":1},{"version":"6c7176368037af28cb72f2392010fa1cef295d6d6744bca8cfb54985f3a18c3e","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab41ef1f2cdafb8df48be20cd969d875602483859dc194e9c97c8a576892c052","affectsGlobalScope":true,"impliedFormat":1},{"version":"437e20f2ba32abaeb7985e0afe0002de1917bc74e949ba585e49feba65da6ca1","affectsGlobalScope":true,"impliedFormat":1},{"version":"21d819c173c0cf7cc3ce57c3276e77fd9a8a01d35a06ad87158781515c9a438a","impliedFormat":1},{"version":"98cffbf06d6bab333473c70a893770dbe990783904002c4f1a960447b4b53dca","affectsGlobalScope":true,"impliedFormat":1},{"version":"3af97acf03cc97de58a3a4bc91f8f616408099bc4233f6d0852e72a8ffb91ac9","affectsGlobalScope":true,"impliedFormat":1},{"version":"808069bba06b6768b62fd22429b53362e7af342da4a236ed2d2e1c89fcca3b4a","affectsGlobalScope":true,"impliedFormat":1},{"version":"1db0b7dca579049ca4193d034d835f6bfe73096c73663e5ef9a0b5779939f3d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"f26b11d8d8e4b8028f1c7d618b22274c892e4b0ef5b3678a8ccbad85419aef43","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e9c23ba78aabc2e0a27033f18737a6df754067731e69dc5f52823957d60a4b6","impliedFormat":1},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"763fe0f42b3d79b440a9b6e51e9ba3f3f91352469c1e4b3b67bfa4ff6352f3f4","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"c464d66b20788266e5353b48dc4aa6bc0dc4a707276df1e7152ab0c9ae21fad8","impliedFormat":1},{"version":"78d0d27c130d35c60b5e5566c9f1e5be77caf39804636bc1a40133919a949f21","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"1d6e127068ea8e104a912e42fc0a110e2aa5a66a356a917a163e8cf9a65e4a75","impliedFormat":1},{"version":"5ded6427296cdf3b9542de4471d2aa8d3983671d4cac0f4bf9c637208d1ced43","impliedFormat":1},{"version":"7f182617db458e98fc18dfb272d40aa2fff3a353c44a89b2c0ccb3937709bfb5","impliedFormat":1},{"version":"cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","impliedFormat":1},{"version":"0b8a9268adaf4da35e7fa830c8981cfa22adbbe5b3f6f5ab91f6658899e657a7","impliedFormat":1},{"version":"11396ed8a44c02ab9798b7dca436009f866e8dae3c9c25e8c1fbc396880bf1bb","impliedFormat":1},{"version":"ba7bc87d01492633cb5a0e5da8a4a42a1c86270e7b3d2dea5d156828a84e4882","impliedFormat":1},{"version":"4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","impliedFormat":1},{"version":"c21dc52e277bcfc75fac0436ccb75c204f9e1b3fa5e12729670910639f27343e","impliedFormat":1},{"version":"13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","impliedFormat":1},{"version":"9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","impliedFormat":1},{"version":"4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","impliedFormat":1},{"version":"24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","impliedFormat":1},{"version":"ea0148f897b45a76544ae179784c95af1bd6721b8610af9ffa467a518a086a43","impliedFormat":1},{"version":"24c6a117721e606c9984335f71711877293a9651e44f59f3d21c1ea0856f9cc9","impliedFormat":1},{"version":"dd3273ead9fbde62a72949c97dbec2247ea08e0c6952e701a483d74ef92d6a17","impliedFormat":1},{"version":"405822be75ad3e4d162e07439bac80c6bcc6dbae1929e179cf467ec0b9ee4e2e","impliedFormat":1},{"version":"0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","impliedFormat":1},{"version":"e61be3f894b41b7baa1fbd6a66893f2579bfad01d208b4ff61daef21493ef0a8","impliedFormat":1},{"version":"bd0532fd6556073727d28da0edfd1736417a3f9f394877b6d5ef6ad88fba1d1a","impliedFormat":1},{"version":"89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","impliedFormat":1},{"version":"615ba88d0128ed16bf83ef8ccbb6aff05c3ee2db1cc0f89ab50a4939bfc1943f","impliedFormat":1},{"version":"a4d551dbf8746780194d550c88f26cf937caf8d56f102969a110cfaed4b06656","impliedFormat":1},{"version":"8bd86b8e8f6a6aa6c49b71e14c4ffe1211a0e97c80f08d2c8cc98838006e4b88","impliedFormat":1},{"version":"317e63deeb21ac07f3992f5b50cdca8338f10acd4fbb7257ebf56735bf52ab00","impliedFormat":1},{"version":"4732aec92b20fb28c5fe9ad99521fb59974289ed1e45aecb282616202184064f","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"bf67d53d168abc1298888693338cb82854bdb2e69ef83f8a0092093c2d562107","impliedFormat":1},{"version":"2cbe0621042e2a68c7cbce5dfed3906a1862a16a7d496010636cdbdb91341c0f","affectsGlobalScope":true,"impliedFormat":1},{"version":"f9501cc13ce624c72b61f12b3963e84fad210fbdf0ffbc4590e08460a3f04eba","affectsGlobalScope":true,"impliedFormat":1},{"version":"e7721c4f69f93c91360c26a0a84ee885997d748237ef78ef665b153e622b36c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"df48adbf5b82b79ed989ec3bef2979d988b94978907fd86b4f30ba2b668e49de","impliedFormat":1},{"version":"7394959e5a741b185456e1ef5d64599c36c60a323207450991e7a42e08911419","impliedFormat":1},{"version":"2b06b93fd01bcd49d1a6bd1f9b65ddcae6480b9a86e9061634d6f8e354c1468f","impliedFormat":1},{"version":"6a0cd27e5dc2cfbe039e731cf879d12b0e2dded06d1b1dedad07f7712de0d7f4","affectsGlobalScope":true,"impliedFormat":1},{"version":"13f5c844119c43e51ce777c509267f14d6aaf31eafb2c2b002ca35584cd13b29","impliedFormat":1},{"version":"e60477649d6ad21542bd2dc7e3d9ff6853d0797ba9f689ba2f6653818999c264","impliedFormat":1},{"version":"c2510f124c0293ab80b1777c44d80f812b75612f297b9857406468c0f4dafe29","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"4c829ab315f57c5442c6667b53769975acbf92003a66aef19bce151987675bd1","affectsGlobalScope":true,"impliedFormat":1},{"version":"b2ade7657e2db96d18315694789eff2ddd3d8aea7215b181f8a0b303277cc579","impliedFormat":1},{"version":"9855e02d837744303391e5623a531734443a5f8e6e8755e018c41d63ad797db2","impliedFormat":1},{"version":"6851b67b164a1e84add721ea67ac52696b5aee426b800f68283c6a13046f95ec","impliedFormat":1},{"version":"836a356aae992ff3c28a0212e3eabcb76dd4b0cc06bcb9607aeef560661b860d","impliedFormat":1},{"version":"1e0d1f8b0adfa0b0330e028c7941b5a98c08b600efe7f14d2d2a00854fb2f393","impliedFormat":1},{"version":"41670ee38943d9cbb4924e436f56fc19ee94232bc96108562de1a734af20dc2c","affectsGlobalScope":true,"impliedFormat":1},{"version":"c906fb15bd2aabc9ed1e3f44eb6a8661199d6c320b3aa196b826121552cb3695","impliedFormat":1},{"version":"22295e8103f1d6d8ea4b5d6211e43421fe4564e34d0dd8e09e520e452d89e659","impliedFormat":1},{"version":"a0c4ff5309f0108772562412d15aaa15b32f5db3326288a4490fd461f66a95c8","impliedFormat":1},{"version":"6b4e081d55ac24fc8a4631d5dd77fe249fa25900abd7d046abb87d90e3b45645","impliedFormat":1},{"version":"a10f0e1854f3316d7ee437b79649e5a6ae3ae14ffe6322b02d4987071a95362e","impliedFormat":1},{"version":"ed58b9974bb3114f39806c9c2c6258c4ffa6a255921976a7c53dfa94bf178f42","impliedFormat":1},{"version":"e6fa9ad47c5f71ff733744a029d1dc472c618de53804eae08ffc243b936f87ff","affectsGlobalScope":true,"impliedFormat":1},{"version":"b57f8f7247d878e1bb5c329acbd4c1ad8efb073f4ffa6dc120d52924b1e30e40","impliedFormat":1},{"version":"24826ed94a78d5c64bd857570fdbd96229ad41b5cb654c08d75a9845e3ab7dde","impliedFormat":1},{"version":"45875bcae57270aeb3ebc73a5e3fb4c7b9d91d6b045f107c1d8513c28ece71c0","impliedFormat":1},{"version":"928af3d90454bf656a52a48679f199f64c1435247d6189d1caf4c68f2eaf921f","affectsGlobalScope":true,"impliedFormat":1},{"version":"6fac322c7864146db8daa23389f979fdb9fb97f63f212a9424a302f01c2a40d1","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f16a7e4deafa527ed9995a772bb380eb7d3c2c0fd4ae178c5263ed18394db2c","impliedFormat":1},{"version":"933921f0bb0ec12ef45d1062a1fc0f27635318f4d294e4d99de9a5493e618ca2","impliedFormat":1},{"version":"71a0f3ad612c123b57239a7749770017ecfe6b66411488000aba83e4546fde25","impliedFormat":1},{"version":"77fbe5eecb6fac4b6242bbf6eebfc43e98ce5ccba8fa44e0ef6a95c945ff4d98","impliedFormat":1},{"version":"4f9d8ca0c417b67b69eeb54c7ca1bedd7b56034bb9bfd27c5d4f3bc4692daca7","impliedFormat":1},{"version":"814118df420c4e38fe5ae1b9a3bafb6e9c2aa40838e528cde908381867be6466","impliedFormat":1},{"version":"248bc21b92f51ce0b8a67140f2e55887c5f598095e9a790a05fdd2729b531e7a","impliedFormat":1},{"version":"f27524f4bef4b6519c604bdb23bf4465bddcccbf3f003abb901acbd0d7404d99","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"45650f47bfb376c8a8ed39d4bcda5902ab899a3150029684ee4c10676d9fbaee","impliedFormat":1},{"version":"dba28a419aec76ed864ef43e5f577a5c99a010c32e5949fe4e17a4d57c58dd11","affectsGlobalScope":true,"impliedFormat":1},{"version":"18fd40412d102c5564136f29735e5d1c3b455b8a37f920da79561f1fde068208","impliedFormat":1},{"version":"c959a391a75be9789b43c8468f71e3fa06488b4d691d5729dde1416dcd38225b","impliedFormat":1},{"version":"f0be1b8078cd549d91f37c30c222c2a187ac1cf981d994fb476a1adc61387b14","affectsGlobalScope":true,"impliedFormat":1},{"version":"0aaed1d72199b01234152f7a60046bc947f1f37d78d182e9ae09c4289e06a592","impliedFormat":1},{"version":"8c66347a2f5b28e579a306672633dd900751e72bb5c3150ceb10b1fcfcf3d12d","impliedFormat":1},{"version":"66ba1b2c3e3a3644a1011cd530fb444a96b1b2dfe2f5e837a002d41a1a799e60","impliedFormat":1},{"version":"7e514f5b852fdbc166b539fdd1f4e9114f29911592a5eb10a94bb3a13ccac3c4","impliedFormat":1},{"version":"ea2e8e586844e2ebda7986fd859c4c7b283dc90198cd485250498a5412db27a0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4bf07b8f59b43670a28f14d0d5668a5f4abfe106d481fad660f8a1010529609a","affectsGlobalScope":true,"impliedFormat":1},{"version":"ea08a0345023ade2b47fbff5a76d0d0ed8bff10bc9d22b83f40858a8e941501c","impliedFormat":1},{"version":"47613031a5a31510831304405af561b0ffaedb734437c595256bb61a90f9311b","impliedFormat":1},{"version":"ae062ce7d9510060c5d7e7952ae379224fb3f8f2dd74e88959878af2057c143b","impliedFormat":1},{"version":"71122b94871f11a2be216426470523b679a318b08b34dab23e5e4ba9bdf54c23","affectsGlobalScope":true,"impliedFormat":1},{"version":"02aa5feb7aaa41b25b86c7a873839a799d4c6beee4f7d1789aa338905554e495","impliedFormat":1},{"version":"bdf1feb266c87edbee61f12ceaaef60ab0e2e5dba70ca19360b6448911c53d52","impliedFormat":1},{"version":"104c67f0da1bdf0d94865419247e20eded83ce7f9911a1aa75fc675c077ca66e","impliedFormat":1},{"version":"cc0d0b339f31ce0ab3b7a5b714d8e578ce698f1e13d7f8c60bfb766baeb1d35c","impliedFormat":1},{"version":"f9e22729fa06ed20f8b1fe60670b7c74933fdfd44d869ddfb1919c15a5cf12fb","impliedFormat":1},{"version":"d34aa8df2d0b18fb56b1d772ff9b3c7aea7256cf0d692f969be6e1d27b74d660","impliedFormat":1},{"version":"baac9896d29bcc55391d769e408ff400d61273d832dd500f21de766205255acb","impliedFormat":1},{"version":"2f5747b1508ccf83fad0c251ba1e5da2f5a30b78b09ffa1cfaf633045160afed","impliedFormat":1},{"version":"94ee9ee71018d54902c3fe6730090a8a421dcad95fc372d9b69a6d5351194885","affectsGlobalScope":true,"impliedFormat":1},{"version":"689be50b735f145624c6f391042155ae2ff6b90a93bac11ca5712bc866f6010c","impliedFormat":1},{"version":"fb893a0dfc3c9fb0f9ca93d0648694dd95f33cbad2c0f2c629f842981dfd4e2e","impliedFormat":1},{"version":"3eb11dbf3489064a47a2e1cf9d261b1f100ef0b3b50ffca6c44dd99d6dd81ac1","impliedFormat":1},{"version":"1800025430a0f210d5d1476459447a8a635bfbd9140111fd987e711ad1a770da","impliedFormat":1},{"version":"151ff381ef9ff8da2da9b9663ebf657eac35c4c9a19183420c05728f31a6761d","impliedFormat":1},{"version":"f3d8c757e148ad968f0d98697987db363070abada5f503da3c06aefd9d4248c1","impliedFormat":1},{"version":"a4a39b5714adfcadd3bbea6698ca2e942606d833bde62ad5fb6ec55f5e438ff8","impliedFormat":1},{"version":"bbc1d029093135d7d9bfa4b38cbf8761db505026cc458b5e9c8b74f4000e5e75","impliedFormat":1},{"version":"ac450542cbfd50a4d7bf0f3ec8aeedb9e95791ecc6f2b2b19367696bd303e8c6","impliedFormat":99},{"version":"8a190298d0ff502ad1c7294ba6b0abb3a290fc905b3a00603016a97c363a4c7a","impliedFormat":1},{"version":"5ba4a4a1f9fae0550de86889fb06cd997c8406795d85647cbcd992245625680c","impliedFormat":1},{"version":"1f68ab0e055994eb337b67aa87d2a15e0200951e9664959b3866ee6f6b11a0fe","impliedFormat":1},{"version":"5d08a179b846f5ee674624b349ebebe2121c455e3a265dc93da4e8d9e89722b4","impliedFormat":1},{"version":"b71c603a539078a5e3a039b20f2b0a0d1708967530cf97dec8850a9ca45baa2b","impliedFormat":1},{"version":"d3f2d715f57df3f04bf7b16dde01dec10366f64fce44503c92b8f78f614c1769","impliedFormat":1},{"version":"cb90077223cc1365fa21ef0911a1f9b8f2f878943523d97350dc557973ca3823","impliedFormat":1},{"version":"18f1541b81b80d806120a3489af683edfb811deb91aeca19735d9bb2613e6311","impliedFormat":1},{"version":"232f118ae64ab84dcd26ddb60eaed5a6e44302d36249abf05e9e3fc2cbb701a2","impliedFormat":1},{"version":"89121c1bf2990f5219bfd802a3e7fc557de447c62058d6af68d6b6348d64499a","impliedFormat":1},{"version":"79b4369233a12c6fa4a07301ecb7085802c98f3a77cf9ab97eee27e1656f82e6","impliedFormat":1},{"version":"d7dbe0ad36bdca8a6ecf143422a48e72cc8927bab7b23a1a2485c2f78a7022c6","impliedFormat":1},{"version":"26b7d0cd4b41ab557ef9e3bfeec42dcf24252843633e3d29f38d2c0b13aaa528","impliedFormat":1},{"version":"035a5df183489c2e22f3cf59fc1ed2b043d27f357eecc0eb8d8e840059d44245","impliedFormat":1},{"version":"a4809f4d92317535e6b22b01019437030077a76fec1d93b9881c9ed4738fcc54","impliedFormat":1},{"version":"5f53fa0bd22096d2a78533f94e02c899143b8f0f9891a46965294ee8b91a9434","impliedFormat":1},{"version":"d934a06d62d87a7e2d75a3586b5f9fb2d94d5fe4725ff07252d5f4651485100f","impliedFormat":1},{"version":"0d14fa22c41fdc7277e6f71473b20ebc07f40f00e38875142335d5b63cdfc9d2","impliedFormat":1},{"version":"b104e2da53231a529373174880dc0abfbc80184bb473b6bf2a9a0746bebb663d","impliedFormat":1},{"version":"ee91a5fbbd1627c632df89cce5a4054f9cc6e7413ebdccc82b27c7ffeedf982d","impliedFormat":1},{"version":"85c8731ca285809fc248abf21b921fe00a67b6121d27060d6194eddc0e042b1a","impliedFormat":1},{"version":"6bac0cbdf1bc85ae707f91fdf037e1b600e39fb05df18915d4ecab04a1e59d3c","impliedFormat":1},{"version":"5688b21a05a2a11c25f56e53359e2dcda0a34cb1a582dbeb1eaacdeca55cb699","impliedFormat":1},{"version":"35558bf15f773acbe3ed5ac07dd27c278476630d85245f176e85f9a95128b6e0","impliedFormat":1},{"version":"951f54e4a63e82b310439993170e866dba0f28bb829cbc14d2f2103935cea381","impliedFormat":1},{"version":"4454a999dc1676b866450e8cddd9490be87b391b5526a33f88c7e45129d30c5d","impliedFormat":1},{"version":"99013139312db746c142f27515a14cdebb61ff37f20ee1de6a58ce30d36a4f0d","impliedFormat":1},{"version":"71da852f38ac50d2ae43a7b7f2899b10a2000727fee293b0b72123ed2e7e2ad6","impliedFormat":1},{"version":"74dd1096fca1fec76b951cf5eacf609feaf919e67e13af02fed49ec3b77ea797","impliedFormat":1},{"version":"a0691153ccf5aa1b687b1500239722fff4d755481c20e16d9fcd7fb2d659c7c7","impliedFormat":1},{"version":"fe2201d73ae56b1b4946c10e18549a93bf4c390308af9d422f1ffd3c7989ffc8","impliedFormat":1},{"version":"cad63667f992149cee390c3e98f38c00eee56a2dae3541c6d9929641b835f987","impliedFormat":1},{"version":"f497cad2b33824d8b566fa276cfe3561553f905fdc6b40406c92bcfcaec96552","impliedFormat":1},{"version":"eb58c4dbc6fec60617d80f8ccf23900a64d3190fda7cfb2558b389506ec69be0","impliedFormat":1},{"version":"578929b1c1e3adaed503c0a0f9bda8ba3fea598cc41ad5c38932f765684d9888","impliedFormat":1},{"version":"7cc9d600b2070b1e5c220044a8d5a58b40da1c11399b6c8968711de9663dc6b2","impliedFormat":1},{"version":"45f36cf09d3067cd98b39a7d430e0e531f02911dd6d63b6d784b1955eef86435","impliedFormat":1},{"version":"80419a23b4182c256fa51d71cb9c4d872256ca6873701ceabbd65f8426591e49","impliedFormat":1},{"version":"5aa046aaab44da1a63d229bd67a7a1344afbd6f64db20c2bbe3981ceb2db3b07","impliedFormat":1},{"version":"ed9ad5b51c6faf9d6f597aa0ab11cb1d3a361c51ba59d1220557ef21ad5b0146","impliedFormat":1},{"version":"73db7984e8a35e6b48e3879a6d024803dd990022def2750b3c23c01eb58bc30f","impliedFormat":1},{"version":"c9ecb910b3b4c0cf67bc74833fc41585141c196b5660d2eb3a74cfffbf5aa266","impliedFormat":1},{"version":"33dcfba8a7e4acbe23974d342c44c36d7382c3d1d261f8aef28261a7a5df2969","impliedFormat":1},{"version":"de26700eb7277e8cfdde32ebb21b3d9ad1d713b64fdc2019068b857611e8f0c4","impliedFormat":1},{"version":"e481bd2c07c8e93eb58a857a9e66f22cb0b5ddfd86bbf273816fd31ef3a80613","impliedFormat":1},{"version":"ef156ba4043f6228d37645d6d9c6230a311e1c7a86669518d5f2ebc26e6559bf","impliedFormat":1},{"version":"457fd1e6d6f359d7fa2ca453353f4317efccae5c902b13f15c587597015212bc","impliedFormat":1},{"version":"473b2b42af720ebdb539988c06e040fd9600facdeb23cb297d72ee0098d8598f","impliedFormat":1},{"version":"22bc373ca556de33255faaddb373fec49e08336638958ad17fbd6361c7461eed","impliedFormat":1},{"version":"b3d58358675095fef03ec71bddc61f743128682625f1336df2fc31e29499ab25","impliedFormat":1},{"version":"5b1ef94b03042629c76350fe18be52e17ab70f1c3be8f606102b30a5cd86c1b3","impliedFormat":1},{"version":"a7b6046c44d5fda21d39b3266805d37a2811c2f639bf6b40a633b9a5fb4f5d88","impliedFormat":1},{"version":"80b036a132f3def4623aad73d526c6261dcae3c5f7013857f9ecf6589b72951f","impliedFormat":1},{"version":"0a347c2088c3b1726b95ccde77953bede00dd9dd2fda84585fa6f9f6e9573c18","impliedFormat":1},{"version":"8cc3abb4586d574a3faeea6747111b291e0c9981003a0d72711351a6bcc01421","impliedFormat":1},{"version":"0a516adfde610035e31008b170da29166233678216ef3646822c1b9af98879da","impliedFormat":1},{"version":"70d48a1faa86f67c9cb8a39babc5049246d7c67b6617cd08f64e29c055897ca9","impliedFormat":1},{"version":"a8d7795fcf72b0b91fe2ad25276ea6ab34fdb0f8f42aa1dd4e64ee7d02727031","impliedFormat":1},{"version":"082b818038423de54be877cebdb344a2e3cf3f6abcfc48218d8acf95c030426a","impliedFormat":1},{"version":"813514ef625cb8fc3befeec97afddfb3b80b80ced859959339d99f3ad538d8fe","impliedFormat":1},{"version":"039cd54028eb988297e189275764df06c18f9299b14c063e93bd3f30c046fee6","impliedFormat":1},{"version":"e91cfd040e6da28427c5c4396912874902c26605240bdc3457cc75b6235a80f2","impliedFormat":1},{"version":"b4347f0b45e4788c18241ac4dee20ceab96d172847f1c11d42439d3de3c09a3e","impliedFormat":1},{"version":"16fe6721dc0b4144a0cdcef98857ee19025bf3c2a3cc210bcd0b9d0e25f7cec8","impliedFormat":1},{"version":"346d903799e8ea99e9674ba5745642d47c0d77b003cc7bb93e1d4c21c9e37101","impliedFormat":1},{"version":"3997421bb1889118b1bbfc53dd198c3f653bf566fd13c663e02eb08649b985c4","impliedFormat":1},{"version":"2d1ac54184d897cb5b2e732d501fa4591f751678717fd0c1fd4a368236b75cba","impliedFormat":1},{"version":"bade30041d41945c54d16a6ec7046fba6d1a279aade69dfdef9e70f71f2b7226","impliedFormat":1},{"version":"56fbea100bd7dd903dc49a1001995d3c6eee10a419c66a79cdb194bff7250eb7","impliedFormat":1},{"version":"fe8d26b2b3e519e37ceea31b1790b17d7c5ab30334ca2b56d376501388ba80d6","impliedFormat":1},{"version":"37ad0a0c2b296442072cd928d55ef6a156d50793c46c2e2497da1c2750d27c1e","impliedFormat":1},{"version":"be93d07586d09e1b6625e51a1591d6119c9f1cbd95718497636a406ec42babee","impliedFormat":1},{"version":"a062b507ed5fc23fbc5850fd101bc9a39e9a0940bb52a45cd4624176337ad6b8","impliedFormat":1},{"version":"cf01f601ef1e10b90cad69312081ce0350f26a18330913487a26d6d4f7ce5a73","impliedFormat":1},{"version":"a9de7b9a5deaed116c9c89ad76fdcc469226a22b79c80736de585af4f97b17cd","impliedFormat":1},{"version":"5bde81e8b0efb2d977c6795f9425f890770d54610764b1d8df340ce35778c4f8","impliedFormat":1},{"version":"20fd0402351907669405355eeae8db00b3cf0331a3a86d8142f7b33805174f57","impliedFormat":1},{"version":"da6949af729eca1ec1fe867f93a601988b5b206b6049c027d0c849301d20af6f","impliedFormat":1},{"version":"7008f240ea3a5a344be4e5f9b5dbf26721aad3c5cfef5ff79d133fa7450e48fa","impliedFormat":1},{"version":"eb13c8624f5747a845aea0df1dfde0f2b8f5ed90ca3bc550b12777797cb1b1e3","impliedFormat":1},{"version":"2452fc0f47d3b5b466bda412397831dd5138e62f77aa5e11270e6ca3ecb8328d","impliedFormat":1},{"version":"33c2ebbdd9a62776ca0091a8d1f445fa2ea4b4f378bc92f524031a70dfbeec86","impliedFormat":1},{"version":"3ac3a5b34331a56a3f76de9baf619def3f3073961ce0a012b6ffa72cf8a91f1f","impliedFormat":1},{"version":"d5e9d32cc9813a5290a17492f554999e33f1aa083a128d3e857779548537a778","impliedFormat":1},{"version":"776f49489fa2e461b40370e501d8e775ddb32433c2d1b973f79d9717e1d79be5","impliedFormat":1},{"version":"be94ea1bfaa2eeef1e821a024914ef94cf0cba05be8f2e7df7e9556231870a1d","impliedFormat":1},{"version":"40cd13782413c7195ad8f189f81174850cc083967d056b23d529199d64f02c79","impliedFormat":1},{"version":"05e041810faf710c1dcd03f3ffde100c4a744672d93512314b1f3cfffccdaf20","impliedFormat":1},{"version":"15a8f79b1557978d752c0be488ee5a70daa389638d79570507a3d4cfc620d49d","impliedFormat":1},{"version":"968ee57037c469cffb3b0e268ab824a9c31e4205475b230011895466a1e72da4","impliedFormat":1},{"version":"77debd777927059acbaf1029dfc95900b3ab8ed0434ce3914775efb0574e747b","impliedFormat":1},{"version":"921e3bd6325acb712cd319eaec9392c9ad81f893dead509ab2f4e688f265e536","impliedFormat":1},{"version":"60f6768c96f54b870966957fb9a1b176336cd82895ded088980fb506c032be1c","impliedFormat":1},{"version":"755d9b267084db4ea40fa29653ea5fc43e125792b1940f2909ec70a4c7f712d8","impliedFormat":1},{"version":"7e3056d5333f2d8a9e54324c2e2293027e4cd9874615692a53ad69090894d116","impliedFormat":1},{"version":"1e25b848c58ad80be5c31b794d49092d94df2b7e492683974c436bcdbefb983c","impliedFormat":1},{"version":"3df6fc700b8d787974651680ae6e37b6b50726cf5401b7887f669ab195c2f2ef","impliedFormat":1},{"version":"145df08c171ec616645a353d5eaa5d5f57a5fbce960a47d847548abd9215a99e","impliedFormat":1},{"version":"dcfd2ca9e033077f9125eeca6890bb152c6c0bc715d0482595abc93c05d02d92","impliedFormat":1},{"version":"8056fa6beb8297f160e13c9b677ba2be92ab23adfb6940e5a974b05acd33163b","impliedFormat":1},{"version":"86dda1e79020fad844010b39abb68fafed2f3b2156e3302820c4d0a161f88b03","impliedFormat":1},{"version":"dea0dcec8d5e0153d6f0eacebb163d7c3a4b322a9304048adffc6d26084054bd","impliedFormat":1},{"version":"2afd081a65d595d806b0ff434d2a96dc3d6dcd8f0d1351c0a0968568c6944e0b","impliedFormat":1},{"version":"10ca40958b0dbba6426cf142c0347559cdd97d66c10083e829b10eb3c0ebc75c","impliedFormat":1},{"version":"2f1f7c65e8ee58e3e7358f9b8b3c37d8447549ecc85046f9405a0fc67fbdf54b","impliedFormat":1},{"version":"e3f3964ff78dee11a07ae589f1319ff682f62f3c6c8afa935e3d8616cf21b431","impliedFormat":1},{"version":"2762c2dbee294ffb8fdbcae6db32c3dae09e477d6a348b48578b4145b15d1818","impliedFormat":1},{"version":"e0f1c55e727739d4918c80cd9f82cf8a94274838e5ac48ff0c36529e23b79dc5","impliedFormat":1},{"version":"24bd135b687da453ea7bd98f7ece72e610a3ff8ca6ec23d321c0e32f19d32db6","impliedFormat":1},{"version":"64d45d55ba6e42734ac326d2ea1f674c72837443eb7ff66c82f95e4544980713","impliedFormat":1},{"version":"f9b0dc747f13dcc09e40c26ddcc118b1bafc3152f771fdc32757a7f8916a11fc","impliedFormat":1},{"version":"7035fc608c297fd38dfe757d44d3483a570e2d6c8824b2d6b20294d617da64c6","impliedFormat":1},{"version":"22160a296186123d2df75280a1fab70d2105ce1677af1ebb344ffcb88eef6e42","impliedFormat":1},{"version":"9067b3fd7d71165d4c34fcbbf29f883860fd722b7e8f92e87da036b355a6c625","impliedFormat":1},{"version":"e01ab4b99cc4a775d06155e9cadd2ebd93e4af46e2723cb9361f24a4e1f178ef","impliedFormat":1},{"version":"9a13410635d5cc9c2882e67921c59fb26e77b9d99efa1a80b5a46fdc2954afce","impliedFormat":1},{"version":"eabf68d666f0568b6439f4a58559d42287c3397a03fa6335758b1c8811d4174a","impliedFormat":1},{"version":"fa894bdddb2ba0e6c65ad0d88942cf15328941246410c502576124ef044746f9","impliedFormat":1},{"version":"59c5a06fa4bf2fa320a3c5289b6f199a3e4f9562480f59c0987c91dc135a1adf","impliedFormat":1},{"version":"456a9a12ad5d57af0094edf99ceab1804449f6e7bc773d85d09c56a18978a177","impliedFormat":1},{"version":"a8e2a77f445a8a1ce61bfd4b7b22664d98cf19b84ec6a966544d0decec18e143","impliedFormat":1},{"version":"6f6b0b477db6c4039410c7a13fe1ebed4910dedf644330269816df419cdb1c65","impliedFormat":1},{"version":"960b6e1edfb9aafbd560eceaae0093b31a9232ab273f4ed776c647b2fb9771da","impliedFormat":1},{"version":"3bf44073402d2489e61cdf6769c5c4cf37529e3a1cd02f01c58b7cf840308393","impliedFormat":1},{"version":"a0db48d42371b223cea8fd7a41763d48f9166ecd4baecc9d29d9bb44cc3c2d83","impliedFormat":1},{"version":"aaf3c2e268f27514eb28255835f38445a200cd8bcfdff2c07c6227f67aaaf657","impliedFormat":1},{"version":"6ade56d2afdf75a9bd55cd9c8593ed1d78674804d9f6d9aba04f807f3179979e","impliedFormat":1},{"version":"b67acb619b761e91e3a11dddb98c51ee140361bc361eb17538f1c3617e3ec157","impliedFormat":1},{"version":"81b097e0f9f8d8c3d5fe6ba9dc86139e2d95d1e24c5ce7396a276dfbb2713371","impliedFormat":1},{"version":"692d56fff4fb60948fe16e9fed6c4c4eac9b263c06a8c6e63726e28ed4844fd4","impliedFormat":1},{"version":"f13228f2c0e145fc6dc64917eeef690fb2883a0ac3fa9ebfbd99616fd12f5629","impliedFormat":1},{"version":"d89b2b41a42c04853037408080a2740f8cd18beee1c422638d54f8aefe95c5b8","impliedFormat":1},{"version":"be5d39e513e3e0135068e4ebed5473ab465ae441405dce90ab95055a14403f64","impliedFormat":1},{"version":"97e320c56905d9fa6ac8bd652cea750265384f048505870831e273050e2878cc","impliedFormat":1},{"version":"9932f390435192eb93597f89997500626fb31005416ce08a614f66ec475c5c42","impliedFormat":1},{"version":"5d89ca552233ac2d61aee34b0587f49111a54a02492e7a1098e0701dedca60c9","impliedFormat":1},{"version":"369773458c84d91e1bfcb3b94948a9768f15bf2829538188abd467bad57553cd","impliedFormat":1},{"version":"fdc4fd2c610b368104746960b45216bc32685927529dd871a5330f4871d14906","impliedFormat":1},{"version":"7b5d77c769a6f54ea64b22f1877d64436f038d9c81f1552ad11ed63f394bd351","impliedFormat":1},{"version":"4f7d54c603949113f45505330caae6f41e8dbb59841d4ae20b42307dc4579835","impliedFormat":1},{"version":"a71fd01a802624c3fce6b09c14b461cc7c7758aa199c202d423a7c89ad89943c","impliedFormat":1},{"version":"1ed0dc05908eb15f46379bc1cb64423760e59d6c3de826a970b2e2f6da290bf5","impliedFormat":1},{"version":"db89ef053f209839606e770244031688c47624b771ff5c65f0fa1ec10a6919f1","impliedFormat":1},{"version":"4d45b88987f32b2ac744f633ff5ddb95cd10f64459703f91f1633ff457d6c30d","impliedFormat":1},{"version":"8512fd4a480cd8ef8bf923a85ff5e97216fa93fb763ec871144a9026e1c9dade","impliedFormat":1},{"version":"2aa58b491183eedf2c8ae6ef9a610cd43433fcd854f4cc3e2492027fbe63f5ca","impliedFormat":1},{"version":"ce1f3439cb1c5a207f47938e68752730892fc3e66222227effc6a8b693450b82","impliedFormat":1},{"version":"295ce2cf585c26a9b71ba34fbb026d2b5a5f0d738b06a356e514f39c20bf38ba","impliedFormat":1},{"version":"342f10cf9ba3fbf52d54253db5c0ac3de50360b0a3c28e648a449e28a4ac8a8c","impliedFormat":1},{"version":"c485987c684a51c30e375d70f70942576fa86e9d30ee8d5849b6017931fccc6f","impliedFormat":1},{"version":"320bd1aa480e22cdd7cd3d385157258cc252577f4948cbf7cfdf78ded9d6d0a8","impliedFormat":1},{"version":"4ee053dfa1fce5266ecfae2bf8b6b0cb78a6a76060a1dcf66fb7215b9ff46b0b","impliedFormat":1},{"version":"1f84d8b133284b596328df47453d3b3f3817ad206cf3facf5eb64b0a2c14f6d7","impliedFormat":1},{"version":"5c75e05bc62bffe196a9b2e9adfa824ffa7b90d62345a766c21585f2ce775001","impliedFormat":1},{"version":"cc2eb5b23140bbceadf000ef2b71d27ac011d1c325b0fc5ecd42a3221db5fb2e","impliedFormat":1},{"version":"fd75cc24ea5ec28a44c0afc2f8f33da5736be58737ba772318ae3bdc1c079dc3","impliedFormat":1},{"version":"5ae43407346e6f7d5408292a7d957a663cc7b6d858a14526714a23466ac83ef9","impliedFormat":1},{"version":"c72001118edc35bbe4fff17674dc5f2032ccdbcc5bec4bd7894a6ed55739d31b","impliedFormat":1},{"version":"353196fd0dd1d05e933703d8dad664651ed172b8dfb3beaef38e66522b1e0219","impliedFormat":1},{"version":"670aef817baea9332d7974295938cf0201a2d533c5721fccf4801ba9a4571c75","impliedFormat":1},{"version":"3f5736e735ee01c6ecc6d4ab35b2d905418bb0d2128de098b73e11dd5decc34f","impliedFormat":1},{"version":"b64e159c49afc6499005756f5a7c2397c917525ceab513995f047cdd80b04bdf","impliedFormat":1},{"version":"f72b400dbf8f27adbda4c39a673884cb05daf8e0a1d8152eec2480f5700db36c","impliedFormat":1},{"version":"24509d0601fc00c4d77c20cacddbca6b878025f4e0712bddd171c7917f8cdcde","impliedFormat":1},{"version":"5f5baa59149d3d6d6cef2c09d46bb4d19beb10d6bee8c05b7850c33535b3c438","impliedFormat":1},{"version":"f17a51aae728f9f1a2290919cf29a927621b27f6ae91697aee78f41d48851690","impliedFormat":1},{"version":"be02e3c3cb4e187fd252e7ae12f6383f274e82288c8772bb0daf1a4e4af571ad","impliedFormat":1},{"version":"82ca40fb541799273571b011cd9de6ee9b577ef68acc8408135504ae69365b74","impliedFormat":1},{"version":"8fb6646db72914d6ef0692ea88b25670bbf5e504891613a1f46b42783ec18cce","impliedFormat":1},{"version":"07b0cb8b69e71d34804bde3e6dc6faaae8299f0118e9566b94e1f767b8ba9d64","impliedFormat":1},{"version":"213aa21650a910d95c4d0bee4bb936ecd51e230c1a9e5361e008830dcc73bc86","impliedFormat":1},{"version":"874a8c5125ad187e47e4a8eacc809c866c0e71b619a863cc14794dd3ccf23940","impliedFormat":1},{"version":"c31db8e51e85ee67018ac2a40006910efbb58e46baea774cf1f245d99bf178b5","impliedFormat":1},{"version":"31fac222250b18ebac0158938ede4b5d245e67d29cd2ef1e6c8a5859d137d803","impliedFormat":1},{"version":"a9dfb793a7e10949f4f3ea9f282b53d3bd8bf59f5459bc6e618e3457ed2529f5","impliedFormat":1},{"version":"2a77167687b0ec0c36ef581925103f1dc0c69993f61a9dbd299dcd30601af487","impliedFormat":1},{"version":"0f23b5ce60c754c2816c2542b9b164d6cb15243f4cbcd11cfafcab14b60e04d0","impliedFormat":1},{"version":"813ce40a8c02b172fdbeb8a07fdd427ac68e821f0e20e3dc699fb5f5bdf1ef0a","impliedFormat":1},{"version":"5ce6b24d5fd5ebb1e38fe817b8775e2e00c94145ad6eedaf26e3adf8bb3903d0","impliedFormat":1},{"version":"6babca69d3ae17be168cfceb91011eed881d41ce973302ee4e97d68a81c514b4","impliedFormat":1},{"version":"3e0832bc2533c0ec6ffcd61b7c055adedcca1a45364b3275c03343b83c71f5b3","impliedFormat":1},{"version":"342418c52b55f721b043183975052fb3956dae3c1f55f965fedfbbf4ad540501","impliedFormat":1},{"version":"6a6ab1edb5440ee695818d76f66d1a282a31207707e0d835828341e88e0c1160","impliedFormat":1},{"version":"7e9b4669774e97f5dc435ddb679aa9e7d77a1e5a480072c1d1291892d54bf45c","impliedFormat":1},{"version":"de439ddbed60296fbd1e5b4d242ce12aad718dffe6432efcae1ad6cd996defd3","impliedFormat":1},{"version":"ce5fb71799f4dbb0a9622bf976a192664e6c574d125d3773d0fa57926387b8b2","impliedFormat":1},{"version":"b9c0de070a5876c81540b1340baac0d7098ea9657c6653731a3199fcb2917cef","impliedFormat":1},{"version":"cbc91ecd74d8f9ddcbcbdc2d9245f14eff5b2f6ae38371283c97ca7dc3c4a45f","impliedFormat":1},{"version":"3ca1d6f016f36c61a59483c80d8b9f9d50301fbe52a0dde288c1381862b13636","impliedFormat":1},{"version":"ecfef0c0ff0c80ac9a6c2fab904a06b680fb5dfe8d9654bb789e49c6973cb781","impliedFormat":1},{"version":"0ee2eb3f7c0106ccf6e388bc0a16e1b3d346e88ac31b6a5bbc15766e43992167","impliedFormat":1},{"version":"f9592b77fd32a7a1262c1e9363d2e43027f513d1d2ff6b21e1cfdac4303d5a73","impliedFormat":1},{"version":"7e46dd61422e5afe88c34e5f1894ae89a37b7a07393440c092e9dc4399820172","impliedFormat":1},{"version":"9df4f57d7279173b0810154c174aa03fd60f5a1f0c3acfe8805e55e935bdecd4","impliedFormat":1},{"version":"a02a51b68a60a06d4bd0c747d6fbade0cb87eefda5f985fb4650e343da424f12","impliedFormat":1},{"version":"0cf851e2f0ecf61cabe64efd72de360246bcb8c19c6ef7b5cbb702293e1ff755","impliedFormat":1},{"version":"0c0e0aaf37ab0552dffc13eb584d8c56423b597c1c49f7974695cb45e2973de6","impliedFormat":1},{"version":"e2e0cd8f6470bc69bbfbc5e758e917a4e0f9259da7ffc93c0930516b0aa99520","impliedFormat":1},{"version":"180de8975eff720420697e7b5d95c0ecaf80f25d0cea4f8df7fe9cf817d44884","impliedFormat":1},{"version":"424a7394f9704d45596dce70bd015c5afec74a1cc5760781dfda31bc300df88f","impliedFormat":1},{"version":"044a62b9c967ee8c56dcb7b2090cf07ef2ac15c07e0e9c53d99fab7219ee3d67","impliedFormat":1},{"version":"3903b01a9ba327aae8c7ea884cdabc115d27446fba889afc95fddca8a9b4f6e2","impliedFormat":1},{"version":"78fd8f2504fbfb0070569729bf2fe41417fdf59f8c3e975ab3143a96f03e0a4a","impliedFormat":1},{"version":"8afd4f91e3a060a886a249f22b23da880ec12d4a20b6404acc5e283ef01bdd46","impliedFormat":1},{"version":"72e72e3dea4081877925442f67b23be151484ef0a1565323c9af7f1c5a0820f0","impliedFormat":1},{"version":"fa8c21bafd5d8991019d58887add8971ccbe88243c79bbcaec2e2417a40af4e8","impliedFormat":1},{"version":"ab35597fd103b902484b75a583606f606ab2cef7c069fae6c8aca0f058cee77d","impliedFormat":1},{"version":"ca54ec33929149dded2199dca95fd8ad7d48a04f6e8500f3f84a050fa77fee45","impliedFormat":1},{"version":"cac7dcf6f66d12979cc6095f33edc7fbb4266a44c8554cd44cd04572a4623fd0","impliedFormat":1},{"version":"98af566e6d420e54e4d8d942973e7fbe794e5168133ad6658b589d9dfb4409d8","impliedFormat":1},{"version":"772b2865dd86088c6e0cab71e23534ad7254961c1f791bdeaf31a57a2254df43","impliedFormat":1},{"version":"786d837fba58af9145e7ad685bc1990f52524dc4f84f3e60d9382a0c3f4a0f77","impliedFormat":1},{"version":"539dd525bf1d52094e7a35c2b4270bee757d3a35770462bcb01cd07683b4d489","impliedFormat":1},{"version":"69135303a105f3b058d79ea7e582e170721e621b1222e8f8e51ea29c61cd3acf","impliedFormat":1},{"version":"e92e6f0d63e0675fe2538e8031e1ece36d794cb6ecc07a036d82c33fa3e091a9","impliedFormat":1},{"version":"1fdb07843cdb9bd7e24745d357c6c1fde5e7f2dd7c668dd68b36c0dff144a390","impliedFormat":1},{"version":"3e2f739bdfb6b194ae2af13316b4c5bb18b3fe81ac340288675f92ba2061b370","affectsGlobalScope":true,"impliedFormat":1},{"version":"96d14f21b7652903852eef49379d04dbda28c16ed36468f8c9fa08f7c14c9538","impliedFormat":1},{"version":"d4a22007b481fe2a2e6bfd3a42c00cd62d41edb36d30fc4697df2692e9891fc8","impliedFormat":1},{"version":"29f72ec1289ae3aeda78bf14b38086d3d803262ac13904b400422941a26a3636","affectsGlobalScope":true,"impliedFormat":1},{"version":"7fadb2778688ebf3fd5b8d04f63d5bf27a43a3e420bc80732d3c6239067d1a4b","impliedFormat":1},{"version":"22293bd6fa12747929f8dfca3ec1684a3fe08638aa18023dd286ab337e88a592","impliedFormat":1},{"version":"170d4db14678c68178ee8a3d5a990d5afb759ecb6ec44dbd885c50f6da6204f6","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac51dd7d31333793807a6abaa5ae168512b6131bd41d9c5b98477fc3b7800f9f","impliedFormat":1},{"version":"5e76305d58bcdc924ff2bf14f6a9dc2aa5441ed06464b7e7bd039e611d66a89b","impliedFormat":1},{"version":"be1cc4d94ea60cbe567bc29ed479d42587bf1e6cba490f123d329976b0fe4ee5","impliedFormat":1},{"version":"510616459e6edd01acbce333fb256e06bdffdad43ca233a9090164bf8bb83912","impliedFormat":1},{"version":"d1e9031cfefebb12d6672ef7d85faf2c5a23472f5b5be1909358db426fe82eef","impliedFormat":1},{"version":"ce6a3f09b8db73a7e9701aca91a04b4fabaf77436dd35b24482f9ee816016b17","impliedFormat":1},{"version":"20e086e5b64fdd52396de67761cc0e94693494deadb731264aac122adf08de3f","impliedFormat":1},{"version":"6e78f75403b3ec65efb41c70d392aeda94360f11cedc9fb2c039c9ea23b30962","impliedFormat":1},{"version":"c863198dae89420f3c552b5a03da6ed6d0acfa3807a64772b895db624b0de707","impliedFormat":1},{"version":"8b03a5e327d7db67112ebbc93b4f744133eda2c1743dbb0a990c61a8007823ef","impliedFormat":1},{"version":"42fad1f540271e35ca37cecda12c4ce2eef27f0f5cf0f8dd761d723c744d3159","impliedFormat":1},{"version":"ff3743a5de32bee10906aff63d1de726f6a7fd6ee2da4b8229054dfa69de2c34","impliedFormat":1},{"version":"83acd370f7f84f203e71ebba33ba61b7f1291ca027d7f9a662c6307d74e4ac22","impliedFormat":1},{"version":"1445cec898f90bdd18b2949b9590b3c012f5b7e1804e6e329fb0fe053946d5ec","impliedFormat":1},{"version":"0e5318ec2275d8da858b541920d9306650ae6ac8012f0e872fe66eb50321a669","impliedFormat":1},{"version":"cf530297c3fb3a92ec9591dd4fa229d58b5981e45fe6702a0bd2bea53a5e59be","impliedFormat":1},{"version":"c1f6f7d08d42148ddfe164d36d7aba91f467dbcb3caa715966ff95f55048b3a4","impliedFormat":1},{"version":"eefd2bbc8edb14c3bd1246794e5c070a80f9b8f3730bd42efb80df3cc50b9039","impliedFormat":1},{"version":"0c1ee27b8f6a00097c2d6d91a21ee4d096ab52c1e28350f6362542b55380059a","impliedFormat":1},{"version":"7677d5b0db9e020d3017720f853ba18f415219fb3a9597343b1b1012cfd699f7","impliedFormat":1},{"version":"bc1c6bc119c1784b1a2be6d9c47addec0d83ef0d52c8fbe1f14a51b4dfffc675","impliedFormat":1},{"version":"52cf2ce99c2a23de70225e252e9822a22b4e0adb82643ab0b710858810e00bf1","impliedFormat":1},{"version":"770625067bb27a20b9826255a8d47b6b5b0a2d3dfcbd21f89904c731f671ba77","impliedFormat":1},{"version":"d1ed6765f4d7906a05968fb5cd6d1db8afa14dbe512a4884e8ea5c0f5e142c80","impliedFormat":1},{"version":"799c0f1b07c092626cf1efd71d459997635911bb5f7fc1196efe449bba87e965","impliedFormat":1},{"version":"2a184e4462b9914a30b1b5c41cf80c6d3428f17b20d3afb711fff3f0644001fd","impliedFormat":1},{"version":"9eabde32a3aa5d80de34af2c2206cdc3ee094c6504a8d0c2d6d20c7c179503cc","impliedFormat":1},{"version":"397c8051b6cfcb48aa22656f0faca2553c5f56187262135162ee79d2b2f6c966","impliedFormat":1},{"version":"a8ead142e0c87dcd5dc130eba1f8eeed506b08952d905c47621dc2f583b1bff9","impliedFormat":1},{"version":"a02f10ea5f73130efca046429254a4e3c06b5475baecc8f7b99a0014731be8b3","impliedFormat":1},{"version":"c2576a4083232b0e2d9bd06875dd43d371dee2e090325a9eac0133fd5650c1cb","impliedFormat":1},{"version":"4c9a0564bb317349de6a24eb4efea8bb79898fa72ad63a1809165f5bd42970dd","impliedFormat":1},{"version":"f40ac11d8859092d20f953aae14ba967282c3bb056431a37fced1866ec7a2681","impliedFormat":1},{"version":"cc11e9e79d4746cc59e0e17473a59d6f104692fd0eeea1bdb2e206eabed83b03","impliedFormat":1},{"version":"b444a410d34fb5e98aa5ee2b381362044f4884652e8bc8a11c8fe14bbd85518e","impliedFormat":1},{"version":"c35808c1f5e16d2c571aa65067e3cb95afeff843b259ecfa2fc107a9519b5392","impliedFormat":1},{"version":"14d5dc055143e941c8743c6a21fa459f961cbc3deedf1bfe47b11587ca4b3ef5","impliedFormat":1},{"version":"a3ad4e1fc542751005267d50a6298e6765928c0c3a8dce1572f2ba6ca518661c","impliedFormat":1},{"version":"f237e7c97a3a89f4591afd49ecb3bd8d14f51a1c4adc8fcae3430febedff5eb6","impliedFormat":1},{"version":"3ffdfbec93b7aed71082af62b8c3e0cc71261cc68d796665faa1e91604fbae8f","impliedFormat":1},{"version":"662201f943ed45b1ad600d03a90dffe20841e725203ced8b708c91fcd7f9379a","impliedFormat":1},{"version":"c9ef74c64ed051ea5b958621e7fb853fe3b56e8787c1587aefc6ea988b3c7e79","impliedFormat":1},{"version":"2462ccfac5f3375794b861abaa81da380f1bbd9401de59ffa43119a0b644253d","impliedFormat":1},{"version":"34baf65cfee92f110d6653322e2120c2d368ee64b3c7981dff08ed105c4f19b0","impliedFormat":1},{"version":"a56fe175741cc8841835eb72e61fa5a34adcbc249ede0e3494c229f0750f6b85","impliedFormat":1},{"version":"ddef25f825320de051dcb0e62ffce621b41c67712b5b4105740c32fd83f4c449","impliedFormat":1},{"version":"1b3dffaa4ca8e38ac434856843505af767a614d187fb3a5ef4fcebb023c355aa","impliedFormat":1},{"version":"cbb2be0de4e2a597ba2b7050389629fb4c2592a923e989d45095d1546913a696","impliedFormat":1},{"version":"aadcf59329c6f0f8978cfa1810dab147e0b67f241a39c965c4904459fcc98c27","impliedFormat":1},{"version":"ab82804a14454734010dcdcd43f564ff7b0389bee4c5692eec76ff5b30d4cf66","impliedFormat":1},{"version":"15fe687c59d62741b4494d5e623d497d55eb38966ecf5bea7f36e48fc3fbe15e","impliedFormat":1},{"version":"2c3b8be03577c98530ef9cb1a76e2c812636a871f367e9edf4c5f3ce702b77f8","affectsGlobalScope":true,"impliedFormat":1},{"version":"f874ea4d0091b0a44362a5f74d26caab2e66dec306c2bf7e8965f5106e784c3b","impliedFormat":1},{"version":"caaf6bf4dd0a3f88b50670f5786141b209edb54ba17eb6268c2d28919c813606","affectsGlobalScope":true,"impliedFormat":1},{"version":"bc3d87d494138b037f883840bef538bc25c1432fcd9afb0b71e438319e08780e","affectsGlobalScope":true,"impliedFormat":1},{"version":"f2f23fe34b735887db1d5597714ae37a6ffae530cafd6908c9d79d485667c956","impliedFormat":1},{"version":"5bba0e6cd8375fd37047e99a080d1bd9a808c95ecb7f3043e3adc125196f6607","impliedFormat":1},{"version":"1ba59c8bbeed2cb75b239bb12041582fa3e8ef32f8d0bd0ec802e38442d3f317","impliedFormat":1},{"version":"bae8d023ef6b23df7da26f51cea44321f95817c190342a36882e93b80d07a960","impliedFormat":1},{"version":"26a770cec4bd2e7dbba95c6e536390fffe83c6268b78974a93727903b515c4e7","impliedFormat":1}],"root":[65,66,[68,71]],"options":{"allowSyntheticDefaultImports":true,"composite":true,"declaration":true,"declarationMap":true,"esModuleInterop":true,"module":1,"outDir":"./dist","rootDir":"./src","skipLibCheck":true,"sourceMap":true,"strict":true,"target":10},"referencedMap":[[74,1],[72,2],[197,3],[214,2],[408,4],[407,5],[218,6],[219,7],[356,6],[357,8],[338,9],[339,10],[222,11],[223,12],[293,13],[294,14],[267,6],[268,15],[261,6],[262,16],[353,17],[351,18],[352,2],[367,19],[368,20],[237,21],[238,22],[369,23],[370,24],[371,25],[372,26],[229,27],[230,28],[355,29],[354,30],[340,6],[341,31],[233,32],[234,33],[257,2],[258,34],[375,35],[373,36],[374,37],[376,38],[377,39],[380,40],[378,41],[381,18],[379,42],[382,43],[385,44],[383,45],[384,46],[386,47],[235,27],[236,48],[361,49],[358,50],[359,51],[360,2],[336,52],[337,53],[281,54],[280,55],[278,56],[277,57],[279,58],[388,59],[387,60],[390,61],[389,62],[266,63],[265,6],[244,64],[242,65],[241,11],[243,66],[393,67],[397,68],[391,69],[392,70],[394,67],[395,67],[396,67],[283,71],[282,11],[299,72],[297,73],[298,18],[295,74],[296,75],[232,76],[231,6],[289,77],[220,6],[221,78],[288,79],[326,80],[329,81],[327,82],[328,83],[240,84],[239,6],[331,85],[330,11],[309,86],[308,6],[264,87],[263,6],[335,88],[334,89],[303,90],[302,91],[300,92],[301,93],[292,94],[291,95],[290,96],[399,97],[398,98],[316,99],[315,100],[314,101],[363,102],[362,2],[307,103],[306,104],[304,105],[305,106],[285,107],[284,11],[228,108],[227,109],[226,110],[225,111],[224,112],[320,113],[319,114],[250,115],[249,11],[254,116],[253,117],[318,118],[317,6],[364,2],[366,119],[365,2],[323,120],[322,121],[321,122],[401,123],[400,124],[403,125],[402,126],[349,127],[350,128],[348,129],[287,130],[286,2],[333,131],[332,132],[260,133],[259,6],[311,134],[310,6],[217,135],[216,2],[270,136],[271,137],[276,138],[269,139],[273,140],[272,141],[274,142],[275,143],[325,144],[324,11],[256,145],[255,11],[406,146],[405,147],[404,148],[343,149],[342,6],[313,150],[312,6],[248,151],[246,152],[245,11],[247,153],[345,154],[344,6],[252,155],[251,6],[347,156],[346,6],[77,157],[73,1],[75,158],[76,1],[183,159],[184,160],[189,161],[182,162],[191,163],[192,164],[200,165],[196,166],[195,167],[201,168],[193,2],[188,169],[206,170],[208,171],[209,2],[202,2],[210,172],[211,2],[212,173],[213,174],[414,175],[194,2],[415,2],[416,171],[203,2],[417,2],[190,2],[418,164],[129,176],[130,176],[131,177],[83,178],[132,179],[133,180],[134,181],[78,2],[81,182],[79,2],[80,2],[135,183],[136,184],[137,185],[138,186],[139,187],[140,188],[141,188],[142,189],[143,190],[144,191],[145,192],[84,2],[82,2],[146,193],[147,194],[148,195],[181,196],[149,197],[150,198],[151,199],[152,200],[153,201],[154,202],[155,203],[156,204],[157,205],[158,206],[159,206],[160,207],[161,2],[162,208],[163,209],[165,210],[164,211],[166,212],[167,213],[168,214],[169,215],[170,216],[171,217],[172,218],[173,219],[174,220],[175,221],[176,222],[177,223],[178,224],[85,2],[86,2],[87,2],[126,225],[127,2],[128,2],[179,226],[180,227],[419,2],[186,2],[187,2],[423,228],[420,2],[422,229],[424,2],[425,2],[450,230],[451,231],[427,232],[430,233],[448,230],[449,230],[439,230],[438,234],[436,230],[431,230],[444,230],[442,230],[446,230],[426,230],[443,230],[447,230],[432,230],[433,230],[445,230],[428,230],[434,230],[435,230],[437,230],[441,230],[452,235],[440,230],[429,230],[465,236],[464,2],[459,235],[461,237],[460,235],[453,235],[454,235],[456,235],[458,235],[462,237],[463,237],[455,237],[457,237],[185,238],[466,239],[205,240],[204,241],[467,162],[469,242],[468,243],[470,2],[472,244],[471,2],[207,2],[473,2],[475,2],[474,2],[476,2],[477,2],[478,245],[479,2],[480,246],[63,2],[88,2],[215,2],[421,2],[67,2],[199,247],[198,248],[413,249],[410,250],[411,251],[412,2],[64,252],[409,253],[61,2],[62,2],[12,2],[11,2],[2,2],[13,2],[14,2],[15,2],[16,2],[17,2],[18,2],[19,2],[20,2],[3,2],[21,2],[22,2],[4,2],[23,2],[27,2],[24,2],[25,2],[26,2],[28,2],[29,2],[30,2],[5,2],[31,2],[32,2],[33,2],[34,2],[6,2],[38,2],[35,2],[36,2],[37,2],[39,2],[7,2],[40,2],[45,2],[46,2],[41,2],[42,2],[43,2],[44,2],[8,2],[50,2],[47,2],[48,2],[49,2],[51,2],[9,2],[52,2],[53,2],[54,2],[56,2],[55,2],[57,2],[58,2],[10,2],[59,2],[1,2],[60,2],[104,254],[114,255],[103,254],[124,256],[95,257],[94,258],[123,164],[117,259],[122,260],[97,261],[111,262],[96,263],[120,264],[92,265],[91,164],[121,266],[93,267],[98,268],[99,2],[102,268],[89,2],[125,269],[115,270],[106,271],[107,272],[109,273],[105,274],[108,275],[118,164],[100,276],[101,277],[110,278],[90,279],[113,270],[112,268],[116,2],[119,280],[65,281],[66,2],[69,282],[70,283],[68,284],[71,285]],"latestChangedDtsFile":"./dist/index.d.ts","version":"5.9.3"} \ No newline at end of file diff --git a/src/documentdb/ClusterSession.ts b/src/documentdb/ClusterSession.ts index cfa065196..27ae9b8e4 100644 --- a/src/documentdb/ClusterSession.ts +++ b/src/documentdb/ClusterSession.ts @@ -3,13 +3,16 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { + SchemaAnalyzer, + getPropertyNamesAtLevel, + type FieldEntry, + type JSONSchema, +} from '@vscode-documentdb/schema-analyzer'; import * as l10n from '@vscode/l10n'; import { EJSON } from 'bson'; import { ObjectId, type Document, type Filter, type WithId } from 'mongodb'; import { ext } from '../extensionVariables'; -import { type JSONSchema } from '../utils/json/JSONSchema'; -import { SchemaAnalyzer, getPropertyNamesAtLevel } from '../utils/json/data-api/SchemaAnalyzer'; -import { type FieldEntry } from '../utils/json/data-api/autocomplete/getKnownFields'; import { getDataAtPath } from '../utils/slickgrid/mongo/toSlickGridTable'; import { toSlickGridTree, type TreeData } from '../utils/slickgrid/mongo/toSlickGridTree'; import { ClustersClient, type FindQueryParams } from './ClustersClient'; diff --git a/src/utils/json/data-api/autocomplete/generateDescriptions.test.ts b/src/utils/json/data-api/autocomplete/generateDescriptions.test.ts index 7500cc95c..32a103431 100644 --- a/src/utils/json/data-api/autocomplete/generateDescriptions.test.ts +++ b/src/utils/json/data-api/autocomplete/generateDescriptions.test.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { type JSONSchema } from '../../JSONSchema'; +import { type JSONSchema } from '@vscode-documentdb/schema-analyzer'; import { generateDescriptions } from './generateDescriptions'; describe('generateDescriptions', () => { diff --git a/src/utils/json/data-api/autocomplete/generateDescriptions.ts b/src/utils/json/data-api/autocomplete/generateDescriptions.ts index 261549bc2..2f4f28867 100644 --- a/src/utils/json/data-api/autocomplete/generateDescriptions.ts +++ b/src/utils/json/data-api/autocomplete/generateDescriptions.ts @@ -3,9 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { BSONTypes, type JSONSchema } from '@vscode-documentdb/schema-analyzer'; import Denque from 'denque'; -import { type JSONSchema } from '../../JSONSchema'; -import { BSONTypes } from '../BSONTypes'; /** * Work item for BFS traversal of the schema tree. diff --git a/src/utils/json/data-api/autocomplete/generateMongoFindJsonSchema.ts b/src/utils/json/data-api/autocomplete/generateMongoFindJsonSchema.ts index 0f0fa7bbe..edaa8a64a 100644 --- a/src/utils/json/data-api/autocomplete/generateMongoFindJsonSchema.ts +++ b/src/utils/json/data-api/autocomplete/generateMongoFindJsonSchema.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { type FieldEntry } from './getKnownFields'; +import { type FieldEntry } from '@vscode-documentdb/schema-analyzer'; /** * Generates a JSON schema for MongoDB find filter queries. diff --git a/src/utils/json/data-api/autocomplete/getKnownFields.test.ts b/src/utils/json/data-api/autocomplete/getKnownFields.test.ts index 351dab7ff..d0680e2f3 100644 --- a/src/utils/json/data-api/autocomplete/getKnownFields.test.ts +++ b/src/utils/json/data-api/autocomplete/getKnownFields.test.ts @@ -3,9 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { type FieldEntry, getKnownFields, SchemaAnalyzer } from '@vscode-documentdb/schema-analyzer'; import { ObjectId } from 'bson'; -import { SchemaAnalyzer } from '../SchemaAnalyzer'; -import { getKnownFields, type FieldEntry } from './getKnownFields'; describe('getKnownFields', () => { it('returns bsonType for primitive fields', () => { diff --git a/src/utils/json/data-api/autocomplete/toFieldCompletionItems.test.ts b/src/utils/json/data-api/autocomplete/toFieldCompletionItems.test.ts index 307b0c9d5..947b90629 100644 --- a/src/utils/json/data-api/autocomplete/toFieldCompletionItems.test.ts +++ b/src/utils/json/data-api/autocomplete/toFieldCompletionItems.test.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { type FieldEntry } from './getKnownFields'; +import { type FieldEntry } from '@vscode-documentdb/schema-analyzer'; import { toFieldCompletionItems } from './toFieldCompletionItems'; describe('toFieldCompletionItems', () => { diff --git a/src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts b/src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts index 03d1a9a89..4998dad64 100644 --- a/src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts +++ b/src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts @@ -3,8 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { BSONTypes } from '../BSONTypes'; -import { type FieldEntry } from './getKnownFields'; +import { BSONTypes, type FieldEntry } from '@vscode-documentdb/schema-analyzer'; /** * Completion-ready data for a single field entry. diff --git a/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.test.ts b/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.test.ts index 256d59a27..db2ed0176 100644 --- a/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.test.ts +++ b/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.test.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { type JSONSchema } from '../../JSONSchema'; +import { type JSONSchema } from '@vscode-documentdb/schema-analyzer'; import { toTypeScriptDefinition } from './toTypeScriptDefinition'; describe('toTypeScriptDefinition', () => { diff --git a/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.ts b/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.ts index 588eb6987..559162fc0 100644 --- a/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.ts +++ b/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.ts @@ -3,8 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { type JSONSchema } from '../../JSONSchema'; -import { BSONTypes } from '../BSONTypes'; +import { BSONTypes, type JSONSchema } from '@vscode-documentdb/schema-analyzer'; /** * Maps a BSON type string to the corresponding TypeScript type representation. diff --git a/src/utils/slickgrid/mongo/toSlickGridTable.ts b/src/utils/slickgrid/mongo/toSlickGridTable.ts index ece8d02e6..5deb51fe0 100644 --- a/src/utils/slickgrid/mongo/toSlickGridTable.ts +++ b/src/utils/slickgrid/mongo/toSlickGridTable.ts @@ -3,11 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { BSONTypes, valueToDisplayString } from '@vscode-documentdb/schema-analyzer'; import { EJSON } from 'bson'; import { type Document, type WithId } from 'mongodb'; import { type TableDataEntry } from '../../../documentdb/ClusterSession'; -import { BSONTypes } from '../../json/data-api/BSONTypes'; -import { valueToDisplayString } from '../../json/data-api/ValueFormatters'; /** * Extracts data from a list of MongoDB documents at a specified path. diff --git a/src/utils/slickgrid/mongo/toSlickGridTree.ts b/src/utils/slickgrid/mongo/toSlickGridTree.ts index 1db9e979d..849ad42b6 100644 --- a/src/utils/slickgrid/mongo/toSlickGridTree.ts +++ b/src/utils/slickgrid/mongo/toSlickGridTree.ts @@ -3,9 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { BSONTypes, valueToDisplayString } from '@vscode-documentdb/schema-analyzer'; import { type Document, type ObjectId, type WithId } from 'mongodb'; -import { BSONTypes } from '../../json/data-api/BSONTypes'; -import { valueToDisplayString } from '../../json/data-api/ValueFormatters'; /** * The data structure for a single node entry in the tree data structure for SlickGrid. diff --git a/src/webviews/documentdb/collectionView/collectionViewRouter.ts b/src/webviews/documentdb/collectionView/collectionViewRouter.ts index 0e4b6a81b..62ef2f476 100644 --- a/src/webviews/documentdb/collectionView/collectionViewRouter.ts +++ b/src/webviews/documentdb/collectionView/collectionViewRouter.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { callWithTelemetryAndErrorHandling, type IActionContext } from '@microsoft/vscode-azext-utils'; +import { type FieldEntry } from '@vscode-documentdb/schema-analyzer'; import * as fs from 'fs'; import { type Document } from 'mongodb'; import * as path from 'path'; @@ -12,7 +13,6 @@ import { type JSONSchema } from 'vscode-json-languageservice'; import { z } from 'zod'; import { ClusterSession } from '../../../documentdb/ClusterSession'; import { getConfirmationAsInSettings } from '../../../utils/dialogs/getConfirmation'; -import { type FieldEntry } from '../../../utils/json/data-api/autocomplete/getKnownFields'; import { publicProcedureWithTelemetry, router, type WithTelemetry } from '../../api/extension-server/trpc'; import * as l10n from '@vscode/l10n'; diff --git a/tsconfig.json b/tsconfig.json index 894220ad0..ae69b6474 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -30,5 +30,6 @@ ] */ }, - "exclude": ["node_modules", ".vscode-test"] + "exclude": ["node_modules", ".vscode-test", "packages/*/dist"], + "references": [{ "path": "packages/schema-analyzer" }] } From 2fec69db4cccedc13b8afef0dfb4855fc940bb68 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Feb 2026 11:36:38 +0100 Subject: [PATCH 014/128] docs: add README and bump schema-analyzer to v1.0.0 --- packages/schema-analyzer/README.md | 43 +++++++++++++++++++++++++++ packages/schema-analyzer/package.json | 2 +- 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 packages/schema-analyzer/README.md diff --git a/packages/schema-analyzer/README.md b/packages/schema-analyzer/README.md new file mode 100644 index 000000000..145611fe1 --- /dev/null +++ b/packages/schema-analyzer/README.md @@ -0,0 +1,43 @@ +# @vscode-documentdb/schema-analyzer + +Incremental JSON Schema analyzer for MongoDB and Azure Cosmos DB documents. Processes documents one at a time (or in batches) and produces an extended JSON Schema with statistical metadata — field occurrence counts, BSON type distributions, min/max values, and array length stats. + +> **Note:** This package is not yet published to npm. We plan to publish it once the API stabilizes. For now, it is consumed internally via npm workspaces within the [vscode-documentdb](https://github.com/microsoft/vscode-documentdb) repository. + +## Overview + +The `SchemaAnalyzer` incrementally builds a JSON Schema by inspecting MongoDB/DocumentDB documents. It is designed for scenarios where documents arrive over time (streaming, pagination) and the schema needs to evolve as new documents are observed. + +Key capabilities: + +- **Incremental analysis** — add documents one at a time or in batches; the schema updates in place. +- **BSON type awareness** — recognizes all MongoDB BSON types (`ObjectId`, `Decimal128`, `Binary`, `UUID`, etc.) and annotates them with `x-bsonType`. +- **Statistical extensions** — tracks field occurrence (`x-occurrence`), type frequency (`x-typeOccurrence`), min/max values, string lengths, array sizes, and document counts (`x-documentsInspected`). +- **Known fields extraction** — derives a flat list of known field paths with their types and occurrence probabilities, useful for autocomplete and UI rendering. +- **Version tracking & caching** — a monotonic version counter enables efficient cache invalidation for derived data like `getKnownFields()`. + +## Usage + +```typescript +import { SchemaAnalyzer } from '@vscode-documentdb/schema-analyzer'; + +// Create an analyzer and feed it documents +const analyzer = new SchemaAnalyzer(); +analyzer.addDocument(doc1); +analyzer.addDocuments([doc2, doc3, doc4]); + +// Get the JSON Schema with statistical extensions +const schema = analyzer.getSchema(); + +// Get a flat list of known fields (cached, version-aware) +const fields = analyzer.getKnownFields(); +``` + +## Requirements + +- **Node.js** ≥ 18 +- **mongodb** driver ≥ 6.0.0 (peer dependency) + +## License + +[MIT](../../LICENSE.md) diff --git a/packages/schema-analyzer/package.json b/packages/schema-analyzer/package.json index f5b10840b..ab9c3f5cd 100644 --- a/packages/schema-analyzer/package.json +++ b/packages/schema-analyzer/package.json @@ -1,6 +1,6 @@ { "name": "@vscode-documentdb/schema-analyzer", - "version": "0.1.0", + "version": "1.0.0", "description": "Incremental JSON Schema analyzer for MongoDB/DocumentDB documents with statistical extensions", "main": "dist/index.js", "types": "dist/index.d.ts", From a667c35275ed9aff703f930af1009ca9abd9107c Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Feb 2026 11:55:17 +0100 Subject: [PATCH 015/128] build: add prebuild and prejesttest scripts for workspace package builds --- .github/workflows/main.yml | 3 +++ package.json | 2 ++ 2 files changed, 5 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ac02668fb..7ea04b6ef 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -55,6 +55,9 @@ jobs: - name: 📦 Install Dependencies (npm ci) run: npm ci --prefer-offline --no-audit --no-fund --progress=false --verbose + - name: 🔨 Build Workspace Packages + run: npm run build --workspaces --if-present + - name: 🌐 Check Localization Files run: npm run l10n:check diff --git a/package.json b/package.json index 887ba0ecd..69fc03a84 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "onUri" ], "scripts": { + "prebuild": "npm run build --workspaces --if-present", "build": "tsc", "clean": "git clean -dfx", "compile": "tsc -watch", @@ -73,6 +74,7 @@ "prettier-fix": "prettier -w \"(src|test|l10n|grammar|docs|packages)/**/*.@(js|ts|jsx|tsx|json)\" \"./*.@(js|ts|jsx|tsx|json)\"", "pretest": "npm run build", "test": "vscode-test", + "prejesttest": "npm run build --workspaces --if-present", "jesttest": "jest", "update-grammar": "antlr4ts -visitor ./grammar/mongo.g4 -o src/documentdb/grammar", "webpack-dev": "rimraf ./dist && npm run webpack-dev-ext && npm run webpack-dev-wv", From cbaa57390b6bf3c69f874abb23292880fb7f44da Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Feb 2026 11:55:25 +0100 Subject: [PATCH 016/128] chore: bump schema-analyzer version to 1.0.0 in package-lock.json --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 2a0a6f451..06ce802e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22220,7 +22220,7 @@ }, "packages/schema-analyzer": { "name": "@vscode-documentdb/schema-analyzer", - "version": "0.1.0", + "version": "1.0.0", "license": "MIT", "dependencies": { "denque": "~2.1.0" From f1d006d27b58325fbedb6db46316a5783efee035 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Feb 2026 12:20:49 +0100 Subject: [PATCH 017/128] Refactor code structure for improved readability and maintainability --- .gitignore | 1 + package.json | 2 +- packages/schema-analyzer/package.json | 2 +- packages/schema-analyzer/tsconfig.tsbuildinfo | 1 - 4 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 packages/schema-analyzer/tsconfig.tsbuildinfo diff --git a/.gitignore b/.gitignore index a234ba0aa..f8c691f1e 100644 --- a/.gitignore +++ b/.gitignore @@ -274,6 +274,7 @@ dist stats.json *.tgz *.zip +*.tsbuildinfo # Scrapbooks *.mongo diff --git a/package.json b/package.json index 69fc03a84..5071f6698 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "scripts": { "prebuild": "npm run build --workspaces --if-present", "build": "tsc", - "clean": "git clean -dfx", + "clean": "rimraf out dist coverage && npm run clean --workspaces --if-present", "compile": "tsc -watch", "package": "run-script-os", "package:win32": "npm run webpack-prod && cd dist && npm pkg delete \"scripts.vscode:prepublish\" && npx vsce package --no-dependencies --out ../%npm_package_name%-%npm_package_version%.vsix", diff --git a/packages/schema-analyzer/package.json b/packages/schema-analyzer/package.json index ab9c3f5cd..78a54cc65 100644 --- a/packages/schema-analyzer/package.json +++ b/packages/schema-analyzer/package.json @@ -9,7 +9,7 @@ ], "scripts": { "build": "tsc -p .", - "clean": "rimraf dist", + "clean": "rimraf dist tsconfig.tsbuildinfo", "test": "jest --config jest.config.js" }, "repository": { diff --git a/packages/schema-analyzer/tsconfig.tsbuildinfo b/packages/schema-analyzer/tsconfig.tsbuildinfo deleted file mode 100644 index bfaffb0b6..000000000 --- a/packages/schema-analyzer/tsconfig.tsbuildinfo +++ /dev/null @@ -1 +0,0 @@ -{"fileNames":["../../node_modules/typescript/lib/lib.es5.d.ts","../../node_modules/typescript/lib/lib.es2015.d.ts","../../node_modules/typescript/lib/lib.es2016.d.ts","../../node_modules/typescript/lib/lib.es2017.d.ts","../../node_modules/typescript/lib/lib.es2018.d.ts","../../node_modules/typescript/lib/lib.es2019.d.ts","../../node_modules/typescript/lib/lib.es2020.d.ts","../../node_modules/typescript/lib/lib.es2021.d.ts","../../node_modules/typescript/lib/lib.es2022.d.ts","../../node_modules/typescript/lib/lib.es2023.d.ts","../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../node_modules/typescript/lib/lib.es2016.intl.d.ts","../../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../node_modules/typescript/lib/lib.es2017.date.d.ts","../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../node_modules/typescript/lib/lib.es2021.promise.d.ts","../../node_modules/typescript/lib/lib.es2021.string.d.ts","../../node_modules/typescript/lib/lib.es2021.weakref.d.ts","../../node_modules/typescript/lib/lib.es2021.intl.d.ts","../../node_modules/typescript/lib/lib.es2022.array.d.ts","../../node_modules/typescript/lib/lib.es2022.error.d.ts","../../node_modules/typescript/lib/lib.es2022.intl.d.ts","../../node_modules/typescript/lib/lib.es2022.object.d.ts","../../node_modules/typescript/lib/lib.es2022.string.d.ts","../../node_modules/typescript/lib/lib.es2022.regexp.d.ts","../../node_modules/typescript/lib/lib.es2023.array.d.ts","../../node_modules/typescript/lib/lib.es2023.collection.d.ts","../../node_modules/typescript/lib/lib.es2023.intl.d.ts","../../node_modules/typescript/lib/lib.esnext.disposable.d.ts","../../node_modules/typescript/lib/lib.decorators.d.ts","../../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../../node_modules/bson/bson.d.ts","../../node_modules/mongodb/mongodb.d.ts","./src/BSONTypes.ts","./src/JSONSchema.ts","../../node_modules/denque/index.d.ts","./src/getKnownFields.ts","./src/SchemaAnalyzer.ts","./src/ValueFormatters.ts","./src/index.ts","../../node_modules/@babel/types/lib/index.d.ts","../../node_modules/@types/babel__generator/index.d.ts","../../node_modules/@babel/parser/typings/babel-parser.d.ts","../../node_modules/@types/babel__template/index.d.ts","../../node_modules/@types/babel__traverse/index.d.ts","../../node_modules/@types/babel__core/index.d.ts","../../node_modules/@types/node/compatibility/disposable.d.ts","../../node_modules/@types/node/compatibility/indexable.d.ts","../../node_modules/@types/node/compatibility/iterators.d.ts","../../node_modules/@types/node/compatibility/index.d.ts","../../node_modules/@types/node/globals.typedarray.d.ts","../../node_modules/@types/node/buffer.buffer.d.ts","../../node_modules/@types/node/globals.d.ts","../../node_modules/@types/node/web-globals/abortcontroller.d.ts","../../node_modules/@types/node/web-globals/domexception.d.ts","../../node_modules/@types/node/web-globals/events.d.ts","../../node_modules/buffer/index.d.ts","../../node_modules/undici-types/header.d.ts","../../node_modules/undici-types/readable.d.ts","../../node_modules/undici-types/file.d.ts","../../node_modules/undici-types/fetch.d.ts","../../node_modules/undici-types/formdata.d.ts","../../node_modules/undici-types/connector.d.ts","../../node_modules/undici-types/client.d.ts","../../node_modules/undici-types/errors.d.ts","../../node_modules/undici-types/dispatcher.d.ts","../../node_modules/undici-types/global-dispatcher.d.ts","../../node_modules/undici-types/global-origin.d.ts","../../node_modules/undici-types/pool-stats.d.ts","../../node_modules/undici-types/pool.d.ts","../../node_modules/undici-types/handlers.d.ts","../../node_modules/undici-types/balanced-pool.d.ts","../../node_modules/undici-types/agent.d.ts","../../node_modules/undici-types/mock-interceptor.d.ts","../../node_modules/undici-types/mock-agent.d.ts","../../node_modules/undici-types/mock-client.d.ts","../../node_modules/undici-types/mock-pool.d.ts","../../node_modules/undici-types/mock-errors.d.ts","../../node_modules/undici-types/proxy-agent.d.ts","../../node_modules/undici-types/env-http-proxy-agent.d.ts","../../node_modules/undici-types/retry-handler.d.ts","../../node_modules/undici-types/retry-agent.d.ts","../../node_modules/undici-types/api.d.ts","../../node_modules/undici-types/interceptors.d.ts","../../node_modules/undici-types/util.d.ts","../../node_modules/undici-types/cookies.d.ts","../../node_modules/undici-types/patch.d.ts","../../node_modules/undici-types/websocket.d.ts","../../node_modules/undici-types/eventsource.d.ts","../../node_modules/undici-types/filereader.d.ts","../../node_modules/undici-types/diagnostics-channel.d.ts","../../node_modules/undici-types/content-type.d.ts","../../node_modules/undici-types/cache.d.ts","../../node_modules/undici-types/index.d.ts","../../node_modules/@types/node/web-globals/fetch.d.ts","../../node_modules/@types/node/web-globals/navigator.d.ts","../../node_modules/@types/node/web-globals/storage.d.ts","../../node_modules/@types/node/assert.d.ts","../../node_modules/@types/node/assert/strict.d.ts","../../node_modules/@types/node/async_hooks.d.ts","../../node_modules/@types/node/buffer.d.ts","../../node_modules/@types/node/child_process.d.ts","../../node_modules/@types/node/cluster.d.ts","../../node_modules/@types/node/console.d.ts","../../node_modules/@types/node/constants.d.ts","../../node_modules/@types/node/crypto.d.ts","../../node_modules/@types/node/dgram.d.ts","../../node_modules/@types/node/diagnostics_channel.d.ts","../../node_modules/@types/node/dns.d.ts","../../node_modules/@types/node/dns/promises.d.ts","../../node_modules/@types/node/domain.d.ts","../../node_modules/@types/node/events.d.ts","../../node_modules/@types/node/fs.d.ts","../../node_modules/@types/node/fs/promises.d.ts","../../node_modules/@types/node/http.d.ts","../../node_modules/@types/node/http2.d.ts","../../node_modules/@types/node/https.d.ts","../../node_modules/@types/node/inspector.generated.d.ts","../../node_modules/@types/node/module.d.ts","../../node_modules/@types/node/net.d.ts","../../node_modules/@types/node/os.d.ts","../../node_modules/@types/node/path.d.ts","../../node_modules/@types/node/perf_hooks.d.ts","../../node_modules/@types/node/process.d.ts","../../node_modules/@types/node/punycode.d.ts","../../node_modules/@types/node/querystring.d.ts","../../node_modules/@types/node/readline.d.ts","../../node_modules/@types/node/readline/promises.d.ts","../../node_modules/@types/node/repl.d.ts","../../node_modules/@types/node/sea.d.ts","../../node_modules/@types/node/sqlite.d.ts","../../node_modules/@types/node/stream.d.ts","../../node_modules/@types/node/stream/promises.d.ts","../../node_modules/@types/node/stream/consumers.d.ts","../../node_modules/@types/node/stream/web.d.ts","../../node_modules/@types/node/string_decoder.d.ts","../../node_modules/@types/node/test.d.ts","../../node_modules/@types/node/timers.d.ts","../../node_modules/@types/node/timers/promises.d.ts","../../node_modules/@types/node/tls.d.ts","../../node_modules/@types/node/trace_events.d.ts","../../node_modules/@types/node/tty.d.ts","../../node_modules/@types/node/url.d.ts","../../node_modules/@types/node/util.d.ts","../../node_modules/@types/node/v8.d.ts","../../node_modules/@types/node/vm.d.ts","../../node_modules/@types/node/wasi.d.ts","../../node_modules/@types/node/worker_threads.d.ts","../../node_modules/@types/node/zlib.d.ts","../../node_modules/@types/node/index.d.ts","../../node_modules/@types/connect/index.d.ts","../../node_modules/@types/body-parser/index.d.ts","../../node_modules/@types/bonjour/index.d.ts","../../node_modules/@types/send/index.d.ts","../../node_modules/@types/qs/index.d.ts","../../node_modules/@types/range-parser/index.d.ts","../../node_modules/@types/express-serve-static-core/index.d.ts","../../node_modules/@types/connect-history-api-fallback/index.d.ts","../../node_modules/@types/ms/index.d.ts","../../node_modules/@types/debug/index.d.ts","../../node_modules/@types/documentdb/index.d.ts","../../node_modules/@types/estree/index.d.ts","../../node_modules/@types/json-schema/index.d.ts","../../node_modules/@types/eslint/use-at-your-own-risk.d.ts","../../node_modules/@types/eslint/index.d.ts","../../node_modules/@eslint/core/dist/esm/types.d.ts","../../node_modules/eslint/lib/types/use-at-your-own-risk.d.ts","../../node_modules/eslint/lib/types/index.d.ts","../../node_modules/@types/eslint-scope/index.d.ts","../../node_modules/@types/estree-jsx/index.d.ts","../../node_modules/@types/http-errors/index.d.ts","../../node_modules/@types/mime/index.d.ts","../../node_modules/@types/serve-static/node_modules/@types/send/index.d.ts","../../node_modules/@types/serve-static/index.d.ts","../../node_modules/@types/express/index.d.ts","../../node_modules/@types/unist/index.d.ts","../../node_modules/@types/hast/index.d.ts","../../node_modules/@types/http-cache-semantics/index.d.ts","../../node_modules/@types/http-proxy/index.d.ts","../../node_modules/@types/istanbul-lib-coverage/index.d.ts","../../node_modules/@types/istanbul-lib-report/index.d.ts","../../node_modules/@types/istanbul-reports/index.d.ts","../../node_modules/@jest/expect-utils/build/index.d.ts","../../node_modules/chalk/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/symbols/symbols.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/symbols/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/any/any.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/any/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/mapped/mapped-key.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/mapped/mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/async-iterator/async-iterator.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/async-iterator/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/readonly/readonly.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/readonly/readonly-from-mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/readonly/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/readonly-optional/readonly-optional.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/readonly-optional/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/constructor/constructor.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/constructor/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/literal/literal.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/literal/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/enum/enum.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/enum/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/function/function.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/function/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/computed/computed.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/computed/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/never/never.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/never/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/intersect/intersect-type.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/intersect/intersect-evaluated.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/intersect/intersect.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/intersect/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/union/union-type.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/union/union-evaluated.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/union/union.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/union/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/recursive/recursive.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/recursive/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/unsafe/unsafe.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/unsafe/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/ref/ref.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/ref/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/tuple/tuple.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/tuple/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/error/error.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/error/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/string/string.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/string/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/boolean/boolean.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/boolean/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/number/number.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/number/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/integer/integer.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/integer/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/bigint/bigint.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/bigint/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/template-literal/parse.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/template-literal/finite.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/template-literal/generate.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/template-literal/syntax.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/template-literal/pattern.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/template-literal/template-literal.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/template-literal/union.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/template-literal/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/indexed/indexed-property-keys.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/indexed/indexed-from-mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/indexed/indexed.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/indexed/indexed-from-mapped-key.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/indexed/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/iterator/iterator.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/iterator/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/promise/promise.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/promise/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/sets/set.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/sets/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/mapped/mapped.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/mapped/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/optional/optional.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/optional/optional-from-mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/optional/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/awaited/awaited.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/awaited/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/keyof/keyof-property-keys.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/keyof/keyof.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/keyof/keyof-from-mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/keyof/keyof-property-entries.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/keyof/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/omit/omit-from-mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/omit/omit.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/omit/omit-from-mapped-key.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/omit/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/pick/pick-from-mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/pick/pick.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/pick/pick-from-mapped-key.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/pick/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/null/null.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/null/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/symbol/symbol.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/symbol/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/undefined/undefined.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/undefined/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/partial/partial.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/partial/partial-from-mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/partial/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/regexp/regexp.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/regexp/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/record/record.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/record/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/required/required.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/required/required-from-mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/required/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/transform/transform.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/transform/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/module/compute.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/module/infer.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/module/module.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/module/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/not/not.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/not/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/static/static.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/static/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/object/object.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/object/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/helpers/helpers.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/helpers/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/array/array.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/array/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/date/date.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/date/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/uint8array/uint8array.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/uint8array/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/unknown/unknown.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/unknown/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/void/void.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/void/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/schema/schema.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/schema/anyschema.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/schema/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/clone/type.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/clone/value.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/clone/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/create/type.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/create/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/argument/argument.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/argument/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/guard/kind.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/guard/type.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/guard/value.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/guard/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/patterns/patterns.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/patterns/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/registry/format.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/registry/type.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/registry/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/composite/composite.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/composite/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/const/const.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/const/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/constructor-parameters/constructor-parameters.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/constructor-parameters/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/exclude/exclude-from-template-literal.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/exclude/exclude.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/exclude/exclude-from-mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/exclude/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/extends/extends-check.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/extends/extends-from-mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/extends/extends.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/extends/extends-from-mapped-key.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/extends/extends-undefined.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/extends/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/extract/extract-from-template-literal.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/extract/extract.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/extract/extract-from-mapped-result.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/extract/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/instance-type/instance-type.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/instance-type/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/instantiate/instantiate.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/instantiate/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/intrinsic/intrinsic-from-mapped-key.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/intrinsic/intrinsic.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/intrinsic/capitalize.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/intrinsic/lowercase.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/intrinsic/uncapitalize.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/intrinsic/uppercase.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/intrinsic/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/parameters/parameters.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/parameters/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/rest/rest.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/rest/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/return-type/return-type.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/return-type/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/type/json.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/type/javascript.d.ts","../../node_modules/@sinclair/typebox/build/cjs/type/type/index.d.ts","../../node_modules/@sinclair/typebox/build/cjs/index.d.ts","../../node_modules/@jest/schemas/build/index.d.ts","../../node_modules/pretty-format/build/index.d.ts","../../node_modules/jest-diff/build/index.d.ts","../../node_modules/jest-matcher-utils/build/index.d.ts","../../node_modules/jest-mock/build/index.d.ts","../../node_modules/expect/build/index.d.ts","../../node_modules/@types/jest/index.d.ts","../../node_modules/@types/json5/index.d.ts","../../node_modules/@types/mdast/index.d.ts","../../node_modules/@types/mocha/index.d.ts","../../node_modules/@types/node-forge/index.d.ts","../../node_modules/@types/normalize-package-data/index.d.ts","../../node_modules/@types/react/global.d.ts","../../node_modules/csstype/index.d.ts","../../node_modules/@types/react/index.d.ts","../../node_modules/@types/react-dom/index.d.ts","../../node_modules/@types/retry/index.d.ts","../../node_modules/@types/sarif/index.d.ts","../../node_modules/@types/semver/functions/inc.d.ts","../../node_modules/@types/semver/classes/semver.d.ts","../../node_modules/@types/semver/functions/parse.d.ts","../../node_modules/@types/semver/functions/valid.d.ts","../../node_modules/@types/semver/functions/clean.d.ts","../../node_modules/@types/semver/functions/diff.d.ts","../../node_modules/@types/semver/functions/major.d.ts","../../node_modules/@types/semver/functions/minor.d.ts","../../node_modules/@types/semver/functions/patch.d.ts","../../node_modules/@types/semver/functions/prerelease.d.ts","../../node_modules/@types/semver/functions/compare.d.ts","../../node_modules/@types/semver/functions/rcompare.d.ts","../../node_modules/@types/semver/functions/compare-loose.d.ts","../../node_modules/@types/semver/functions/compare-build.d.ts","../../node_modules/@types/semver/functions/sort.d.ts","../../node_modules/@types/semver/functions/rsort.d.ts","../../node_modules/@types/semver/functions/gt.d.ts","../../node_modules/@types/semver/functions/lt.d.ts","../../node_modules/@types/semver/functions/eq.d.ts","../../node_modules/@types/semver/functions/neq.d.ts","../../node_modules/@types/semver/functions/gte.d.ts","../../node_modules/@types/semver/functions/lte.d.ts","../../node_modules/@types/semver/functions/cmp.d.ts","../../node_modules/@types/semver/functions/coerce.d.ts","../../node_modules/@types/semver/classes/comparator.d.ts","../../node_modules/@types/semver/classes/range.d.ts","../../node_modules/@types/semver/functions/satisfies.d.ts","../../node_modules/@types/semver/ranges/max-satisfying.d.ts","../../node_modules/@types/semver/ranges/min-satisfying.d.ts","../../node_modules/@types/semver/ranges/to-comparators.d.ts","../../node_modules/@types/semver/ranges/min-version.d.ts","../../node_modules/@types/semver/ranges/valid.d.ts","../../node_modules/@types/semver/ranges/outside.d.ts","../../node_modules/@types/semver/ranges/gtr.d.ts","../../node_modules/@types/semver/ranges/ltr.d.ts","../../node_modules/@types/semver/ranges/intersects.d.ts","../../node_modules/@types/semver/ranges/simplify.d.ts","../../node_modules/@types/semver/ranges/subset.d.ts","../../node_modules/@types/semver/internals/identifiers.d.ts","../../node_modules/@types/semver/index.d.ts","../../node_modules/@types/serve-index/index.d.ts","../../node_modules/@types/sockjs/index.d.ts","../../node_modules/@types/sortablejs/plugins.d.ts","../../node_modules/@types/sortablejs/index.d.ts","../../node_modules/@types/stack-utils/index.d.ts","../../node_modules/@types/trusted-types/lib/index.d.ts","../../node_modules/@types/trusted-types/index.d.ts","../../node_modules/@types/uuid/index.d.ts","../../node_modules/@types/vscode/index.d.ts","../../node_modules/@types/vscode-webview/index.d.ts","../../node_modules/@types/webidl-conversions/index.d.ts","../../node_modules/@types/whatwg-url/index.d.ts","../../node_modules/@types/ws/index.d.ts","../../node_modules/@types/yargs-parser/index.d.ts","../../node_modules/@types/yargs/index.d.ts"],"fileIdsList":[[72,83,132],[83,132],[83,132,194],[83,132,407],[83,132,217,219,223,226,228,230,232,234,236,240,244,248,250,252,254,256,258,260,262,264,266,268,276,281,283,285,287,289,292,294,299,303,307,309,311,313,316,318,320,323,325,329,331,333,335,337,339,341,343,345,347,350,353,355,357,361,363,366,368,370,372,376,382,386,388,390,397,399,401,403,406],[83,132,217,350],[83,132,218],[83,132,356],[83,132,217,333,337,350],[83,132,338],[83,132,217,333,350],[83,132,222],[83,132,238,244,248,254,285,337,350],[83,132,293],[83,132,267],[83,132,261],[83,132,351,352],[83,132,350],[83,132,240,244,281,287,299,335,337,350],[83,132,367],[83,132,216,350],[83,132,237],[83,132,219,226,232,236,240,256,268,309,311,313,335,337,341,343,345,350],[83,132,369],[83,132,230,240,256,350],[83,132,371],[83,132,217,226,228,292,333,337,350],[83,132,229],[83,132,354],[83,132,348],[83,132,340],[83,132,217,232,350],[83,132,233],[83,132,257],[83,132,289,335,350,374],[83,132,276,350,374],[83,132,240,248,276,289,333,337,350,373,375],[83,132,373,374,375],[83,132,258,350],[83,132,232,289,335,337,350,379],[83,132,289,335,350,379],[83,132,248,289,333,337,350,378,380],[83,132,377,378,379,380,381],[83,132,289,335,350,384],[83,132,276,350,384],[83,132,240,248,276,289,333,337,350,383,385],[83,132,383,384,385],[83,132,235],[83,132,358,359,360],[83,132,217,219,223,226,230,232,236,238,240,244,248,250,252,254,256,260,262,264,266,268,276,283,285,289,292,309,311,313,318,320,325,329,331,335,339,341,343,345,347,350,357],[83,132,217,219,223,226,230,232,236,238,240,244,248,250,252,254,256,258,260,262,264,266,268,276,283,285,289,292,309,311,313,318,320,325,329,331,335,339,341,343,345,347,350,357],[83,132,240,335,350],[83,132,336],[83,132,277,278,279,280],[83,132,279,289,335,337,350],[83,132,277,281,289,335,350],[83,132,232,248,264,266,276,350],[83,132,238,240,244,248,250,254,256,277,278,280,289,335,337,339,350],[83,132,387],[83,132,230,240,350],[83,132,389],[83,132,223,226,228,230,236,244,248,256,283,285,292,320,335,339,345,350,357],[83,132,265],[83,132,241,242,243],[83,132,226,240,241,292,350],[83,132,240,241,350],[83,132,350,392],[83,132,391,392,393,394,395,396],[83,132,232,289,335,337,350,392],[83,132,232,248,276,289,350,391],[83,132,282],[83,132,295,296,297,298],[83,132,289,296,335,337,350],[83,132,244,248,250,256,287,335,337,339,350],[83,132,232,238,248,254,264,289,295,297,337,350],[83,132,231],[83,132,220,221,288],[83,132,217,335,350],[83,132,220,221,223,226,230,232,234,236,244,248,256,281,283,285,287,292,335,337,339,350],[83,132,223,226,230,234,236,238,240,244,248,254,256,281,283,292,294,299,303,307,316,320,323,325,335,337,339,350],[83,132,328],[83,132,223,226,230,234,236,244,248,250,254,256,283,292,320,333,335,337,339,350],[83,132,217,326,327,333,335,350],[83,132,239],[83,132,330],[83,132,308],[83,132,263],[83,132,334],[83,132,217,226,292,333,337,350],[83,132,300,301,302],[83,132,289,301,335,350],[83,132,289,301,335,337,350],[83,132,232,238,244,248,250,254,281,289,300,302,335,337,350],[83,132,290,291],[83,132,289,290,335],[83,132,217,289,291,337,350],[83,132,398],[83,132,236,240,256,350],[83,132,314,315],[83,132,289,314,335,337,350],[83,132,226,228,232,238,244,248,250,254,260,262,264,266,268,289,292,309,311,313,315,335,337,350],[83,132,362],[83,132,304,305,306],[83,132,289,305,335,350],[83,132,289,305,335,337,350],[83,132,232,238,244,248,250,254,281,289,304,306,335,337,350],[83,132,284],[83,132,227],[83,132,226,292,350],[83,132,224,225],[83,132,224,289,335],[83,132,217,225,289,337,350],[83,132,319],[83,132,217,219,232,234,240,248,260,262,264,266,276,318,333,335,337,350],[83,132,249],[83,132,253],[83,132,217,252,333,350],[83,132,317],[83,132,364,365],[83,132,321,322],[83,132,289,321,335,337,350],[83,132,226,228,232,238,244,248,250,254,260,262,264,266,268,289,292,309,311,313,322,335,337,350],[83,132,400],[83,132,244,248,256,350],[83,132,402],[83,132,236,240,350],[83,132,219,223,230,232,234,236,244,248,250,254,256,260,262,264,266,268,276,283,285,309,311,313,318,320,331,335,339,341,343,345,347,348],[83,132,348,349],[83,132,217],[83,132,286],[83,132,332],[83,132,223,226,230,234,236,240,244,248,250,252,254,256,283,285,292,320,325,329,331,335,337,339,350],[83,132,259],[83,132,310],[83,132,216],[83,132,232,248,258,260,262,264,266,268,269,276],[83,132,232,248,258,262,269,270,276,337],[83,132,269,270,271,272,273,274,275],[83,132,258],[83,132,258,276],[83,132,232,248,260,262,264,268,276,337],[83,132,217,232,240,248,260,262,264,266,268,272,333,337,350],[83,132,232,248,274,333,337],[83,132,324],[83,132,255],[83,132,404,405],[83,132,223,230,236,268,283,285,294,311,313,318,341,343,347,350,357,372,388,390,399,403,404],[83,132,219,226,228,232,234,240,244,248,250,252,254,256,260,262,264,266,276,281,289,292,299,303,307,309,316,320,323,325,329,331,335,339,345,350,368,370,376,382,386,397,401],[83,132,342],[83,132,312],[83,132,245,246,247],[83,132,226,240,245,292,350],[83,132,240,245,350],[83,132,344],[83,132,251],[83,132,346],[72,73,74,75,76,83,132],[72,74,83,132],[83,132,146,181,182],[83,132,138,181],[83,132,174,181,188],[83,132,146,181],[83,132,190],[83,132,181],[83,132,193,199,201],[83,132,193,194,195,201],[83,132,196],[83,132,193,201],[83,132,143,146,181,185,186,187],[83,132,183,186,188,205],[83,132,207],[83,132,143,146,148,151,163,174,181],[83,132,211],[83,132,212],[83,132,409,413],[83,129,132],[83,131,132],[132],[83,132,137,166],[83,132,133,138,143,151,163,174],[83,132,133,134,143,151],[78,79,80,83,132],[83,132,135,175],[83,132,136,137,144,152],[83,132,137,163,171],[83,132,138,140,143,151],[83,131,132,139],[83,132,140,141],[83,132,142,143],[83,131,132,143],[83,132,143,144,145,163,174],[83,132,143,144,145,158,163,166],[83,125,132,140,143,146,151,163,174],[83,132,143,144,146,147,151,163,171,174],[83,132,146,148,163,171,174],[81,82,83,84,85,86,87,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180],[83,132,143,149],[83,132,150,174],[83,132,140,143,151,163],[83,132,152],[83,132,153],[83,131,132,154],[83,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180],[83,132,156],[83,132,157],[83,132,143,158,159],[83,132,158,160,175,177],[83,132,144],[83,132,143,163,164,166],[83,132,165,166],[83,132,163,164],[83,132,166],[83,132,167],[83,129,132,163,168],[83,132,143,169,170],[83,132,169,170],[83,132,137,151,163,171],[83,132,172],[83,132,151,173],[83,132,146,157,174],[83,132,137,175],[83,132,163,176],[83,132,150,177],[83,132,178],[83,125,132],[83,125,132,143,145,154,163,166,174,176,177,179],[83,132,163,180],[83,132,422],[83,132,420,421],[83,132,427,465],[83,132,427,450,465],[83,132,426,465],[83,132,465],[83,132,427],[83,132,427,451,465],[83,132,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464],[83,132,451,465],[83,132,144,163,181],[83,132,144,206],[83,132,146,181,202,204],[83,132,144,163,181,203],[83,132,468],[83,132,469],[83,132,471],[83,132,143,146,148,151,163,171,174,180,181],[83,132,479],[83,132,193,197,198,201],[83,132,199],[83,132,214,411,412],[83,132,409],[83,132,215,410],[63,83,132,140,143,151,163,171],[83,132,408],[83,97,101,132,174],[83,97,132,163,174],[83,92,132],[83,94,97,132,171,174],[83,132,151,171],[83,92,132,181],[83,94,97,132,151,174],[83,89,90,93,96,132,143,163,174],[83,97,104,132],[83,89,95,132],[83,97,118,119,132],[83,93,97,132,166,174,181],[83,118,132,181],[83,91,92,132,181],[83,97,132],[83,91,92,93,94,95,96,97,98,99,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,119,120,121,122,123,124,132],[83,97,112,132],[83,97,104,105,132],[83,95,97,105,106,132],[83,96,132],[83,89,92,97,132],[83,97,101,105,106,132],[83,101,132],[83,95,97,100,132,174],[83,89,94,97,104,132],[83,132,163],[83,92,97,118,132,179,181],[64,83,132],[64,65,66,67,68,83,132,135],[64,65,83,132],[66,67,83,132],[65,66,68,69,70,83,132]],"fileInfos":[{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"feecb1be483ed332fad555aff858affd90a48ab19ba7272ee084704eb7167569","impliedFormat":1},{"version":"ee7bad0c15b58988daa84371e0b89d313b762ab83cb5b31b8a2d1162e8eb41c2","impliedFormat":1},{"version":"27bdc30a0e32783366a5abeda841bc22757c1797de8681bbe81fbc735eeb1c10","impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb0f136d372979348d59b3f5020b4cdb81b5504192b1cacff5d1fbba29378aa1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a680117f487a4d2f30ea46f1b4b7f58bef1480456e18ba53ee85c2746eeca012","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"af3dd424cf267428f30ccfc376f47a2c0114546b55c44d8c0f1d57d841e28d74","affectsGlobalScope":true,"impliedFormat":1},{"version":"995c005ab91a498455ea8dfb63aa9f83fa2ea793c3d8aa344be4a1678d06d399","affectsGlobalScope":true,"impliedFormat":1},{"version":"959d36cddf5e7d572a65045b876f2956c973a586da58e5d26cde519184fd9b8a","affectsGlobalScope":true,"impliedFormat":1},{"version":"965f36eae237dd74e6cca203a43e9ca801ce38824ead814728a2807b1910117d","affectsGlobalScope":true,"impliedFormat":1},{"version":"3925a6c820dcb1a06506c90b1577db1fdbf7705d65b62b99dce4be75c637e26b","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a3d63ef2b853447ec4f749d3f368ce642264246e02911fcb1590d8c161b8005","affectsGlobalScope":true,"impliedFormat":1},{"version":"8cdf8847677ac7d20486e54dd3fcf09eda95812ac8ace44b4418da1bbbab6eb8","affectsGlobalScope":true,"impliedFormat":1},{"version":"8444af78980e3b20b49324f4a16ba35024fef3ee069a0eb67616ea6ca821c47a","affectsGlobalScope":true,"impliedFormat":1},{"version":"3287d9d085fbd618c3971944b65b4be57859f5415f495b33a6adc994edd2f004","affectsGlobalScope":true,"impliedFormat":1},{"version":"b4b67b1a91182421f5df999988c690f14d813b9850b40acd06ed44691f6727ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"df83c2a6c73228b625b0beb6669c7ee2a09c914637e2d35170723ad49c0f5cd4","affectsGlobalScope":true,"impliedFormat":1},{"version":"436aaf437562f276ec2ddbee2f2cdedac7664c1e4c1d2c36839ddd582eeb3d0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e3c06ea092138bf9fa5e874a1fdbc9d54805d074bee1de31b99a11e2fec239d","affectsGlobalScope":true,"impliedFormat":1},{"version":"51ad4c928303041605b4d7ae32e0c1ee387d43a24cd6f1ebf4a2699e1076d4fa","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"26db0a6b70d251b4b95101d8f58dbb8a5fe0643bf010fb69f1deed06a0cc33d2","impliedFormat":1},{"version":"683ab7efcc7cf6e47280404f2bf848a542e306a0ba42cabcd254b22e26de8366","impliedFormat":1},{"version":"c20b8ce38122db4689718a20fdf6d0b4cf15093dbe6d78d37d4e356a873957ef","signature":"044267f133d8dbc6c2dc45938fc8e461ef1ffad97b3c6d578350e519e4c03317"},{"version":"6d5904e3c33d51ca70c178233b3423e975d44fb4ad59e0441a4e84cae477b21f","signature":"923380dfd6d15329e7825751cd55100d7bf79053444d24bc3b3572703de44dc3"},{"version":"ed849d616865076f44a41c87f27698f7cdf230290c44bafc71d7c2bc6919b202","impliedFormat":1},{"version":"0c848b07fd0572ab734788358318459d068d60146b97359931abf6fe9fd17aab","signature":"6530b505e10569b7eed5b4d593175563872adbe29d1897eec015c8292871ddd5"},{"version":"3ca4d95a29ae030bb7ce79baa791bf788ba666a10db998abb776a7eb2cb5d156","signature":"183f4c08a7ba0ebd372749702c05e0c3454deb66b437a8448ac53747c13dbd84"},{"version":"bb9f1c2e030d9a92e814fc030e3c640eee615690ba04e8b8a0c6f09cfb0443de","signature":"ab2bbb6e2856bc23e0d289e364b8472e694c92552b9913d552dace15ceee922d"},{"version":"a3f1ad37c61f8dc9b59d8352259fbaf26ee2e4101347c886216206f1069a969f","signature":"5a03ca98612bedcc00eeae60c16279d58c0f40051a1197ddc56dcec1e645428c"},{"version":"c2c2a861a338244d7dd700d0c52a78916b4bb75b98fc8ca5e7c501899fc03796","impliedFormat":1},{"version":"b6d03c9cfe2cf0ba4c673c209fcd7c46c815b2619fd2aad59fc4229aaef2ed43","impliedFormat":1},{"version":"adb467429462e3891de5bb4a82a4189b92005d61c7f9367c089baf03997c104e","impliedFormat":1},{"version":"670a76db379b27c8ff42f1ba927828a22862e2ab0b0908e38b671f0e912cc5ed","impliedFormat":1},{"version":"13b77ab19ef7aadd86a1e54f2f08ea23a6d74e102909e3c00d31f231ed040f62","impliedFormat":1},{"version":"069bebfee29864e3955378107e243508b163e77ab10de6a5ee03ae06939f0bb9","impliedFormat":1},{"version":"6c7176368037af28cb72f2392010fa1cef295d6d6744bca8cfb54985f3a18c3e","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab41ef1f2cdafb8df48be20cd969d875602483859dc194e9c97c8a576892c052","affectsGlobalScope":true,"impliedFormat":1},{"version":"437e20f2ba32abaeb7985e0afe0002de1917bc74e949ba585e49feba65da6ca1","affectsGlobalScope":true,"impliedFormat":1},{"version":"21d819c173c0cf7cc3ce57c3276e77fd9a8a01d35a06ad87158781515c9a438a","impliedFormat":1},{"version":"98cffbf06d6bab333473c70a893770dbe990783904002c4f1a960447b4b53dca","affectsGlobalScope":true,"impliedFormat":1},{"version":"3af97acf03cc97de58a3a4bc91f8f616408099bc4233f6d0852e72a8ffb91ac9","affectsGlobalScope":true,"impliedFormat":1},{"version":"808069bba06b6768b62fd22429b53362e7af342da4a236ed2d2e1c89fcca3b4a","affectsGlobalScope":true,"impliedFormat":1},{"version":"1db0b7dca579049ca4193d034d835f6bfe73096c73663e5ef9a0b5779939f3d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"f26b11d8d8e4b8028f1c7d618b22274c892e4b0ef5b3678a8ccbad85419aef43","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e9c23ba78aabc2e0a27033f18737a6df754067731e69dc5f52823957d60a4b6","impliedFormat":1},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"763fe0f42b3d79b440a9b6e51e9ba3f3f91352469c1e4b3b67bfa4ff6352f3f4","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"c464d66b20788266e5353b48dc4aa6bc0dc4a707276df1e7152ab0c9ae21fad8","impliedFormat":1},{"version":"78d0d27c130d35c60b5e5566c9f1e5be77caf39804636bc1a40133919a949f21","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"1d6e127068ea8e104a912e42fc0a110e2aa5a66a356a917a163e8cf9a65e4a75","impliedFormat":1},{"version":"5ded6427296cdf3b9542de4471d2aa8d3983671d4cac0f4bf9c637208d1ced43","impliedFormat":1},{"version":"7f182617db458e98fc18dfb272d40aa2fff3a353c44a89b2c0ccb3937709bfb5","impliedFormat":1},{"version":"cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","impliedFormat":1},{"version":"0b8a9268adaf4da35e7fa830c8981cfa22adbbe5b3f6f5ab91f6658899e657a7","impliedFormat":1},{"version":"11396ed8a44c02ab9798b7dca436009f866e8dae3c9c25e8c1fbc396880bf1bb","impliedFormat":1},{"version":"ba7bc87d01492633cb5a0e5da8a4a42a1c86270e7b3d2dea5d156828a84e4882","impliedFormat":1},{"version":"4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","impliedFormat":1},{"version":"c21dc52e277bcfc75fac0436ccb75c204f9e1b3fa5e12729670910639f27343e","impliedFormat":1},{"version":"13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","impliedFormat":1},{"version":"9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","impliedFormat":1},{"version":"4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","impliedFormat":1},{"version":"24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","impliedFormat":1},{"version":"ea0148f897b45a76544ae179784c95af1bd6721b8610af9ffa467a518a086a43","impliedFormat":1},{"version":"24c6a117721e606c9984335f71711877293a9651e44f59f3d21c1ea0856f9cc9","impliedFormat":1},{"version":"dd3273ead9fbde62a72949c97dbec2247ea08e0c6952e701a483d74ef92d6a17","impliedFormat":1},{"version":"405822be75ad3e4d162e07439bac80c6bcc6dbae1929e179cf467ec0b9ee4e2e","impliedFormat":1},{"version":"0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","impliedFormat":1},{"version":"e61be3f894b41b7baa1fbd6a66893f2579bfad01d208b4ff61daef21493ef0a8","impliedFormat":1},{"version":"bd0532fd6556073727d28da0edfd1736417a3f9f394877b6d5ef6ad88fba1d1a","impliedFormat":1},{"version":"89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","impliedFormat":1},{"version":"615ba88d0128ed16bf83ef8ccbb6aff05c3ee2db1cc0f89ab50a4939bfc1943f","impliedFormat":1},{"version":"a4d551dbf8746780194d550c88f26cf937caf8d56f102969a110cfaed4b06656","impliedFormat":1},{"version":"8bd86b8e8f6a6aa6c49b71e14c4ffe1211a0e97c80f08d2c8cc98838006e4b88","impliedFormat":1},{"version":"317e63deeb21ac07f3992f5b50cdca8338f10acd4fbb7257ebf56735bf52ab00","impliedFormat":1},{"version":"4732aec92b20fb28c5fe9ad99521fb59974289ed1e45aecb282616202184064f","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"bf67d53d168abc1298888693338cb82854bdb2e69ef83f8a0092093c2d562107","impliedFormat":1},{"version":"2cbe0621042e2a68c7cbce5dfed3906a1862a16a7d496010636cdbdb91341c0f","affectsGlobalScope":true,"impliedFormat":1},{"version":"f9501cc13ce624c72b61f12b3963e84fad210fbdf0ffbc4590e08460a3f04eba","affectsGlobalScope":true,"impliedFormat":1},{"version":"e7721c4f69f93c91360c26a0a84ee885997d748237ef78ef665b153e622b36c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"df48adbf5b82b79ed989ec3bef2979d988b94978907fd86b4f30ba2b668e49de","impliedFormat":1},{"version":"7394959e5a741b185456e1ef5d64599c36c60a323207450991e7a42e08911419","impliedFormat":1},{"version":"2b06b93fd01bcd49d1a6bd1f9b65ddcae6480b9a86e9061634d6f8e354c1468f","impliedFormat":1},{"version":"6a0cd27e5dc2cfbe039e731cf879d12b0e2dded06d1b1dedad07f7712de0d7f4","affectsGlobalScope":true,"impliedFormat":1},{"version":"13f5c844119c43e51ce777c509267f14d6aaf31eafb2c2b002ca35584cd13b29","impliedFormat":1},{"version":"e60477649d6ad21542bd2dc7e3d9ff6853d0797ba9f689ba2f6653818999c264","impliedFormat":1},{"version":"c2510f124c0293ab80b1777c44d80f812b75612f297b9857406468c0f4dafe29","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"4c829ab315f57c5442c6667b53769975acbf92003a66aef19bce151987675bd1","affectsGlobalScope":true,"impliedFormat":1},{"version":"b2ade7657e2db96d18315694789eff2ddd3d8aea7215b181f8a0b303277cc579","impliedFormat":1},{"version":"9855e02d837744303391e5623a531734443a5f8e6e8755e018c41d63ad797db2","impliedFormat":1},{"version":"6851b67b164a1e84add721ea67ac52696b5aee426b800f68283c6a13046f95ec","impliedFormat":1},{"version":"836a356aae992ff3c28a0212e3eabcb76dd4b0cc06bcb9607aeef560661b860d","impliedFormat":1},{"version":"1e0d1f8b0adfa0b0330e028c7941b5a98c08b600efe7f14d2d2a00854fb2f393","impliedFormat":1},{"version":"41670ee38943d9cbb4924e436f56fc19ee94232bc96108562de1a734af20dc2c","affectsGlobalScope":true,"impliedFormat":1},{"version":"c906fb15bd2aabc9ed1e3f44eb6a8661199d6c320b3aa196b826121552cb3695","impliedFormat":1},{"version":"22295e8103f1d6d8ea4b5d6211e43421fe4564e34d0dd8e09e520e452d89e659","impliedFormat":1},{"version":"a0c4ff5309f0108772562412d15aaa15b32f5db3326288a4490fd461f66a95c8","impliedFormat":1},{"version":"6b4e081d55ac24fc8a4631d5dd77fe249fa25900abd7d046abb87d90e3b45645","impliedFormat":1},{"version":"a10f0e1854f3316d7ee437b79649e5a6ae3ae14ffe6322b02d4987071a95362e","impliedFormat":1},{"version":"ed58b9974bb3114f39806c9c2c6258c4ffa6a255921976a7c53dfa94bf178f42","impliedFormat":1},{"version":"e6fa9ad47c5f71ff733744a029d1dc472c618de53804eae08ffc243b936f87ff","affectsGlobalScope":true,"impliedFormat":1},{"version":"b57f8f7247d878e1bb5c329acbd4c1ad8efb073f4ffa6dc120d52924b1e30e40","impliedFormat":1},{"version":"24826ed94a78d5c64bd857570fdbd96229ad41b5cb654c08d75a9845e3ab7dde","impliedFormat":1},{"version":"45875bcae57270aeb3ebc73a5e3fb4c7b9d91d6b045f107c1d8513c28ece71c0","impliedFormat":1},{"version":"928af3d90454bf656a52a48679f199f64c1435247d6189d1caf4c68f2eaf921f","affectsGlobalScope":true,"impliedFormat":1},{"version":"6fac322c7864146db8daa23389f979fdb9fb97f63f212a9424a302f01c2a40d1","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f16a7e4deafa527ed9995a772bb380eb7d3c2c0fd4ae178c5263ed18394db2c","impliedFormat":1},{"version":"933921f0bb0ec12ef45d1062a1fc0f27635318f4d294e4d99de9a5493e618ca2","impliedFormat":1},{"version":"71a0f3ad612c123b57239a7749770017ecfe6b66411488000aba83e4546fde25","impliedFormat":1},{"version":"77fbe5eecb6fac4b6242bbf6eebfc43e98ce5ccba8fa44e0ef6a95c945ff4d98","impliedFormat":1},{"version":"4f9d8ca0c417b67b69eeb54c7ca1bedd7b56034bb9bfd27c5d4f3bc4692daca7","impliedFormat":1},{"version":"814118df420c4e38fe5ae1b9a3bafb6e9c2aa40838e528cde908381867be6466","impliedFormat":1},{"version":"248bc21b92f51ce0b8a67140f2e55887c5f598095e9a790a05fdd2729b531e7a","impliedFormat":1},{"version":"f27524f4bef4b6519c604bdb23bf4465bddcccbf3f003abb901acbd0d7404d99","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"45650f47bfb376c8a8ed39d4bcda5902ab899a3150029684ee4c10676d9fbaee","impliedFormat":1},{"version":"dba28a419aec76ed864ef43e5f577a5c99a010c32e5949fe4e17a4d57c58dd11","affectsGlobalScope":true,"impliedFormat":1},{"version":"18fd40412d102c5564136f29735e5d1c3b455b8a37f920da79561f1fde068208","impliedFormat":1},{"version":"c959a391a75be9789b43c8468f71e3fa06488b4d691d5729dde1416dcd38225b","impliedFormat":1},{"version":"f0be1b8078cd549d91f37c30c222c2a187ac1cf981d994fb476a1adc61387b14","affectsGlobalScope":true,"impliedFormat":1},{"version":"0aaed1d72199b01234152f7a60046bc947f1f37d78d182e9ae09c4289e06a592","impliedFormat":1},{"version":"8c66347a2f5b28e579a306672633dd900751e72bb5c3150ceb10b1fcfcf3d12d","impliedFormat":1},{"version":"66ba1b2c3e3a3644a1011cd530fb444a96b1b2dfe2f5e837a002d41a1a799e60","impliedFormat":1},{"version":"7e514f5b852fdbc166b539fdd1f4e9114f29911592a5eb10a94bb3a13ccac3c4","impliedFormat":1},{"version":"ea2e8e586844e2ebda7986fd859c4c7b283dc90198cd485250498a5412db27a0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4bf07b8f59b43670a28f14d0d5668a5f4abfe106d481fad660f8a1010529609a","affectsGlobalScope":true,"impliedFormat":1},{"version":"ea08a0345023ade2b47fbff5a76d0d0ed8bff10bc9d22b83f40858a8e941501c","impliedFormat":1},{"version":"47613031a5a31510831304405af561b0ffaedb734437c595256bb61a90f9311b","impliedFormat":1},{"version":"ae062ce7d9510060c5d7e7952ae379224fb3f8f2dd74e88959878af2057c143b","impliedFormat":1},{"version":"71122b94871f11a2be216426470523b679a318b08b34dab23e5e4ba9bdf54c23","affectsGlobalScope":true,"impliedFormat":1},{"version":"02aa5feb7aaa41b25b86c7a873839a799d4c6beee4f7d1789aa338905554e495","impliedFormat":1},{"version":"bdf1feb266c87edbee61f12ceaaef60ab0e2e5dba70ca19360b6448911c53d52","impliedFormat":1},{"version":"104c67f0da1bdf0d94865419247e20eded83ce7f9911a1aa75fc675c077ca66e","impliedFormat":1},{"version":"cc0d0b339f31ce0ab3b7a5b714d8e578ce698f1e13d7f8c60bfb766baeb1d35c","impliedFormat":1},{"version":"f9e22729fa06ed20f8b1fe60670b7c74933fdfd44d869ddfb1919c15a5cf12fb","impliedFormat":1},{"version":"d34aa8df2d0b18fb56b1d772ff9b3c7aea7256cf0d692f969be6e1d27b74d660","impliedFormat":1},{"version":"baac9896d29bcc55391d769e408ff400d61273d832dd500f21de766205255acb","impliedFormat":1},{"version":"2f5747b1508ccf83fad0c251ba1e5da2f5a30b78b09ffa1cfaf633045160afed","impliedFormat":1},{"version":"94ee9ee71018d54902c3fe6730090a8a421dcad95fc372d9b69a6d5351194885","affectsGlobalScope":true,"impliedFormat":1},{"version":"689be50b735f145624c6f391042155ae2ff6b90a93bac11ca5712bc866f6010c","impliedFormat":1},{"version":"fb893a0dfc3c9fb0f9ca93d0648694dd95f33cbad2c0f2c629f842981dfd4e2e","impliedFormat":1},{"version":"3eb11dbf3489064a47a2e1cf9d261b1f100ef0b3b50ffca6c44dd99d6dd81ac1","impliedFormat":1},{"version":"1800025430a0f210d5d1476459447a8a635bfbd9140111fd987e711ad1a770da","impliedFormat":1},{"version":"151ff381ef9ff8da2da9b9663ebf657eac35c4c9a19183420c05728f31a6761d","impliedFormat":1},{"version":"f3d8c757e148ad968f0d98697987db363070abada5f503da3c06aefd9d4248c1","impliedFormat":1},{"version":"a4a39b5714adfcadd3bbea6698ca2e942606d833bde62ad5fb6ec55f5e438ff8","impliedFormat":1},{"version":"bbc1d029093135d7d9bfa4b38cbf8761db505026cc458b5e9c8b74f4000e5e75","impliedFormat":1},{"version":"ac450542cbfd50a4d7bf0f3ec8aeedb9e95791ecc6f2b2b19367696bd303e8c6","impliedFormat":99},{"version":"8a190298d0ff502ad1c7294ba6b0abb3a290fc905b3a00603016a97c363a4c7a","impliedFormat":1},{"version":"5ba4a4a1f9fae0550de86889fb06cd997c8406795d85647cbcd992245625680c","impliedFormat":1},{"version":"1f68ab0e055994eb337b67aa87d2a15e0200951e9664959b3866ee6f6b11a0fe","impliedFormat":1},{"version":"5d08a179b846f5ee674624b349ebebe2121c455e3a265dc93da4e8d9e89722b4","impliedFormat":1},{"version":"b71c603a539078a5e3a039b20f2b0a0d1708967530cf97dec8850a9ca45baa2b","impliedFormat":1},{"version":"d3f2d715f57df3f04bf7b16dde01dec10366f64fce44503c92b8f78f614c1769","impliedFormat":1},{"version":"cb90077223cc1365fa21ef0911a1f9b8f2f878943523d97350dc557973ca3823","impliedFormat":1},{"version":"18f1541b81b80d806120a3489af683edfb811deb91aeca19735d9bb2613e6311","impliedFormat":1},{"version":"232f118ae64ab84dcd26ddb60eaed5a6e44302d36249abf05e9e3fc2cbb701a2","impliedFormat":1},{"version":"89121c1bf2990f5219bfd802a3e7fc557de447c62058d6af68d6b6348d64499a","impliedFormat":1},{"version":"79b4369233a12c6fa4a07301ecb7085802c98f3a77cf9ab97eee27e1656f82e6","impliedFormat":1},{"version":"d7dbe0ad36bdca8a6ecf143422a48e72cc8927bab7b23a1a2485c2f78a7022c6","impliedFormat":1},{"version":"26b7d0cd4b41ab557ef9e3bfeec42dcf24252843633e3d29f38d2c0b13aaa528","impliedFormat":1},{"version":"035a5df183489c2e22f3cf59fc1ed2b043d27f357eecc0eb8d8e840059d44245","impliedFormat":1},{"version":"a4809f4d92317535e6b22b01019437030077a76fec1d93b9881c9ed4738fcc54","impliedFormat":1},{"version":"5f53fa0bd22096d2a78533f94e02c899143b8f0f9891a46965294ee8b91a9434","impliedFormat":1},{"version":"d934a06d62d87a7e2d75a3586b5f9fb2d94d5fe4725ff07252d5f4651485100f","impliedFormat":1},{"version":"0d14fa22c41fdc7277e6f71473b20ebc07f40f00e38875142335d5b63cdfc9d2","impliedFormat":1},{"version":"b104e2da53231a529373174880dc0abfbc80184bb473b6bf2a9a0746bebb663d","impliedFormat":1},{"version":"ee91a5fbbd1627c632df89cce5a4054f9cc6e7413ebdccc82b27c7ffeedf982d","impliedFormat":1},{"version":"85c8731ca285809fc248abf21b921fe00a67b6121d27060d6194eddc0e042b1a","impliedFormat":1},{"version":"6bac0cbdf1bc85ae707f91fdf037e1b600e39fb05df18915d4ecab04a1e59d3c","impliedFormat":1},{"version":"5688b21a05a2a11c25f56e53359e2dcda0a34cb1a582dbeb1eaacdeca55cb699","impliedFormat":1},{"version":"35558bf15f773acbe3ed5ac07dd27c278476630d85245f176e85f9a95128b6e0","impliedFormat":1},{"version":"951f54e4a63e82b310439993170e866dba0f28bb829cbc14d2f2103935cea381","impliedFormat":1},{"version":"4454a999dc1676b866450e8cddd9490be87b391b5526a33f88c7e45129d30c5d","impliedFormat":1},{"version":"99013139312db746c142f27515a14cdebb61ff37f20ee1de6a58ce30d36a4f0d","impliedFormat":1},{"version":"71da852f38ac50d2ae43a7b7f2899b10a2000727fee293b0b72123ed2e7e2ad6","impliedFormat":1},{"version":"74dd1096fca1fec76b951cf5eacf609feaf919e67e13af02fed49ec3b77ea797","impliedFormat":1},{"version":"a0691153ccf5aa1b687b1500239722fff4d755481c20e16d9fcd7fb2d659c7c7","impliedFormat":1},{"version":"fe2201d73ae56b1b4946c10e18549a93bf4c390308af9d422f1ffd3c7989ffc8","impliedFormat":1},{"version":"cad63667f992149cee390c3e98f38c00eee56a2dae3541c6d9929641b835f987","impliedFormat":1},{"version":"f497cad2b33824d8b566fa276cfe3561553f905fdc6b40406c92bcfcaec96552","impliedFormat":1},{"version":"eb58c4dbc6fec60617d80f8ccf23900a64d3190fda7cfb2558b389506ec69be0","impliedFormat":1},{"version":"578929b1c1e3adaed503c0a0f9bda8ba3fea598cc41ad5c38932f765684d9888","impliedFormat":1},{"version":"7cc9d600b2070b1e5c220044a8d5a58b40da1c11399b6c8968711de9663dc6b2","impliedFormat":1},{"version":"45f36cf09d3067cd98b39a7d430e0e531f02911dd6d63b6d784b1955eef86435","impliedFormat":1},{"version":"80419a23b4182c256fa51d71cb9c4d872256ca6873701ceabbd65f8426591e49","impliedFormat":1},{"version":"5aa046aaab44da1a63d229bd67a7a1344afbd6f64db20c2bbe3981ceb2db3b07","impliedFormat":1},{"version":"ed9ad5b51c6faf9d6f597aa0ab11cb1d3a361c51ba59d1220557ef21ad5b0146","impliedFormat":1},{"version":"73db7984e8a35e6b48e3879a6d024803dd990022def2750b3c23c01eb58bc30f","impliedFormat":1},{"version":"c9ecb910b3b4c0cf67bc74833fc41585141c196b5660d2eb3a74cfffbf5aa266","impliedFormat":1},{"version":"33dcfba8a7e4acbe23974d342c44c36d7382c3d1d261f8aef28261a7a5df2969","impliedFormat":1},{"version":"de26700eb7277e8cfdde32ebb21b3d9ad1d713b64fdc2019068b857611e8f0c4","impliedFormat":1},{"version":"e481bd2c07c8e93eb58a857a9e66f22cb0b5ddfd86bbf273816fd31ef3a80613","impliedFormat":1},{"version":"ef156ba4043f6228d37645d6d9c6230a311e1c7a86669518d5f2ebc26e6559bf","impliedFormat":1},{"version":"457fd1e6d6f359d7fa2ca453353f4317efccae5c902b13f15c587597015212bc","impliedFormat":1},{"version":"473b2b42af720ebdb539988c06e040fd9600facdeb23cb297d72ee0098d8598f","impliedFormat":1},{"version":"22bc373ca556de33255faaddb373fec49e08336638958ad17fbd6361c7461eed","impliedFormat":1},{"version":"b3d58358675095fef03ec71bddc61f743128682625f1336df2fc31e29499ab25","impliedFormat":1},{"version":"5b1ef94b03042629c76350fe18be52e17ab70f1c3be8f606102b30a5cd86c1b3","impliedFormat":1},{"version":"a7b6046c44d5fda21d39b3266805d37a2811c2f639bf6b40a633b9a5fb4f5d88","impliedFormat":1},{"version":"80b036a132f3def4623aad73d526c6261dcae3c5f7013857f9ecf6589b72951f","impliedFormat":1},{"version":"0a347c2088c3b1726b95ccde77953bede00dd9dd2fda84585fa6f9f6e9573c18","impliedFormat":1},{"version":"8cc3abb4586d574a3faeea6747111b291e0c9981003a0d72711351a6bcc01421","impliedFormat":1},{"version":"0a516adfde610035e31008b170da29166233678216ef3646822c1b9af98879da","impliedFormat":1},{"version":"70d48a1faa86f67c9cb8a39babc5049246d7c67b6617cd08f64e29c055897ca9","impliedFormat":1},{"version":"a8d7795fcf72b0b91fe2ad25276ea6ab34fdb0f8f42aa1dd4e64ee7d02727031","impliedFormat":1},{"version":"082b818038423de54be877cebdb344a2e3cf3f6abcfc48218d8acf95c030426a","impliedFormat":1},{"version":"813514ef625cb8fc3befeec97afddfb3b80b80ced859959339d99f3ad538d8fe","impliedFormat":1},{"version":"039cd54028eb988297e189275764df06c18f9299b14c063e93bd3f30c046fee6","impliedFormat":1},{"version":"e91cfd040e6da28427c5c4396912874902c26605240bdc3457cc75b6235a80f2","impliedFormat":1},{"version":"b4347f0b45e4788c18241ac4dee20ceab96d172847f1c11d42439d3de3c09a3e","impliedFormat":1},{"version":"16fe6721dc0b4144a0cdcef98857ee19025bf3c2a3cc210bcd0b9d0e25f7cec8","impliedFormat":1},{"version":"346d903799e8ea99e9674ba5745642d47c0d77b003cc7bb93e1d4c21c9e37101","impliedFormat":1},{"version":"3997421bb1889118b1bbfc53dd198c3f653bf566fd13c663e02eb08649b985c4","impliedFormat":1},{"version":"2d1ac54184d897cb5b2e732d501fa4591f751678717fd0c1fd4a368236b75cba","impliedFormat":1},{"version":"bade30041d41945c54d16a6ec7046fba6d1a279aade69dfdef9e70f71f2b7226","impliedFormat":1},{"version":"56fbea100bd7dd903dc49a1001995d3c6eee10a419c66a79cdb194bff7250eb7","impliedFormat":1},{"version":"fe8d26b2b3e519e37ceea31b1790b17d7c5ab30334ca2b56d376501388ba80d6","impliedFormat":1},{"version":"37ad0a0c2b296442072cd928d55ef6a156d50793c46c2e2497da1c2750d27c1e","impliedFormat":1},{"version":"be93d07586d09e1b6625e51a1591d6119c9f1cbd95718497636a406ec42babee","impliedFormat":1},{"version":"a062b507ed5fc23fbc5850fd101bc9a39e9a0940bb52a45cd4624176337ad6b8","impliedFormat":1},{"version":"cf01f601ef1e10b90cad69312081ce0350f26a18330913487a26d6d4f7ce5a73","impliedFormat":1},{"version":"a9de7b9a5deaed116c9c89ad76fdcc469226a22b79c80736de585af4f97b17cd","impliedFormat":1},{"version":"5bde81e8b0efb2d977c6795f9425f890770d54610764b1d8df340ce35778c4f8","impliedFormat":1},{"version":"20fd0402351907669405355eeae8db00b3cf0331a3a86d8142f7b33805174f57","impliedFormat":1},{"version":"da6949af729eca1ec1fe867f93a601988b5b206b6049c027d0c849301d20af6f","impliedFormat":1},{"version":"7008f240ea3a5a344be4e5f9b5dbf26721aad3c5cfef5ff79d133fa7450e48fa","impliedFormat":1},{"version":"eb13c8624f5747a845aea0df1dfde0f2b8f5ed90ca3bc550b12777797cb1b1e3","impliedFormat":1},{"version":"2452fc0f47d3b5b466bda412397831dd5138e62f77aa5e11270e6ca3ecb8328d","impliedFormat":1},{"version":"33c2ebbdd9a62776ca0091a8d1f445fa2ea4b4f378bc92f524031a70dfbeec86","impliedFormat":1},{"version":"3ac3a5b34331a56a3f76de9baf619def3f3073961ce0a012b6ffa72cf8a91f1f","impliedFormat":1},{"version":"d5e9d32cc9813a5290a17492f554999e33f1aa083a128d3e857779548537a778","impliedFormat":1},{"version":"776f49489fa2e461b40370e501d8e775ddb32433c2d1b973f79d9717e1d79be5","impliedFormat":1},{"version":"be94ea1bfaa2eeef1e821a024914ef94cf0cba05be8f2e7df7e9556231870a1d","impliedFormat":1},{"version":"40cd13782413c7195ad8f189f81174850cc083967d056b23d529199d64f02c79","impliedFormat":1},{"version":"05e041810faf710c1dcd03f3ffde100c4a744672d93512314b1f3cfffccdaf20","impliedFormat":1},{"version":"15a8f79b1557978d752c0be488ee5a70daa389638d79570507a3d4cfc620d49d","impliedFormat":1},{"version":"968ee57037c469cffb3b0e268ab824a9c31e4205475b230011895466a1e72da4","impliedFormat":1},{"version":"77debd777927059acbaf1029dfc95900b3ab8ed0434ce3914775efb0574e747b","impliedFormat":1},{"version":"921e3bd6325acb712cd319eaec9392c9ad81f893dead509ab2f4e688f265e536","impliedFormat":1},{"version":"60f6768c96f54b870966957fb9a1b176336cd82895ded088980fb506c032be1c","impliedFormat":1},{"version":"755d9b267084db4ea40fa29653ea5fc43e125792b1940f2909ec70a4c7f712d8","impliedFormat":1},{"version":"7e3056d5333f2d8a9e54324c2e2293027e4cd9874615692a53ad69090894d116","impliedFormat":1},{"version":"1e25b848c58ad80be5c31b794d49092d94df2b7e492683974c436bcdbefb983c","impliedFormat":1},{"version":"3df6fc700b8d787974651680ae6e37b6b50726cf5401b7887f669ab195c2f2ef","impliedFormat":1},{"version":"145df08c171ec616645a353d5eaa5d5f57a5fbce960a47d847548abd9215a99e","impliedFormat":1},{"version":"dcfd2ca9e033077f9125eeca6890bb152c6c0bc715d0482595abc93c05d02d92","impliedFormat":1},{"version":"8056fa6beb8297f160e13c9b677ba2be92ab23adfb6940e5a974b05acd33163b","impliedFormat":1},{"version":"86dda1e79020fad844010b39abb68fafed2f3b2156e3302820c4d0a161f88b03","impliedFormat":1},{"version":"dea0dcec8d5e0153d6f0eacebb163d7c3a4b322a9304048adffc6d26084054bd","impliedFormat":1},{"version":"2afd081a65d595d806b0ff434d2a96dc3d6dcd8f0d1351c0a0968568c6944e0b","impliedFormat":1},{"version":"10ca40958b0dbba6426cf142c0347559cdd97d66c10083e829b10eb3c0ebc75c","impliedFormat":1},{"version":"2f1f7c65e8ee58e3e7358f9b8b3c37d8447549ecc85046f9405a0fc67fbdf54b","impliedFormat":1},{"version":"e3f3964ff78dee11a07ae589f1319ff682f62f3c6c8afa935e3d8616cf21b431","impliedFormat":1},{"version":"2762c2dbee294ffb8fdbcae6db32c3dae09e477d6a348b48578b4145b15d1818","impliedFormat":1},{"version":"e0f1c55e727739d4918c80cd9f82cf8a94274838e5ac48ff0c36529e23b79dc5","impliedFormat":1},{"version":"24bd135b687da453ea7bd98f7ece72e610a3ff8ca6ec23d321c0e32f19d32db6","impliedFormat":1},{"version":"64d45d55ba6e42734ac326d2ea1f674c72837443eb7ff66c82f95e4544980713","impliedFormat":1},{"version":"f9b0dc747f13dcc09e40c26ddcc118b1bafc3152f771fdc32757a7f8916a11fc","impliedFormat":1},{"version":"7035fc608c297fd38dfe757d44d3483a570e2d6c8824b2d6b20294d617da64c6","impliedFormat":1},{"version":"22160a296186123d2df75280a1fab70d2105ce1677af1ebb344ffcb88eef6e42","impliedFormat":1},{"version":"9067b3fd7d71165d4c34fcbbf29f883860fd722b7e8f92e87da036b355a6c625","impliedFormat":1},{"version":"e01ab4b99cc4a775d06155e9cadd2ebd93e4af46e2723cb9361f24a4e1f178ef","impliedFormat":1},{"version":"9a13410635d5cc9c2882e67921c59fb26e77b9d99efa1a80b5a46fdc2954afce","impliedFormat":1},{"version":"eabf68d666f0568b6439f4a58559d42287c3397a03fa6335758b1c8811d4174a","impliedFormat":1},{"version":"fa894bdddb2ba0e6c65ad0d88942cf15328941246410c502576124ef044746f9","impliedFormat":1},{"version":"59c5a06fa4bf2fa320a3c5289b6f199a3e4f9562480f59c0987c91dc135a1adf","impliedFormat":1},{"version":"456a9a12ad5d57af0094edf99ceab1804449f6e7bc773d85d09c56a18978a177","impliedFormat":1},{"version":"a8e2a77f445a8a1ce61bfd4b7b22664d98cf19b84ec6a966544d0decec18e143","impliedFormat":1},{"version":"6f6b0b477db6c4039410c7a13fe1ebed4910dedf644330269816df419cdb1c65","impliedFormat":1},{"version":"960b6e1edfb9aafbd560eceaae0093b31a9232ab273f4ed776c647b2fb9771da","impliedFormat":1},{"version":"3bf44073402d2489e61cdf6769c5c4cf37529e3a1cd02f01c58b7cf840308393","impliedFormat":1},{"version":"a0db48d42371b223cea8fd7a41763d48f9166ecd4baecc9d29d9bb44cc3c2d83","impliedFormat":1},{"version":"aaf3c2e268f27514eb28255835f38445a200cd8bcfdff2c07c6227f67aaaf657","impliedFormat":1},{"version":"6ade56d2afdf75a9bd55cd9c8593ed1d78674804d9f6d9aba04f807f3179979e","impliedFormat":1},{"version":"b67acb619b761e91e3a11dddb98c51ee140361bc361eb17538f1c3617e3ec157","impliedFormat":1},{"version":"81b097e0f9f8d8c3d5fe6ba9dc86139e2d95d1e24c5ce7396a276dfbb2713371","impliedFormat":1},{"version":"692d56fff4fb60948fe16e9fed6c4c4eac9b263c06a8c6e63726e28ed4844fd4","impliedFormat":1},{"version":"f13228f2c0e145fc6dc64917eeef690fb2883a0ac3fa9ebfbd99616fd12f5629","impliedFormat":1},{"version":"d89b2b41a42c04853037408080a2740f8cd18beee1c422638d54f8aefe95c5b8","impliedFormat":1},{"version":"be5d39e513e3e0135068e4ebed5473ab465ae441405dce90ab95055a14403f64","impliedFormat":1},{"version":"97e320c56905d9fa6ac8bd652cea750265384f048505870831e273050e2878cc","impliedFormat":1},{"version":"9932f390435192eb93597f89997500626fb31005416ce08a614f66ec475c5c42","impliedFormat":1},{"version":"5d89ca552233ac2d61aee34b0587f49111a54a02492e7a1098e0701dedca60c9","impliedFormat":1},{"version":"369773458c84d91e1bfcb3b94948a9768f15bf2829538188abd467bad57553cd","impliedFormat":1},{"version":"fdc4fd2c610b368104746960b45216bc32685927529dd871a5330f4871d14906","impliedFormat":1},{"version":"7b5d77c769a6f54ea64b22f1877d64436f038d9c81f1552ad11ed63f394bd351","impliedFormat":1},{"version":"4f7d54c603949113f45505330caae6f41e8dbb59841d4ae20b42307dc4579835","impliedFormat":1},{"version":"a71fd01a802624c3fce6b09c14b461cc7c7758aa199c202d423a7c89ad89943c","impliedFormat":1},{"version":"1ed0dc05908eb15f46379bc1cb64423760e59d6c3de826a970b2e2f6da290bf5","impliedFormat":1},{"version":"db89ef053f209839606e770244031688c47624b771ff5c65f0fa1ec10a6919f1","impliedFormat":1},{"version":"4d45b88987f32b2ac744f633ff5ddb95cd10f64459703f91f1633ff457d6c30d","impliedFormat":1},{"version":"8512fd4a480cd8ef8bf923a85ff5e97216fa93fb763ec871144a9026e1c9dade","impliedFormat":1},{"version":"2aa58b491183eedf2c8ae6ef9a610cd43433fcd854f4cc3e2492027fbe63f5ca","impliedFormat":1},{"version":"ce1f3439cb1c5a207f47938e68752730892fc3e66222227effc6a8b693450b82","impliedFormat":1},{"version":"295ce2cf585c26a9b71ba34fbb026d2b5a5f0d738b06a356e514f39c20bf38ba","impliedFormat":1},{"version":"342f10cf9ba3fbf52d54253db5c0ac3de50360b0a3c28e648a449e28a4ac8a8c","impliedFormat":1},{"version":"c485987c684a51c30e375d70f70942576fa86e9d30ee8d5849b6017931fccc6f","impliedFormat":1},{"version":"320bd1aa480e22cdd7cd3d385157258cc252577f4948cbf7cfdf78ded9d6d0a8","impliedFormat":1},{"version":"4ee053dfa1fce5266ecfae2bf8b6b0cb78a6a76060a1dcf66fb7215b9ff46b0b","impliedFormat":1},{"version":"1f84d8b133284b596328df47453d3b3f3817ad206cf3facf5eb64b0a2c14f6d7","impliedFormat":1},{"version":"5c75e05bc62bffe196a9b2e9adfa824ffa7b90d62345a766c21585f2ce775001","impliedFormat":1},{"version":"cc2eb5b23140bbceadf000ef2b71d27ac011d1c325b0fc5ecd42a3221db5fb2e","impliedFormat":1},{"version":"fd75cc24ea5ec28a44c0afc2f8f33da5736be58737ba772318ae3bdc1c079dc3","impliedFormat":1},{"version":"5ae43407346e6f7d5408292a7d957a663cc7b6d858a14526714a23466ac83ef9","impliedFormat":1},{"version":"c72001118edc35bbe4fff17674dc5f2032ccdbcc5bec4bd7894a6ed55739d31b","impliedFormat":1},{"version":"353196fd0dd1d05e933703d8dad664651ed172b8dfb3beaef38e66522b1e0219","impliedFormat":1},{"version":"670aef817baea9332d7974295938cf0201a2d533c5721fccf4801ba9a4571c75","impliedFormat":1},{"version":"3f5736e735ee01c6ecc6d4ab35b2d905418bb0d2128de098b73e11dd5decc34f","impliedFormat":1},{"version":"b64e159c49afc6499005756f5a7c2397c917525ceab513995f047cdd80b04bdf","impliedFormat":1},{"version":"f72b400dbf8f27adbda4c39a673884cb05daf8e0a1d8152eec2480f5700db36c","impliedFormat":1},{"version":"24509d0601fc00c4d77c20cacddbca6b878025f4e0712bddd171c7917f8cdcde","impliedFormat":1},{"version":"5f5baa59149d3d6d6cef2c09d46bb4d19beb10d6bee8c05b7850c33535b3c438","impliedFormat":1},{"version":"f17a51aae728f9f1a2290919cf29a927621b27f6ae91697aee78f41d48851690","impliedFormat":1},{"version":"be02e3c3cb4e187fd252e7ae12f6383f274e82288c8772bb0daf1a4e4af571ad","impliedFormat":1},{"version":"82ca40fb541799273571b011cd9de6ee9b577ef68acc8408135504ae69365b74","impliedFormat":1},{"version":"8fb6646db72914d6ef0692ea88b25670bbf5e504891613a1f46b42783ec18cce","impliedFormat":1},{"version":"07b0cb8b69e71d34804bde3e6dc6faaae8299f0118e9566b94e1f767b8ba9d64","impliedFormat":1},{"version":"213aa21650a910d95c4d0bee4bb936ecd51e230c1a9e5361e008830dcc73bc86","impliedFormat":1},{"version":"874a8c5125ad187e47e4a8eacc809c866c0e71b619a863cc14794dd3ccf23940","impliedFormat":1},{"version":"c31db8e51e85ee67018ac2a40006910efbb58e46baea774cf1f245d99bf178b5","impliedFormat":1},{"version":"31fac222250b18ebac0158938ede4b5d245e67d29cd2ef1e6c8a5859d137d803","impliedFormat":1},{"version":"a9dfb793a7e10949f4f3ea9f282b53d3bd8bf59f5459bc6e618e3457ed2529f5","impliedFormat":1},{"version":"2a77167687b0ec0c36ef581925103f1dc0c69993f61a9dbd299dcd30601af487","impliedFormat":1},{"version":"0f23b5ce60c754c2816c2542b9b164d6cb15243f4cbcd11cfafcab14b60e04d0","impliedFormat":1},{"version":"813ce40a8c02b172fdbeb8a07fdd427ac68e821f0e20e3dc699fb5f5bdf1ef0a","impliedFormat":1},{"version":"5ce6b24d5fd5ebb1e38fe817b8775e2e00c94145ad6eedaf26e3adf8bb3903d0","impliedFormat":1},{"version":"6babca69d3ae17be168cfceb91011eed881d41ce973302ee4e97d68a81c514b4","impliedFormat":1},{"version":"3e0832bc2533c0ec6ffcd61b7c055adedcca1a45364b3275c03343b83c71f5b3","impliedFormat":1},{"version":"342418c52b55f721b043183975052fb3956dae3c1f55f965fedfbbf4ad540501","impliedFormat":1},{"version":"6a6ab1edb5440ee695818d76f66d1a282a31207707e0d835828341e88e0c1160","impliedFormat":1},{"version":"7e9b4669774e97f5dc435ddb679aa9e7d77a1e5a480072c1d1291892d54bf45c","impliedFormat":1},{"version":"de439ddbed60296fbd1e5b4d242ce12aad718dffe6432efcae1ad6cd996defd3","impliedFormat":1},{"version":"ce5fb71799f4dbb0a9622bf976a192664e6c574d125d3773d0fa57926387b8b2","impliedFormat":1},{"version":"b9c0de070a5876c81540b1340baac0d7098ea9657c6653731a3199fcb2917cef","impliedFormat":1},{"version":"cbc91ecd74d8f9ddcbcbdc2d9245f14eff5b2f6ae38371283c97ca7dc3c4a45f","impliedFormat":1},{"version":"3ca1d6f016f36c61a59483c80d8b9f9d50301fbe52a0dde288c1381862b13636","impliedFormat":1},{"version":"ecfef0c0ff0c80ac9a6c2fab904a06b680fb5dfe8d9654bb789e49c6973cb781","impliedFormat":1},{"version":"0ee2eb3f7c0106ccf6e388bc0a16e1b3d346e88ac31b6a5bbc15766e43992167","impliedFormat":1},{"version":"f9592b77fd32a7a1262c1e9363d2e43027f513d1d2ff6b21e1cfdac4303d5a73","impliedFormat":1},{"version":"7e46dd61422e5afe88c34e5f1894ae89a37b7a07393440c092e9dc4399820172","impliedFormat":1},{"version":"9df4f57d7279173b0810154c174aa03fd60f5a1f0c3acfe8805e55e935bdecd4","impliedFormat":1},{"version":"a02a51b68a60a06d4bd0c747d6fbade0cb87eefda5f985fb4650e343da424f12","impliedFormat":1},{"version":"0cf851e2f0ecf61cabe64efd72de360246bcb8c19c6ef7b5cbb702293e1ff755","impliedFormat":1},{"version":"0c0e0aaf37ab0552dffc13eb584d8c56423b597c1c49f7974695cb45e2973de6","impliedFormat":1},{"version":"e2e0cd8f6470bc69bbfbc5e758e917a4e0f9259da7ffc93c0930516b0aa99520","impliedFormat":1},{"version":"180de8975eff720420697e7b5d95c0ecaf80f25d0cea4f8df7fe9cf817d44884","impliedFormat":1},{"version":"424a7394f9704d45596dce70bd015c5afec74a1cc5760781dfda31bc300df88f","impliedFormat":1},{"version":"044a62b9c967ee8c56dcb7b2090cf07ef2ac15c07e0e9c53d99fab7219ee3d67","impliedFormat":1},{"version":"3903b01a9ba327aae8c7ea884cdabc115d27446fba889afc95fddca8a9b4f6e2","impliedFormat":1},{"version":"78fd8f2504fbfb0070569729bf2fe41417fdf59f8c3e975ab3143a96f03e0a4a","impliedFormat":1},{"version":"8afd4f91e3a060a886a249f22b23da880ec12d4a20b6404acc5e283ef01bdd46","impliedFormat":1},{"version":"72e72e3dea4081877925442f67b23be151484ef0a1565323c9af7f1c5a0820f0","impliedFormat":1},{"version":"fa8c21bafd5d8991019d58887add8971ccbe88243c79bbcaec2e2417a40af4e8","impliedFormat":1},{"version":"ab35597fd103b902484b75a583606f606ab2cef7c069fae6c8aca0f058cee77d","impliedFormat":1},{"version":"ca54ec33929149dded2199dca95fd8ad7d48a04f6e8500f3f84a050fa77fee45","impliedFormat":1},{"version":"cac7dcf6f66d12979cc6095f33edc7fbb4266a44c8554cd44cd04572a4623fd0","impliedFormat":1},{"version":"98af566e6d420e54e4d8d942973e7fbe794e5168133ad6658b589d9dfb4409d8","impliedFormat":1},{"version":"772b2865dd86088c6e0cab71e23534ad7254961c1f791bdeaf31a57a2254df43","impliedFormat":1},{"version":"786d837fba58af9145e7ad685bc1990f52524dc4f84f3e60d9382a0c3f4a0f77","impliedFormat":1},{"version":"539dd525bf1d52094e7a35c2b4270bee757d3a35770462bcb01cd07683b4d489","impliedFormat":1},{"version":"69135303a105f3b058d79ea7e582e170721e621b1222e8f8e51ea29c61cd3acf","impliedFormat":1},{"version":"e92e6f0d63e0675fe2538e8031e1ece36d794cb6ecc07a036d82c33fa3e091a9","impliedFormat":1},{"version":"1fdb07843cdb9bd7e24745d357c6c1fde5e7f2dd7c668dd68b36c0dff144a390","impliedFormat":1},{"version":"3e2f739bdfb6b194ae2af13316b4c5bb18b3fe81ac340288675f92ba2061b370","affectsGlobalScope":true,"impliedFormat":1},{"version":"96d14f21b7652903852eef49379d04dbda28c16ed36468f8c9fa08f7c14c9538","impliedFormat":1},{"version":"d4a22007b481fe2a2e6bfd3a42c00cd62d41edb36d30fc4697df2692e9891fc8","impliedFormat":1},{"version":"29f72ec1289ae3aeda78bf14b38086d3d803262ac13904b400422941a26a3636","affectsGlobalScope":true,"impliedFormat":1},{"version":"7fadb2778688ebf3fd5b8d04f63d5bf27a43a3e420bc80732d3c6239067d1a4b","impliedFormat":1},{"version":"22293bd6fa12747929f8dfca3ec1684a3fe08638aa18023dd286ab337e88a592","impliedFormat":1},{"version":"170d4db14678c68178ee8a3d5a990d5afb759ecb6ec44dbd885c50f6da6204f6","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac51dd7d31333793807a6abaa5ae168512b6131bd41d9c5b98477fc3b7800f9f","impliedFormat":1},{"version":"5e76305d58bcdc924ff2bf14f6a9dc2aa5441ed06464b7e7bd039e611d66a89b","impliedFormat":1},{"version":"be1cc4d94ea60cbe567bc29ed479d42587bf1e6cba490f123d329976b0fe4ee5","impliedFormat":1},{"version":"510616459e6edd01acbce333fb256e06bdffdad43ca233a9090164bf8bb83912","impliedFormat":1},{"version":"d1e9031cfefebb12d6672ef7d85faf2c5a23472f5b5be1909358db426fe82eef","impliedFormat":1},{"version":"ce6a3f09b8db73a7e9701aca91a04b4fabaf77436dd35b24482f9ee816016b17","impliedFormat":1},{"version":"20e086e5b64fdd52396de67761cc0e94693494deadb731264aac122adf08de3f","impliedFormat":1},{"version":"6e78f75403b3ec65efb41c70d392aeda94360f11cedc9fb2c039c9ea23b30962","impliedFormat":1},{"version":"c863198dae89420f3c552b5a03da6ed6d0acfa3807a64772b895db624b0de707","impliedFormat":1},{"version":"8b03a5e327d7db67112ebbc93b4f744133eda2c1743dbb0a990c61a8007823ef","impliedFormat":1},{"version":"42fad1f540271e35ca37cecda12c4ce2eef27f0f5cf0f8dd761d723c744d3159","impliedFormat":1},{"version":"ff3743a5de32bee10906aff63d1de726f6a7fd6ee2da4b8229054dfa69de2c34","impliedFormat":1},{"version":"83acd370f7f84f203e71ebba33ba61b7f1291ca027d7f9a662c6307d74e4ac22","impliedFormat":1},{"version":"1445cec898f90bdd18b2949b9590b3c012f5b7e1804e6e329fb0fe053946d5ec","impliedFormat":1},{"version":"0e5318ec2275d8da858b541920d9306650ae6ac8012f0e872fe66eb50321a669","impliedFormat":1},{"version":"cf530297c3fb3a92ec9591dd4fa229d58b5981e45fe6702a0bd2bea53a5e59be","impliedFormat":1},{"version":"c1f6f7d08d42148ddfe164d36d7aba91f467dbcb3caa715966ff95f55048b3a4","impliedFormat":1},{"version":"eefd2bbc8edb14c3bd1246794e5c070a80f9b8f3730bd42efb80df3cc50b9039","impliedFormat":1},{"version":"0c1ee27b8f6a00097c2d6d91a21ee4d096ab52c1e28350f6362542b55380059a","impliedFormat":1},{"version":"7677d5b0db9e020d3017720f853ba18f415219fb3a9597343b1b1012cfd699f7","impliedFormat":1},{"version":"bc1c6bc119c1784b1a2be6d9c47addec0d83ef0d52c8fbe1f14a51b4dfffc675","impliedFormat":1},{"version":"52cf2ce99c2a23de70225e252e9822a22b4e0adb82643ab0b710858810e00bf1","impliedFormat":1},{"version":"770625067bb27a20b9826255a8d47b6b5b0a2d3dfcbd21f89904c731f671ba77","impliedFormat":1},{"version":"d1ed6765f4d7906a05968fb5cd6d1db8afa14dbe512a4884e8ea5c0f5e142c80","impliedFormat":1},{"version":"799c0f1b07c092626cf1efd71d459997635911bb5f7fc1196efe449bba87e965","impliedFormat":1},{"version":"2a184e4462b9914a30b1b5c41cf80c6d3428f17b20d3afb711fff3f0644001fd","impliedFormat":1},{"version":"9eabde32a3aa5d80de34af2c2206cdc3ee094c6504a8d0c2d6d20c7c179503cc","impliedFormat":1},{"version":"397c8051b6cfcb48aa22656f0faca2553c5f56187262135162ee79d2b2f6c966","impliedFormat":1},{"version":"a8ead142e0c87dcd5dc130eba1f8eeed506b08952d905c47621dc2f583b1bff9","impliedFormat":1},{"version":"a02f10ea5f73130efca046429254a4e3c06b5475baecc8f7b99a0014731be8b3","impliedFormat":1},{"version":"c2576a4083232b0e2d9bd06875dd43d371dee2e090325a9eac0133fd5650c1cb","impliedFormat":1},{"version":"4c9a0564bb317349de6a24eb4efea8bb79898fa72ad63a1809165f5bd42970dd","impliedFormat":1},{"version":"f40ac11d8859092d20f953aae14ba967282c3bb056431a37fced1866ec7a2681","impliedFormat":1},{"version":"cc11e9e79d4746cc59e0e17473a59d6f104692fd0eeea1bdb2e206eabed83b03","impliedFormat":1},{"version":"b444a410d34fb5e98aa5ee2b381362044f4884652e8bc8a11c8fe14bbd85518e","impliedFormat":1},{"version":"c35808c1f5e16d2c571aa65067e3cb95afeff843b259ecfa2fc107a9519b5392","impliedFormat":1},{"version":"14d5dc055143e941c8743c6a21fa459f961cbc3deedf1bfe47b11587ca4b3ef5","impliedFormat":1},{"version":"a3ad4e1fc542751005267d50a6298e6765928c0c3a8dce1572f2ba6ca518661c","impliedFormat":1},{"version":"f237e7c97a3a89f4591afd49ecb3bd8d14f51a1c4adc8fcae3430febedff5eb6","impliedFormat":1},{"version":"3ffdfbec93b7aed71082af62b8c3e0cc71261cc68d796665faa1e91604fbae8f","impliedFormat":1},{"version":"662201f943ed45b1ad600d03a90dffe20841e725203ced8b708c91fcd7f9379a","impliedFormat":1},{"version":"c9ef74c64ed051ea5b958621e7fb853fe3b56e8787c1587aefc6ea988b3c7e79","impliedFormat":1},{"version":"2462ccfac5f3375794b861abaa81da380f1bbd9401de59ffa43119a0b644253d","impliedFormat":1},{"version":"34baf65cfee92f110d6653322e2120c2d368ee64b3c7981dff08ed105c4f19b0","impliedFormat":1},{"version":"a56fe175741cc8841835eb72e61fa5a34adcbc249ede0e3494c229f0750f6b85","impliedFormat":1},{"version":"ddef25f825320de051dcb0e62ffce621b41c67712b5b4105740c32fd83f4c449","impliedFormat":1},{"version":"1b3dffaa4ca8e38ac434856843505af767a614d187fb3a5ef4fcebb023c355aa","impliedFormat":1},{"version":"cbb2be0de4e2a597ba2b7050389629fb4c2592a923e989d45095d1546913a696","impliedFormat":1},{"version":"aadcf59329c6f0f8978cfa1810dab147e0b67f241a39c965c4904459fcc98c27","impliedFormat":1},{"version":"ab82804a14454734010dcdcd43f564ff7b0389bee4c5692eec76ff5b30d4cf66","impliedFormat":1},{"version":"15fe687c59d62741b4494d5e623d497d55eb38966ecf5bea7f36e48fc3fbe15e","impliedFormat":1},{"version":"2c3b8be03577c98530ef9cb1a76e2c812636a871f367e9edf4c5f3ce702b77f8","affectsGlobalScope":true,"impliedFormat":1},{"version":"f874ea4d0091b0a44362a5f74d26caab2e66dec306c2bf7e8965f5106e784c3b","impliedFormat":1},{"version":"caaf6bf4dd0a3f88b50670f5786141b209edb54ba17eb6268c2d28919c813606","affectsGlobalScope":true,"impliedFormat":1},{"version":"bc3d87d494138b037f883840bef538bc25c1432fcd9afb0b71e438319e08780e","affectsGlobalScope":true,"impliedFormat":1},{"version":"f2f23fe34b735887db1d5597714ae37a6ffae530cafd6908c9d79d485667c956","impliedFormat":1},{"version":"5bba0e6cd8375fd37047e99a080d1bd9a808c95ecb7f3043e3adc125196f6607","impliedFormat":1},{"version":"1ba59c8bbeed2cb75b239bb12041582fa3e8ef32f8d0bd0ec802e38442d3f317","impliedFormat":1},{"version":"bae8d023ef6b23df7da26f51cea44321f95817c190342a36882e93b80d07a960","impliedFormat":1},{"version":"26a770cec4bd2e7dbba95c6e536390fffe83c6268b78974a93727903b515c4e7","impliedFormat":1}],"root":[65,66,[68,71]],"options":{"allowSyntheticDefaultImports":true,"composite":true,"declaration":true,"declarationMap":true,"esModuleInterop":true,"module":1,"outDir":"./dist","rootDir":"./src","skipLibCheck":true,"sourceMap":true,"strict":true,"target":10},"referencedMap":[[74,1],[72,2],[197,3],[214,2],[408,4],[407,5],[218,6],[219,7],[356,6],[357,8],[338,9],[339,10],[222,11],[223,12],[293,13],[294,14],[267,6],[268,15],[261,6],[262,16],[353,17],[351,18],[352,2],[367,19],[368,20],[237,21],[238,22],[369,23],[370,24],[371,25],[372,26],[229,27],[230,28],[355,29],[354,30],[340,6],[341,31],[233,32],[234,33],[257,2],[258,34],[375,35],[373,36],[374,37],[376,38],[377,39],[380,40],[378,41],[381,18],[379,42],[382,43],[385,44],[383,45],[384,46],[386,47],[235,27],[236,48],[361,49],[358,50],[359,51],[360,2],[336,52],[337,53],[281,54],[280,55],[278,56],[277,57],[279,58],[388,59],[387,60],[390,61],[389,62],[266,63],[265,6],[244,64],[242,65],[241,11],[243,66],[393,67],[397,68],[391,69],[392,70],[394,67],[395,67],[396,67],[283,71],[282,11],[299,72],[297,73],[298,18],[295,74],[296,75],[232,76],[231,6],[289,77],[220,6],[221,78],[288,79],[326,80],[329,81],[327,82],[328,83],[240,84],[239,6],[331,85],[330,11],[309,86],[308,6],[264,87],[263,6],[335,88],[334,89],[303,90],[302,91],[300,92],[301,93],[292,94],[291,95],[290,96],[399,97],[398,98],[316,99],[315,100],[314,101],[363,102],[362,2],[307,103],[306,104],[304,105],[305,106],[285,107],[284,11],[228,108],[227,109],[226,110],[225,111],[224,112],[320,113],[319,114],[250,115],[249,11],[254,116],[253,117],[318,118],[317,6],[364,2],[366,119],[365,2],[323,120],[322,121],[321,122],[401,123],[400,124],[403,125],[402,126],[349,127],[350,128],[348,129],[287,130],[286,2],[333,131],[332,132],[260,133],[259,6],[311,134],[310,6],[217,135],[216,2],[270,136],[271,137],[276,138],[269,139],[273,140],[272,141],[274,142],[275,143],[325,144],[324,11],[256,145],[255,11],[406,146],[405,147],[404,148],[343,149],[342,6],[313,150],[312,6],[248,151],[246,152],[245,11],[247,153],[345,154],[344,6],[252,155],[251,6],[347,156],[346,6],[77,157],[73,1],[75,158],[76,1],[183,159],[184,160],[189,161],[182,162],[191,163],[192,164],[200,165],[196,166],[195,167],[201,168],[193,2],[188,169],[206,170],[208,171],[209,2],[202,2],[210,172],[211,2],[212,173],[213,174],[414,175],[194,2],[415,2],[416,171],[203,2],[417,2],[190,2],[418,164],[129,176],[130,176],[131,177],[83,178],[132,179],[133,180],[134,181],[78,2],[81,182],[79,2],[80,2],[135,183],[136,184],[137,185],[138,186],[139,187],[140,188],[141,188],[142,189],[143,190],[144,191],[145,192],[84,2],[82,2],[146,193],[147,194],[148,195],[181,196],[149,197],[150,198],[151,199],[152,200],[153,201],[154,202],[155,203],[156,204],[157,205],[158,206],[159,206],[160,207],[161,2],[162,208],[163,209],[165,210],[164,211],[166,212],[167,213],[168,214],[169,215],[170,216],[171,217],[172,218],[173,219],[174,220],[175,221],[176,222],[177,223],[178,224],[85,2],[86,2],[87,2],[126,225],[127,2],[128,2],[179,226],[180,227],[419,2],[186,2],[187,2],[423,228],[420,2],[422,229],[424,2],[425,2],[450,230],[451,231],[427,232],[430,233],[448,230],[449,230],[439,230],[438,234],[436,230],[431,230],[444,230],[442,230],[446,230],[426,230],[443,230],[447,230],[432,230],[433,230],[445,230],[428,230],[434,230],[435,230],[437,230],[441,230],[452,235],[440,230],[429,230],[465,236],[464,2],[459,235],[461,237],[460,235],[453,235],[454,235],[456,235],[458,235],[462,237],[463,237],[455,237],[457,237],[185,238],[466,239],[205,240],[204,241],[467,162],[469,242],[468,243],[470,2],[472,244],[471,2],[207,2],[473,2],[475,2],[474,2],[476,2],[477,2],[478,245],[479,2],[480,246],[63,2],[88,2],[215,2],[421,2],[67,2],[199,247],[198,248],[413,249],[410,250],[411,251],[412,2],[64,252],[409,253],[61,2],[62,2],[12,2],[11,2],[2,2],[13,2],[14,2],[15,2],[16,2],[17,2],[18,2],[19,2],[20,2],[3,2],[21,2],[22,2],[4,2],[23,2],[27,2],[24,2],[25,2],[26,2],[28,2],[29,2],[30,2],[5,2],[31,2],[32,2],[33,2],[34,2],[6,2],[38,2],[35,2],[36,2],[37,2],[39,2],[7,2],[40,2],[45,2],[46,2],[41,2],[42,2],[43,2],[44,2],[8,2],[50,2],[47,2],[48,2],[49,2],[51,2],[9,2],[52,2],[53,2],[54,2],[56,2],[55,2],[57,2],[58,2],[10,2],[59,2],[1,2],[60,2],[104,254],[114,255],[103,254],[124,256],[95,257],[94,258],[123,164],[117,259],[122,260],[97,261],[111,262],[96,263],[120,264],[92,265],[91,164],[121,266],[93,267],[98,268],[99,2],[102,268],[89,2],[125,269],[115,270],[106,271],[107,272],[109,273],[105,274],[108,275],[118,164],[100,276],[101,277],[110,278],[90,279],[113,270],[112,268],[116,2],[119,280],[65,281],[66,2],[69,282],[70,283],[68,284],[71,285]],"latestChangedDtsFile":"./dist/index.d.ts","version":"5.9.3"} \ No newline at end of file From 62a3e5768e762705dab09cfd015799a18434ebae Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Feb 2026 12:49:44 +0100 Subject: [PATCH 018/128] docs: add future work item for undeclared BSON type names in TS definitions The bsonToTypeScriptMap emits non-built-in type names (ObjectId, Binary, Timestamp, etc.) without corresponding import statements or declare stubs. Currently harmless since the output is for display/hover only, but should be addressed if the TS definition is ever consumed by a real TS language service. Addresses PR #506 review comment from copilot. --- .../json/data-api/autocomplete/future-work.md | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/utils/json/data-api/autocomplete/future-work.md b/src/utils/json/data-api/autocomplete/future-work.md index 6e77d2913..1ee321564 100644 --- a/src/utils/json/data-api/autocomplete/future-work.md +++ b/src/utils/json/data-api/autocomplete/future-work.md @@ -138,3 +138,47 @@ This is a **breaking change** to the `FieldEntry` interface. Affected consumers: - `SchemaAnalyzer.ts` (returns `FieldEntry[]` via `getKnownFields`) **Recommendation:** Defer until the completion provider is built. The ambiguity only matters for fields with literal dots, which are uncommon. When fixing, do it as a single atomic change across all consumers. + +--- + +## 4. TypeScript definition output references undeclared BSON type names + +**Severity:** Low — the TS definition is for display/hover only, not compiled or type-checked +**File:** `toTypeScriptDefinition.ts` — `bsonToTypeScriptMap` +**When to fix:** Before the TS definition is used in a context where type correctness matters (e.g., Monaco intellisense with an actual TS language service) + +### Problem + +The BSON-to-TypeScript type mapping emits non-built-in type names such as `ObjectId`, `Binary`, `Timestamp`, `MinKey`, `MaxKey`, `Code`, `DBRef`, and `UUID`. These are MongoDB BSON driver types, but the generated definition string doesn't include `import` statements or `declare` stubs for them. + +If the output is ever fed to a TypeScript compiler or language service (e.g., Monaco with full TS checking), it will report "Cannot find name 'ObjectId'" etc. + +### Current state + +The generated output is used for documentation/hover display only — it's rendered as syntax-highlighted text, not compiled. So this is purely cosmetic today. + +### Proposed fix (when needed) + +**Option A — Emit `import type`:** +```typescript +import type { ObjectId, Binary, Timestamp, MinKey, MaxKey, Code, DBRef, UUID } from 'mongodb'; +``` +Only include types that actually appear in the schema. + +**Option B — Emit `declare type` stubs:** +```typescript +declare type ObjectId = { toString(): string }; +declare type Binary = { length(): number }; +// ... etc. +``` +Lightweight, no dependency on the `mongodb` package. + +**Option C — Map everything to primitive types:** +```typescript +ObjectId → string // (its string representation) +Binary → Uint8Array +Timestamp → { t: number; i: number } +``` +Loses semantic precision but avoids the undeclared-type problem entirely. + +**Recommendation:** Option A is the most correct approach. Collect the set of non-built-in types actually used in the schema, then prepend a single `import type` line. Defer until the output is consumed by a real TS language service. From 4b3dd00d88d117d6b37cf50f690563dca697cb28 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Feb 2026 12:50:33 +0100 Subject: [PATCH 019/128] fix: toInterfaceName handles digit-leading and separator-only collection names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Prefix with _ when PascalCase result starts with a digit (e.g. '123abc' → '_123abcDocument') - Fall back to 'CollectionDocument' when name is empty or only separators - Filter empty segments from split result - Add tests for edge cases Addresses PR #506 review comment from copilot. --- .../toTypeScriptDefinition.test.ts | 24 +++++++++++++++++++ .../autocomplete/toTypeScriptDefinition.ts | 15 +++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.test.ts b/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.test.ts index db2ed0176..a5628e7f1 100644 --- a/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.test.ts +++ b/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.test.ts @@ -207,6 +207,30 @@ describe('toTypeScriptDefinition', () => { ); }); + it('prefixes with _ when collection name starts with a digit', () => { + expect(toTypeScriptDefinition({ 'x-documentsInspected': 0 }, '123abc')).toContain( + 'interface _123abcDocument', + ); + expect(toTypeScriptDefinition({ 'x-documentsInspected': 0 }, '99_bottles')).toContain( + 'interface _99BottlesDocument', + ); + }); + + it('falls back to CollectionDocument when name is only separators', () => { + expect(toTypeScriptDefinition({ 'x-documentsInspected': 0 }, '---')).toContain( + 'interface CollectionDocument', + ); + expect(toTypeScriptDefinition({ 'x-documentsInspected': 0 }, '_ _ _')).toContain( + 'interface CollectionDocument', + ); + }); + + it('falls back to CollectionDocument for empty string', () => { + expect(toTypeScriptDefinition({ 'x-documentsInspected': 0 }, '')).toContain( + 'interface CollectionDocument', + ); + }); + describe('special character field names', () => { function makeSchemaWithField(fieldName: string): JSONSchema { return { diff --git a/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.ts b/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.ts index 559162fc0..5f23cf652 100644 --- a/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.ts +++ b/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.ts @@ -70,16 +70,29 @@ function safePropertyName(name: string): string { /** * Converts a collection name to PascalCase and appends "Document". + * If the result would start with a digit, a leading `_` is prepended. + * If the collection name contains only separators or is empty, falls back to "CollectionDocument". + * * Examples: * - "users" → "UsersDocument" * - "order_items" → "OrderItemsDocument" + * - "123abc" → "_123abcDocument" + * - "---" → "CollectionDocument" */ function toInterfaceName(collectionName: string): string { const pascal = collectionName .split(/[_\-\s]+/) + .filter((s) => s.length > 0) .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1)) .join(''); - return `${pascal}Document`; + + if (pascal.length === 0) { + return 'CollectionDocument'; + } + + // Prefix with _ if the first character is a digit (invalid TS identifier start) + const prefix = /^[0-9]/.test(pascal) ? '_' : ''; + return `${prefix}${pascal}Document`; } /** From 37e64e5d8dfa7e4af384d4215b369508fe2b6bde Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Feb 2026 12:50:57 +0100 Subject: [PATCH 020/128] docs: clarify boolean JSONSchemaRef safety in getKnownFields Add comment explaining why the cast to JSONSchema is safe: our SchemaAnalyzer never produces boolean schema refs. Notes that a typeof guard should be added if the function is ever reused with externally-sourced schemas. Addresses PR #506 review comment from copilot. --- packages/schema-analyzer/src/getKnownFields.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/schema-analyzer/src/getKnownFields.ts b/packages/schema-analyzer/src/getKnownFields.ts index d3f12ee89..5c5f82bdc 100644 --- a/packages/schema-analyzer/src/getKnownFields.ts +++ b/packages/schema-analyzer/src/getKnownFields.ts @@ -58,6 +58,13 @@ export function getKnownFields(schema: JSONSchema): FieldEntry[] { const queue: Denque = new Denque(); // Initialize the queue with root properties + // + // Note: JSON Schema allows boolean values as schema references (true = accept all, + // false = reject all), but our SchemaAnalyzer never produces boolean refs — it always + // emits full schema objects. The cast to JSONSchema below is therefore safe for our + // use case. If this function were ever reused with externally-sourced schemas, a + // `typeof propSchema === 'boolean'` guard should be added here and in the nested + // property loop below. if (schema.properties) { for (const propName of Object.keys(schema.properties)) { const propSchema = schema.properties[propName] as JSONSchema; From b17e9cc2cead212b66382f5bf08c4c2409affa98 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Feb 2026 12:52:13 +0100 Subject: [PATCH 021/128] =?UTF-8?q?fix:=20insertText=20escaping=20?= =?UTF-8?q?=E2=80=94=20use=20identifier=20check=20+=20escape=20quotes/back?= =?UTF-8?q?slashes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace SPECIAL_CHARS_PATTERN with JS_IDENTIFIER_PATTERN for proper identifier validity check (catches dashes, brackets, digits, quotes, etc.) - Escape embedded double quotes and backslashes when quoting insertText - Add tests for all edge cases (dashes, brackets, digits, quotes, backslashes) - Mark future-work item #1 as resolved; item #2 (referenceText/$getField) remains open for aggregation completion provider phase Addresses PR #506 review comment from copilot. --- .../json/data-api/autocomplete/future-work.md | 39 +++------------- .../toFieldCompletionItems.test.ts | 44 +++++++++++++++++++ .../autocomplete/toFieldCompletionItems.ts | 27 +++++++----- 3 files changed, 65 insertions(+), 45 deletions(-) diff --git a/src/utils/json/data-api/autocomplete/future-work.md b/src/utils/json/data-api/autocomplete/future-work.md index 1ee321564..7554a383b 100644 --- a/src/utils/json/data-api/autocomplete/future-work.md +++ b/src/utils/json/data-api/autocomplete/future-work.md @@ -5,42 +5,13 @@ These must be resolved before the completion providers ship to users. --- -## 1. `SPECIAL_CHARS_PATTERN` is incomplete + `insertText` quoting doesn't escape +## ~~1. `SPECIAL_CHARS_PATTERN` is incomplete + `insertText` quoting doesn't escape~~ ✅ RESOLVED -**Severity:** Medium — will produce broken query expressions for real-world field names -**File:** `toFieldCompletionItems.ts` — `SPECIAL_CHARS_PATTERN` and `insertText` construction -**When to fix:** Before the `CompletionItemProvider` is wired up +**Resolved in:** PR #506 (commit addressing copilot review comment) -### Problem - -`SPECIAL_CHARS_PATTERN` (`/[.$\s]/`) only catches dots, `$`, and whitespace. MongoDB field names can also contain: - -| Character | Example field name | Current behavior | -| ---------------- | ------------------ | ----------------------------------------------- | -| Dash `-` | `order-items` | Inserted unquoted → breaks JSON key context | -| Brackets `[]` | `items[0]` | Inserted unquoted | -| Double quote `"` | `say"hi"` | Wrapped as `"say"hi""` → broken string | -| Single quote `'` | `it's` | Inserted unquoted (may break some contexts) | -| Backslash `\` | `back\slash` | Wrapped as `"back\slash"` → unescaped backslash | - -Additionally, when quoting _is_ triggered, the current logic (`"${entry.path}"`) does not escape embedded `"` or `\` inside the value. - -### Proposed fix - -1. Replace `SPECIAL_CHARS_PATTERN` with an identifier check (same as `safePropertyName` in `toTypeScriptDefinition.ts`): - ```typescript - const JS_IDENTIFIER = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/; - const needsQuoting = !JS_IDENTIFIER.test(entry.path); - ``` -2. When quoting, escape the content: - ```typescript - const escaped = entry.path.replace(/\\/g, '\\\\').replace(/"/g, '\\"'); - insertText: needsQuoting ? `"${escaped}"` : entry.path, - ``` - -### Note on display vs insert - -The `fieldName` property intentionally stays unescaped (human-readable) for the completion list label. Only `insertText` gets escaped — this is by design, so users see clean names in the dropdown and the escaped form is inserted on selection. +Replaced `SPECIAL_CHARS_PATTERN` with `JS_IDENTIFIER_PATTERN` — a proper identifier validity check. +Added `\` → `\\` and `"` → `\"` escaping when quoting `insertText`. +Tests cover dashes, brackets, digits, embedded quotes, and backslashes. --- diff --git a/src/utils/json/data-api/autocomplete/toFieldCompletionItems.test.ts b/src/utils/json/data-api/autocomplete/toFieldCompletionItems.test.ts index 947b90629..37a7ecc4e 100644 --- a/src/utils/json/data-api/autocomplete/toFieldCompletionItems.test.ts +++ b/src/utils/json/data-api/autocomplete/toFieldCompletionItems.test.ts @@ -39,6 +39,50 @@ describe('toFieldCompletionItems', () => { expect(result[1].insertText).toBe('"user.profile.bio"'); }); + it('quotes field names with dashes', () => { + const fields: FieldEntry[] = [{ path: 'order-items', type: 'string', bsonType: 'string' }]; + const result = toFieldCompletionItems(fields); + expect(result[0].insertText).toBe('"order-items"'); + expect(result[0].fieldName).toBe('order-items'); // display stays unescaped + }); + + it('quotes field names with brackets', () => { + const fields: FieldEntry[] = [{ path: 'items[0]', type: 'string', bsonType: 'string' }]; + const result = toFieldCompletionItems(fields); + expect(result[0].insertText).toBe('"items[0]"'); + }); + + it('quotes field names starting with a digit', () => { + const fields: FieldEntry[] = [{ path: '123abc', type: 'string', bsonType: 'string' }]; + const result = toFieldCompletionItems(fields); + expect(result[0].insertText).toBe('"123abc"'); + }); + + it('escapes embedded double quotes in insertText', () => { + const fields: FieldEntry[] = [{ path: 'say"hi"', type: 'string', bsonType: 'string' }]; + const result = toFieldCompletionItems(fields); + expect(result[0].insertText).toBe('"say\\"hi\\""'); + expect(result[0].fieldName).toBe('say"hi"'); // display stays unescaped + }); + + it('escapes backslashes in insertText', () => { + const fields: FieldEntry[] = [{ path: 'back\\slash', type: 'string', bsonType: 'string' }]; + const result = toFieldCompletionItems(fields); + expect(result[0].insertText).toBe('"back\\\\slash"'); + }); + + it('does not quote valid identifiers', () => { + const fields: FieldEntry[] = [ + { path: 'name', type: 'string', bsonType: 'string' }, + { path: '_id', type: 'string', bsonType: 'objectid' }, + { path: '$type', type: 'string', bsonType: 'string' }, + ]; + const result = toFieldCompletionItems(fields); + expect(result[0].insertText).toBe('name'); + expect(result[1].insertText).toBe('_id'); + expect(result[2].insertText).toBe('$type'); + }); + it('adds $ prefix to referenceText', () => { const fields: FieldEntry[] = [ { path: 'age', type: 'number', bsonType: 'int32' }, diff --git a/src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts b/src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts index 4998dad64..63e85bd92 100644 --- a/src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts +++ b/src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts @@ -40,17 +40,14 @@ export interface FieldCompletionData { } /** - * Characters that require quoting in a field name for insert text. + * Matches valid JavaScript/TypeScript identifiers. + * A valid identifier starts with a letter, underscore, or dollar sign, + * followed by zero or more letters, digits, underscores, or dollar signs. * - * TODO: This pattern currently only catches dots, `$`, and whitespace. It misses other - * characters that are valid in MongoDB field names but problematic in query expressions: - * dashes (`-`), brackets (`[`, `]`), quotes (`"`, `'`), and backslashes (`\`). - * Additionally, the quoting logic (`"${path}"`) does not escape embedded double quotes - * or backslashes inside the field name. Both gaps should be addressed when the - * CompletionItemProvider is wired up — the fix is to (1) widen this to a "is valid - * unquoted identifier" check and (2) escape `"` → `\"` and `\` → `\\` in insertText. + * Field names that do NOT match this pattern must be quoted and escaped + * in `insertText` to produce valid query expressions. */ -const SPECIAL_CHARS_PATTERN = /[.$\s]/; +const JS_IDENTIFIER_PATTERN = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/; /** * Converts an array of FieldEntry objects into completion-ready FieldCompletionData items. @@ -61,14 +58,22 @@ const SPECIAL_CHARS_PATTERN = /[.$\s]/; export function toFieldCompletionItems(fields: FieldEntry[]): FieldCompletionData[] { return fields.map((entry) => { const displayType = BSONTypes.toDisplayString(entry.bsonType as BSONTypes); - const needsQuoting = SPECIAL_CHARS_PATTERN.test(entry.path); + const needsQuoting = !JS_IDENTIFIER_PATTERN.test(entry.path); + + let insertText: string; + if (needsQuoting) { + const escaped = entry.path.replace(/\\/g, '\\\\').replace(/"/g, '\\"'); + insertText = `"${escaped}"`; + } else { + insertText = entry.path; + } return { fieldName: entry.path, displayType, bsonType: entry.bsonType, isSparse: entry.isSparse ?? false, - insertText: needsQuoting ? `"${entry.path}"` : entry.path, + insertText, referenceText: `$${entry.path}`, }; }); From 35a13a1d5bacb82afaddfe484812339b8d1373d1 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Feb 2026 13:03:42 +0100 Subject: [PATCH 022/128] refactor: streamline TypeScript definition tests for improved readability --- src/utils/json/data-api/autocomplete/future-work.md | 6 ++++++ .../autocomplete/toTypeScriptDefinition.test.ts | 12 +++--------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/utils/json/data-api/autocomplete/future-work.md b/src/utils/json/data-api/autocomplete/future-work.md index 7554a383b..cac0d4ab0 100644 --- a/src/utils/json/data-api/autocomplete/future-work.md +++ b/src/utils/json/data-api/autocomplete/future-work.md @@ -131,25 +131,31 @@ The generated output is used for documentation/hover display only — it's rende ### Proposed fix (when needed) **Option A — Emit `import type`:** + ```typescript import type { ObjectId, Binary, Timestamp, MinKey, MaxKey, Code, DBRef, UUID } from 'mongodb'; ``` + Only include types that actually appear in the schema. **Option B — Emit `declare type` stubs:** + ```typescript declare type ObjectId = { toString(): string }; declare type Binary = { length(): number }; // ... etc. ``` + Lightweight, no dependency on the `mongodb` package. **Option C — Map everything to primitive types:** + ```typescript ObjectId → string // (its string representation) Binary → Uint8Array Timestamp → { t: number; i: number } ``` + Loses semantic precision but avoids the undeclared-type problem entirely. **Recommendation:** Option A is the most correct approach. Collect the set of non-built-in types actually used in the schema, then prepend a single `import type` line. Defer until the output is consumed by a real TS language service. diff --git a/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.test.ts b/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.test.ts index a5628e7f1..d003b9ded 100644 --- a/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.test.ts +++ b/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.test.ts @@ -208,27 +208,21 @@ describe('toTypeScriptDefinition', () => { }); it('prefixes with _ when collection name starts with a digit', () => { - expect(toTypeScriptDefinition({ 'x-documentsInspected': 0 }, '123abc')).toContain( - 'interface _123abcDocument', - ); + expect(toTypeScriptDefinition({ 'x-documentsInspected': 0 }, '123abc')).toContain('interface _123abcDocument'); expect(toTypeScriptDefinition({ 'x-documentsInspected': 0 }, '99_bottles')).toContain( 'interface _99BottlesDocument', ); }); it('falls back to CollectionDocument when name is only separators', () => { - expect(toTypeScriptDefinition({ 'x-documentsInspected': 0 }, '---')).toContain( - 'interface CollectionDocument', - ); + expect(toTypeScriptDefinition({ 'x-documentsInspected': 0 }, '---')).toContain('interface CollectionDocument'); expect(toTypeScriptDefinition({ 'x-documentsInspected': 0 }, '_ _ _')).toContain( 'interface CollectionDocument', ); }); it('falls back to CollectionDocument for empty string', () => { - expect(toTypeScriptDefinition({ 'x-documentsInspected': 0 }, '')).toContain( - 'interface CollectionDocument', - ); + expect(toTypeScriptDefinition({ 'x-documentsInspected': 0 }, '')).toContain('interface CollectionDocument'); }); describe('special character field names', () => { From 1cb9e5b78fd5ab8da7e443c2cf0b02a617d7afb9 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Feb 2026 13:37:07 +0100 Subject: [PATCH 023/128] docs: add terminology guidelines for DocumentDB and MongoDB API usage --- .github/copilot-instructions.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index e5a438ee1..78b2d1f06 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -178,6 +178,22 @@ For Discovery View, both `treeId` and `clusterId` are sanitized (all `/` replace See `src/tree/models/BaseClusterModel.ts` and `docs/analysis/08-cluster-model-simplification-plan.md` for details. +## Terminology + +This is a **DocumentDB** extension that uses the **MongoDB-compatible wire protocol**. + +- Use **"DocumentDB"** when referring to the database service itself. +- Use **"MongoDB API"** or **"DocumentDB API"** when referring to the wire protocol, query language, or API compatibility layer. +- **Never use "MongoDB" alone** as a product name in code, comments, docs, or user-facing strings. + +| ✅ Do | ❌ Don't | +| ---------------------------------------------------- | -------------------------------- | +| `// Query operators supported by the DocumentDB API` | `// MongoDB query operators` | +| `// BSON types per the MongoDB API spec` | `// Uses MongoDB's $match stage` | +| `documentdbQuery` (variable name) | `mongoQuery` | + +This applies to: code comments, JSDoc/TSDoc, naming (prefer `documentdb` prefix), user-facing strings, docs, and test descriptions. + ## Additional Patterns For detailed patterns, see: From 43915a576782dcb495f6ec7d1681ae3a9d4798c7 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Feb 2026 14:25:57 +0100 Subject: [PATCH 024/128] refactor: replace 'console' assert with 'node:assert/strict' for improved consistency --- packages/schema-analyzer/src/SchemaAnalyzer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/schema-analyzer/src/SchemaAnalyzer.ts b/packages/schema-analyzer/src/SchemaAnalyzer.ts index b26f6fa76..8f24d532a 100644 --- a/packages/schema-analyzer/src/SchemaAnalyzer.ts +++ b/packages/schema-analyzer/src/SchemaAnalyzer.ts @@ -3,9 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { assert } from 'console'; import Denque from 'denque'; import { type Document, type WithId } from 'mongodb'; +import assert from 'node:assert/strict'; import { BSONTypes } from './BSONTypes'; import { type JSONSchema, type JSONSchemaRef } from './JSONSchema'; import { type FieldEntry, getKnownFields as getKnownFieldsFromSchema } from './getKnownFields'; From 75536e9e160d8961a33b58aadb65c03269586d08 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Feb 2026 14:52:37 +0100 Subject: [PATCH 025/128] refactor: update documentation to consistently reference DocumentDB API alongside MongoDB API --- .github/copilot-instructions.md | 2 +- packages/schema-analyzer/README.md | 6 +++--- packages/schema-analyzer/package.json | 2 +- packages/schema-analyzer/src/BSONTypes.ts | 12 ++++++------ packages/schema-analyzer/src/ValueFormatters.ts | 6 +++--- packages/schema-analyzer/src/getKnownFields.ts | 6 +++--- src/utils/json/data-api/autocomplete/future-work.md | 4 ++-- .../data-api/autocomplete/toTypeScriptDefinition.ts | 2 +- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 78b2d1f06..6a7852567 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,6 +1,6 @@ # GitHub Copilot Instructions for vscode-documentdb -VS Code Extension for Azure Cosmos DB and MongoDB. TypeScript (strict mode), React webviews, Jest testing. +VS Code Extension for Azure Cosmos DB and the MongoDB API. TypeScript (strict mode), React webviews, Jest testing. ## Critical Build Commands diff --git a/packages/schema-analyzer/README.md b/packages/schema-analyzer/README.md index 145611fe1..2010f2e7a 100644 --- a/packages/schema-analyzer/README.md +++ b/packages/schema-analyzer/README.md @@ -1,17 +1,17 @@ # @vscode-documentdb/schema-analyzer -Incremental JSON Schema analyzer for MongoDB and Azure Cosmos DB documents. Processes documents one at a time (or in batches) and produces an extended JSON Schema with statistical metadata — field occurrence counts, BSON type distributions, min/max values, and array length stats. +Incremental JSON Schema analyzer for DocumentDB API and MongoDB API documents. Processes documents one at a time (or in batches) and produces an extended JSON Schema with statistical metadata — field occurrence counts, BSON type distributions, min/max values, and array length stats. > **Note:** This package is not yet published to npm. We plan to publish it once the API stabilizes. For now, it is consumed internally via npm workspaces within the [vscode-documentdb](https://github.com/microsoft/vscode-documentdb) repository. ## Overview -The `SchemaAnalyzer` incrementally builds a JSON Schema by inspecting MongoDB/DocumentDB documents. It is designed for scenarios where documents arrive over time (streaming, pagination) and the schema needs to evolve as new documents are observed. +The `SchemaAnalyzer` incrementally builds a JSON Schema by inspecting DocumentDB API / MongoDB API documents. It is designed for scenarios where documents arrive over time (streaming, pagination) and the schema needs to evolve as new documents are observed. Key capabilities: - **Incremental analysis** — add documents one at a time or in batches; the schema updates in place. -- **BSON type awareness** — recognizes all MongoDB BSON types (`ObjectId`, `Decimal128`, `Binary`, `UUID`, etc.) and annotates them with `x-bsonType`. +- **BSON type awareness** — recognizes BSON types defined by the MongoDB API (`ObjectId`, `Decimal128`, `Binary`, `UUID`, etc.) and annotates them with `x-bsonType`. - **Statistical extensions** — tracks field occurrence (`x-occurrence`), type frequency (`x-typeOccurrence`), min/max values, string lengths, array sizes, and document counts (`x-documentsInspected`). - **Known fields extraction** — derives a flat list of known field paths with their types and occurrence probabilities, useful for autocomplete and UI rendering. - **Version tracking & caching** — a monotonic version counter enables efficient cache invalidation for derived data like `getKnownFields()`. diff --git a/packages/schema-analyzer/package.json b/packages/schema-analyzer/package.json index 78a54cc65..3751cdba2 100644 --- a/packages/schema-analyzer/package.json +++ b/packages/schema-analyzer/package.json @@ -1,7 +1,7 @@ { "name": "@vscode-documentdb/schema-analyzer", "version": "1.0.0", - "description": "Incremental JSON Schema analyzer for MongoDB/DocumentDB documents with statistical extensions", + "description": "Incremental JSON Schema analyzer for DocumentDB API / MongoDB API documents with statistical extensions", "main": "dist/index.js", "types": "dist/index.d.ts", "files": [ diff --git a/packages/schema-analyzer/src/BSONTypes.ts b/packages/schema-analyzer/src/BSONTypes.ts index 17c8ff45d..b8fb92f16 100644 --- a/packages/schema-analyzer/src/BSONTypes.ts +++ b/packages/schema-analyzer/src/BSONTypes.ts @@ -20,8 +20,8 @@ import { } from 'mongodb'; /** - * Represents the different data types that can be stored in a MongoDB document. - * The string representation is casesensitive and should match the MongoDB documentation. + * Represents the different data types that can be stored in a DocumentDB API / MongoDB API document. + * The string representation is case-sensitive and should match the MongoDB API documentation. * https://www.mongodb.com/docs/manual/reference/bson-types/ */ export enum BSONTypes { @@ -93,8 +93,8 @@ export namespace BSONTypes { } /** - * Converts a MongoDB data type to a case sensitive JSON data type - * @param type The MongoDB data type + * Converts a MongoDB API data type to a case-sensitive JSON data type + * @param type The MongoDB API data type * @returns A corresponding JSON data type (please note: it's case sensitive) */ export function toJSONType(type: BSONTypes): string { @@ -141,8 +141,8 @@ export namespace BSONTypes { } /** - * Accepts a value from a MongoDB 'Document' object and returns the inferred type. - * @param value The value of a field in a MongoDB 'Document' object + * Accepts a value from a MongoDB API `Document` object and returns the inferred type. + * @param value The value of a field in a MongoDB API `Document` object * @returns */ export function inferType(value: unknown): BSONTypes { diff --git a/packages/schema-analyzer/src/ValueFormatters.ts b/packages/schema-analyzer/src/ValueFormatters.ts index 8d770e318..7f9e8e5fa 100644 --- a/packages/schema-analyzer/src/ValueFormatters.ts +++ b/packages/schema-analyzer/src/ValueFormatters.ts @@ -7,13 +7,13 @@ import { type Binary, type BSONRegExp, type ObjectId } from 'mongodb'; import { BSONTypes } from './BSONTypes'; /** - * Converts a MongoDB value to its display string representation based on its type. + * Converts a MongoDB API value to its display string representation based on its type. * * @param value - The value to be converted to a display string. - * @param type - The MongoDB data type of the value. + * @param type - The MongoDB API data type of the value. * @returns The string representation of the value. * - * The function handles various MongoDB data types including: + * The function handles various MongoDB API data types including: * - String * - Number, Int32, Double, Decimal128, Long * - Boolean diff --git a/packages/schema-analyzer/src/getKnownFields.ts b/packages/schema-analyzer/src/getKnownFields.ts index 5c5f82bdc..f5da314b6 100644 --- a/packages/schema-analyzer/src/getKnownFields.ts +++ b/packages/schema-analyzer/src/getKnownFields.ts @@ -19,8 +19,8 @@ export interface FieldEntry { * True if this field was not present in every inspected document * (x-occurrence < parent x-documentsInspected). * - * This is a statistical observation, not a schema constraint — in the - * MongoDB API / DocumentDB API all fields are implicitly optional. + * This is a statistical observation, not a schema constraint — in the MongoDB API / DocumentDB API, + * all fields are implicitly optional. */ isSparse?: boolean; /** If the field is an array, the dominant element BSON type */ @@ -93,7 +93,7 @@ export function getKnownFields(schema: JSONSchema): FieldEntry[] { // itself contains a literal dot. For example, a root-level field named // "a.b" produces path "a.b", indistinguishable from a nested field // { a: { b: ... } }. Fields with literal dots in their names were - // prohibited before MongoDB 3.6 and remain rare in practice. + // prohibited before MongoDB API 3.6 and remain rare in practice. // // Future improvement: change `path` from `string` to `string[]` // (segment array) to preserve the distinction between nesting and diff --git a/src/utils/json/data-api/autocomplete/future-work.md b/src/utils/json/data-api/autocomplete/future-work.md index cac0d4ab0..660113c7d 100644 --- a/src/utils/json/data-api/autocomplete/future-work.md +++ b/src/utils/json/data-api/autocomplete/future-work.md @@ -55,7 +55,7 @@ referenceText: needsQuoting ## 3. `FieldEntry.path` dot-concatenation is ambiguous for literal dots -**Severity:** Low (rare in practice) — fields with literal dots were prohibited before MongoDB 3.6 +**Severity:** Low (rare in practice) — fields with literal dots were prohibited before MongoDB API 3.6 **File:** `getKnownFields.ts` — path concatenation at `path: \`${path}.${childName}\``**When to fix:** When we encounter real-world schemas with literal dots, or during the next`FieldEntry` interface revision ### Problem @@ -120,7 +120,7 @@ This is a **breaking change** to the `FieldEntry` interface. Affected consumers: ### Problem -The BSON-to-TypeScript type mapping emits non-built-in type names such as `ObjectId`, `Binary`, `Timestamp`, `MinKey`, `MaxKey`, `Code`, `DBRef`, and `UUID`. These are MongoDB BSON driver types, but the generated definition string doesn't include `import` statements or `declare` stubs for them. +The BSON-to-TypeScript type mapping emits non-built-in type names such as `ObjectId`, `Binary`, `Timestamp`, `MinKey`, `MaxKey`, `Code`, `DBRef`, and `UUID`. These are MongoDB API BSON driver types, but the generated definition string doesn't include `import` statements or `declare` stubs for them. If the output is ever fed to a TypeScript compiler or language service (e.g., Monaco with full TS checking), it will report "Cannot find name 'ObjectId'" etc. diff --git a/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.ts b/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.ts index 5f23cf652..17328dfeb 100644 --- a/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.ts +++ b/src/utils/json/data-api/autocomplete/toTypeScriptDefinition.ts @@ -100,7 +100,7 @@ function toInterfaceName(collectionName: string): string { * produced by the SchemaAnalyzer. * * @param schema - The JSON Schema with x- extensions from SchemaAnalyzer - * @param collectionName - The MongoDB collection name, used to derive the interface name + * @param collectionName - The MongoDB API collection name, used to derive the interface name * @returns A formatted TypeScript interface definition string */ export function toTypeScriptDefinition(schema: JSONSchema, collectionName: string): string { From a44c90b2ec47ba128ed7379dc15d7ef6c3d7f3e1 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Thu, 19 Feb 2026 12:58:05 +0000 Subject: [PATCH 026/128] feat: add DocumentDB constants package with operator metadata and documentation links - Introduced `docLinks.ts` for generating documentation URLs for DocumentDB operators. - Created `getFilteredCompletions.ts` to provide filtered access to operator entries based on meta tags and BSON type constraints. - Added `metaTags.ts` for categorizing operators with hierarchical meta tags. - Defined types for operators and completion filters in `types.ts`. - Configured TypeScript settings in `tsconfig.json` for the new package. - Updated `index.ts` to export new functionalities and constants. --- package-lock.json | 13 + package.json | 1 + packages/documentdb-constants/README.md | 74 + packages/documentdb-constants/jest.config.js | 8 + packages/documentdb-constants/package.json | 25 + .../resources/operator-reference.md | 4061 +++++++++++++++++ .../scripts/scrape-operator-docs.ts | 778 ++++ packages/documentdb-constants/src/docLinks.ts | 77 + .../src/getFilteredCompletions.ts | 76 + packages/documentdb-constants/src/index.ts | 71 + packages/documentdb-constants/src/metaTags.ts | 130 + packages/documentdb-constants/src/types.ts | 112 + packages/documentdb-constants/tsconfig.json | 20 + tsconfig.json | 2 +- 14 files changed, 5447 insertions(+), 1 deletion(-) create mode 100644 packages/documentdb-constants/README.md create mode 100644 packages/documentdb-constants/jest.config.js create mode 100644 packages/documentdb-constants/package.json create mode 100644 packages/documentdb-constants/resources/operator-reference.md create mode 100644 packages/documentdb-constants/scripts/scrape-operator-docs.ts create mode 100644 packages/documentdb-constants/src/docLinks.ts create mode 100644 packages/documentdb-constants/src/getFilteredCompletions.ts create mode 100644 packages/documentdb-constants/src/index.ts create mode 100644 packages/documentdb-constants/src/metaTags.ts create mode 100644 packages/documentdb-constants/src/types.ts create mode 100644 packages/documentdb-constants/tsconfig.json diff --git a/package-lock.json b/package-lock.json index 06ce802e7..fb55eb5d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,6 +29,7 @@ "@mongodb-js/explain-plan-helper": "1.4.24", "@trpc/client": "~11.10.0", "@trpc/server": "~11.10.0", + "@vscode-documentdb/documentdb-constants": "*", "@vscode-documentdb/schema-analyzer": "*", "@vscode/l10n": "~0.0.18", "antlr4ts": "^0.5.0-alpha.4", @@ -7311,6 +7312,10 @@ "win32" ] }, + "node_modules/@vscode-documentdb/documentdb-constants": { + "resolved": "packages/documentdb-constants", + "link": true + }, "node_modules/@vscode-documentdb/schema-analyzer": { "resolved": "packages/schema-analyzer", "link": true @@ -22218,6 +22223,14 @@ "url": "https://github.com/sponsors/wooorm" } }, + "packages/documentdb-constants": { + "name": "@vscode-documentdb/documentdb-constants", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "ts-node": "^10.9.2" + } + }, "packages/schema-analyzer": { "name": "@vscode-documentdb/schema-analyzer", "version": "1.0.0", diff --git a/package.json b/package.json index 5071f6698..ec67c79ca 100644 --- a/package.json +++ b/package.json @@ -170,6 +170,7 @@ "@trpc/client": "~11.10.0", "@trpc/server": "~11.10.0", "@vscode/l10n": "~0.0.18", + "@vscode-documentdb/documentdb-constants": "*", "@vscode-documentdb/schema-analyzer": "*", "antlr4ts": "^0.5.0-alpha.4", "bson": "~7.0.0", diff --git a/packages/documentdb-constants/README.md b/packages/documentdb-constants/README.md new file mode 100644 index 000000000..2f2625ffd --- /dev/null +++ b/packages/documentdb-constants/README.md @@ -0,0 +1,74 @@ +# @vscode-documentdb/documentdb-constants + +Static operator metadata for all DocumentDB-supported operators, aggregation stages, accumulators, update operators, BSON type constructors, and system variables. + +## Purpose + +This package is the **single source of truth** for operator metadata when the connected database is DocumentDB. It provides: + +- `OperatorEntry` objects with value, description, snippet, documentation link, and type metadata +- Meta-tag based filtering (`getFilteredCompletions()`) for context-aware autocompletion +- Convenience presets for common completion contexts (filter bar, aggregation pipeline, etc.) +- Documentation URL generation (`getDocLink()`) + +## Data Source + +All operator data is derived from the official DocumentDB documentation: + +- **Compatibility reference:** [DocumentDB Query Language Compatibility](https://learn.microsoft.com/en-us/azure/documentdb/compatibility-query-language) — lists every operator with its support status across DocumentDB versions 5.0–8.0. +- **Per-operator docs:** [DocumentDB Operators](https://learn.microsoft.com/en-us/azure/documentdb/operators/) — individual pages with descriptions and syntax for each operator. +- **Source repository:** [MicrosoftDocs/azure-databases-docs](https://github.com/MicrosoftDocs/azure-databases-docs) — the GitHub repo containing the raw Markdown source for all documentation pages above (under `articles/documentdb/`). + +The scraper (`scripts/scrape-operator-docs.ts`) fetches data from these sources and generates the `resources/operator-reference.md` dump file that serves as the contract between the documentation and the TypeScript implementation. + +## Usage + +```typescript +import { + getFilteredCompletions, + getAllCompletions, + FILTER_COMPLETION_META, + STAGE_COMPLETION_META, +} from '@vscode-documentdb/documentdb-constants'; + +// Get operators for a filter/query context +const filterOps = getFilteredCompletions({ meta: FILTER_COMPLETION_META }); + +// Get operators for a specific BSON type +const stringOps = getFilteredCompletions({ + meta: FILTER_COMPLETION_META, + bsonTypes: ['string'], +}); + +// Get all stage names +const stages = getFilteredCompletions({ meta: STAGE_COMPLETION_META }); +``` + +## Scraper + +The operator data is sourced from the official DocumentDB documentation. To re-scrape: + +```bash +npm run scrape --workspace=@vscode-documentdb/documentdb-constants +``` + +This runs the scraper and then formats the output with Prettier. The scraper: + +1. **Verifies** upstream doc structure (early fail-fast) +2. **Extracts** all operators from the [compatibility page](https://learn.microsoft.com/en-us/azure/documentdb/compatibility-query-language) +3. **Fetches** per-operator documentation (descriptions, syntax) with a global file index fallback for operators filed in unexpected directories +4. **Generates** `resources/operator-reference.md` in a structured heading format (`### $operator` with description, syntax, and doc link) + +The dump serves as the authoritative reference for the TypeScript implementation. A Jest test (`test/operatorReference.test.ts`) will validate that the implementation matches the dump. + +## Structure + +| File | Purpose | +| --------------------------------- | -------------------------------------------- | +| `src/types.ts` | `OperatorEntry` interface and `MetaTag` type | +| `src/metaTags.ts` | Meta tag constants and completion presets | +| `src/docLinks.ts` | Documentation URL generation | +| `src/getFilteredCompletions.ts` | Primary consumer API: filter by meta tags | +| `src/index.ts` | Barrel exports for all public API | +| `resources/operator-reference.md` | Scraped operator dump (source of truth) | +| `scripts/scrape-operator-docs.ts` | Scraper script | diff --git a/packages/documentdb-constants/jest.config.js b/packages/documentdb-constants/jest.config.js new file mode 100644 index 000000000..388d1e1d1 --- /dev/null +++ b/packages/documentdb-constants/jest.config.js @@ -0,0 +1,8 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} **/ +module.exports = { + testEnvironment: 'node', + testMatch: ['/test/**/*.test.ts'], + transform: { + '^.+\\.tsx?$': ['ts-jest', {}], + }, +}; diff --git a/packages/documentdb-constants/package.json b/packages/documentdb-constants/package.json new file mode 100644 index 000000000..b38e59034 --- /dev/null +++ b/packages/documentdb-constants/package.json @@ -0,0 +1,25 @@ +{ + "name": "@vscode-documentdb/documentdb-constants", + "version": "1.0.0", + "description": "Static operator metadata for DocumentDB-supported operators, stages, accumulators, and BSON constructors", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist" + ], + "scripts": { + "build": "tsc -p .", + "clean": "rimraf dist tsconfig.tsbuildinfo", + "test": "jest --config jest.config.js", + "scrape": "ts-node scripts/scrape-operator-docs.ts && prettier --write resources/operator-reference.md" + }, + "repository": { + "type": "git", + "url": "https://github.com/microsoft/vscode-documentdb", + "directory": "packages/documentdb-constants" + }, + "license": "MIT", + "devDependencies": { + "ts-node": "^10.9.2" + } +} diff --git a/packages/documentdb-constants/resources/operator-reference.md b/packages/documentdb-constants/resources/operator-reference.md new file mode 100644 index 000000000..378839198 --- /dev/null +++ b/packages/documentdb-constants/resources/operator-reference.md @@ -0,0 +1,4061 @@ +# DocumentDB Operator Reference + + + + + +## Summary + +| Category | Listed | Total | +| ------------------------------------------------------------- | ------- | ------- | +| Comparison Query Operators | 8 | 8 | +| Logical Query Operators | 4 | 4 | +| Element Query Operators | 2 | 2 | +| Evaluation Query Operators | 5 | 6 | +| Geospatial Operators | 11 | 11 | +| Array Query Operators | 3 | 3 | +| Bitwise Query Operators | 4 | 4 | +| Projection Operators | 3 | 4 | +| Miscellaneous Query Operators | 3 | 3 | +| Field Update Operators | 9 | 9 | +| Array Update Operators | 12 | 12 | +| Bitwise Update Operators | 1 | 1 | +| Arithmetic Expression Operators | 16 | 16 | +| Array Expression Operators | 20 | 20 | +| Bitwise Operators | 4 | 4 | +| Boolean Expression Operators | 3 | 3 | +| Comparison Expression Operators | 7 | 7 | +| Custom Aggregation Expression Operators | 0 | 2 | +| Data Size Operators | 2 | 2 | +| Date Expression Operators | 22 | 22 | +| Literal Expression Operator | 1 | 1 | +| Miscellaneous Operators | 3 | 3 | +| Object Expression Operators | 3 | 3 | +| Set Expression Operators | 7 | 7 | +| String Expression Operators | 23 | 23 | +| Text Expression Operator | 0 | 1 | +| Timestamp Expression Operators | 2 | 2 | +| Trigonometry Expression Operators | 15 | 15 | +| Type Expression Operators | 11 | 11 | +| Accumulators ($group, $bucket, $bucketAuto, $setWindowFields) | 21 | 22 | +| Accumulators (in Other Stages) | 10 | 10 | +| Variable Expression Operators | 1 | 1 | +| Window Operators | 27 | 27 | +| Conditional Expression Operators | 3 | 3 | +| Aggregation Pipeline Stages | 35 | 42 | +| Variables in Aggregation Expressions | 7 | 10 | +| **Total** | **308** | **324** | + +## Comparison Query Operators + +### $eq + +- **Description:** The $eq query operator compares the value of a field to a specified value +- **Syntax:** + +```javascript +{ + field: { + $eq: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$eq + +### $gt + +- **Description:** The $gt query operator retrieves documents where the value of a field is greater than a specified value +- **Syntax:** + +```javascript +{ + field: { + $gt: value; + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$gt + +### $gte + +- **Description:** The $gte operator retrieves documents where the value of a field is greater than or equal to a specified value +- **Syntax:** + +```javascript +{ + field: { + $gte: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$gte + +### $in + +- **Description:** The $in operator matches value of a field against an array of specified values +- **Syntax:** + +```javascript +{ + field: { + $in: [listOfValues]; + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$in + +### $lt + +- **Description:** The $lt operator retrieves documents where the value of field is less than a specified value +- **Syntax:** + +```javascript +{ + field: { + $lt: value; + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$lt + +### $lte + +- **Description:** The $lte operator retrieves documents where the value of a field is less than or equal to a specified value +- **Syntax:** + +```javascript +{ + field: { + $lte: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$lte + +### $ne + +- **Description:** The $ne operator retrieves documents where the value of a field doesn't equal a specified value +- **Syntax:** + +```javascript +{ + field: { + $ne: value; + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$ne + +### $nin + +- **Description:** The $nin operator retrieves documents where the value of a field doesn't match a list of values +- **Syntax:** + +```javascript +{ + field: { + $nin: [ < listOfValues > ] + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$nin + +## Logical Query Operators + +### $and + +- **Description:** The $and operator joins multiple query clauses and returns documents that match all specified conditions. +- **Syntax:** + +```javascript +{ + $and: [{ + < expression1 > + }, { + < expression2 > + }, ..., { + < expressionN > + }] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/logical-query/$and + +### $not + +- **Description:** The $not operator performs a logical NOT operation on a specified expression, selecting documents that don't match the expression. +- **Syntax:** + +```javascript +{ + field: { + $not: { + < operator - expression > + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/logical-query/$not + +### $nor + +- **Description:** The $nor operator performs a logical NOR on an array of expressions and retrieves documents that fail all the conditions. +- **Syntax:** + +```javascript +{ + $nor: [{ + < expression1 > + }, { + < expression2 > + }, ..., { + < expressionN > + }] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/logical-query/$nor + +### $or + +- **Description:** The $or operator joins query clauses with a logical OR and returns documents that match at least one of the specified conditions. +- **Syntax:** + +```javascript +{ + $or: [{ + < expression1 > + }, { + < expression2 > + }, ..., { + < expressionN > + }] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/logical-query/$or + +## Element Query Operators + +### $exists + +- **Description:** The $exists operator retrieves documents that contain the specified field in their document structure. +- **Syntax:** + +```javascript +{ + : { $exists: } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/element-query/$exists + +### $type + +- **Description:** The $type operator retrieves documents if the chosen field is of the specified type. +- **Syntax:** + +```javascript +{ + : { $type: | } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/element-query/$type + +## Evaluation Query Operators + +### $expr + +- **Description:** The $expr operator allows the use of aggregation expressions within the query language, enabling complex field comparisons and calculations. +- **Syntax:** + +```javascript +{ + $expr: { } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/evaluation-query/$expr + +### $jsonSchema + +- **Description:** The $jsonSchema operator validates documents against a JSON Schema definition for data validation and structure enforcement. Discover supported features and limitations. +- **Syntax:** + +```javascript +db.createCollection('collectionName', { + validator: { + $jsonSchema: { + bsonType: 'object', + required: ['field1', 'field2'], + properties: { + field1: { + bsonType: 'string', + }, + field2: { + bsonType: 'int', + minimum: 0, + description: 'Description of field2 requirements', + }, + }, + }, + }, + validationLevel: 'strict', // Optional: "strict" or "moderate" + validationAction: 'error', // Optional: "error" or "warn" +}); +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/evaluation-query/$jsonschema + +### $mod + +- **Description:** The $mod operator performs a modulo operation on the value of a field and selects documents with a specified result. +- **Syntax:** + +```javascript +{ + : { $mod: [ , ] } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/evaluation-query/$mod + +### $regex + +- **Description:** The $regex operator provides regular expression capabilities for pattern matching in queries, allowing flexible string matching and searching. +- **Syntax:** + +```javascript +{ + : { $regex: , $options: } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/evaluation-query/$regex + +### $text + +- **Description:** The $text operator performs text search on the content of indexed string fields, enabling full-text search capabilities. +- **Syntax:** + +```javascript +{ + $text: { + $search: , + $language: , + $caseSensitive: , + $diacriticSensitive: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/evaluation-query/$text + +## Geospatial Operators + +### $geoIntersects + +- **Description:** The $geoIntersects operator selects documents whose location field intersects with a specified GeoJSON object. +- **Syntax:** + +```javascript +{ + : { + $geoIntersects: { + $geometry: { + type: , + coordinates: + } + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/geospatial/$geointersects + +### $geoWithin + +- **Description:** The $geoWithin operator selects documents whose location field is completely within a specified geometry. +- **Syntax:** + +```javascript +// Using $box +{ + : { + $geoWithin: { + $box: [ [ ], [ ] ] + } + } +} + +// Using $center +{ + : { + $geoWithin: { + $center: [ [ , ], ] + } + } +} + +// Using $geometry +{ + : { + $geoWithin: { + $geometry: { + type: , + coordinates: + } + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/geospatial/$geowithin + +### $box + +- **Description:** The $box operator defines a rectangular area for geospatial queries using coordinate pairs. +- **Syntax:** + +```javascript +{ + : { + $geoWithin: { + $box: [ + [, ], + [, ] + ] + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/geospatial/$box + +### $center + +- **Description:** The $center operator specifies a circle using legacy coordinate pairs for $geoWithin queries. +- **Syntax:** + +```javascript +{ + $geoWithin: { + $center: [ [ , ], ] + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/geospatial/$center + +### $centerSphere + +- **Description:** The $centerSphere operator specifies a circle using spherical geometry for $geoWithin queries. +- **Syntax:** + +```javascript +{ + $geoWithin: { + $centerSphere: [ [ , ], ] + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/geospatial/$centersphere + +### $geometry + +- **Description:** The $geometry operator specifies a GeoJSON geometry for geospatial queries. +- **Syntax:** + +```javascript +{ + $geometry: { + type: , + coordinates: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/geospatial/$geometry + +### $maxDistance + +- **Description:** The $maxDistance operator specifies the maximum distance that can exist between two points in a geospatial query. +- **Syntax:** + +```javascript +{ + : { + $near: { + $geometry: { + type: "Point", + coordinates: [, ] + }, + $maxDistance: + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/geospatial/$maxdistance + +### $minDistance + +- **Description:** The $minDistance operator specifies the minimum distance that must exist between two points in a geospatial query. +- **Syntax:** + +```javascript +{ + : { + $near: { + $geometry: { + type: "Point", + coordinates: [, ] + }, + $minDistance: + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/geospatial/$mindistance + +### $polygon + +- **Description:** The $polygon operator defines a polygon for geospatial queries, allowing you to find locations within an irregular shape. +- **Syntax:** + +```javascript +{ + : { + $geoWithin: { + $geometry: { + type: "Polygon", + coordinates: [ + [[, ], ..., [, ], [, ]] + ] + } + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/geospatial/$polygon + +### $near + +- **Description:** The $near operator returns documents with location fields that are near a specified point, sorted by distance. +- **Syntax:** + +```javascript +{ + : { + $near: { + $geometry: { + type: "Point", + coordinates: [, ] + }, + $maxDistance: , + $minDistance: + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/geospatial/$near + +### $nearSphere + +- **Description:** The $nearSphere operator returns documents whose location fields are near a specified point on a sphere, sorted by distance on a spherical surface. +- **Syntax:** + +```javascript +{ + : { + $nearSphere: { + $geometry: { + type: "Point", + coordinates: [, ] + }, + $maxDistance: , + $minDistance: + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/geospatial/$nearsphere + +## Array Query Operators + +### $all + +- **Description:** The $all operator helps finding array documents matching all the elements. +- **Syntax:** + +```javascript +db.collection.find({ + field : { + $all: [ < value1 > , < value2 > ] + } +}) +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-query/$all + +### $elemMatch + +- **Description:** The $elemmatch operator returns complete array, qualifying criteria with at least one matching array element. +- **Syntax:** + +```javascript +db.collection.find({ : { $elemMatch: { , , ... } } }) +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-query/$elemmatch + +### $size + +- **Description:** The $size operator is used to query documents where an array field has a specified number of elements. +- **Syntax:** + +```javascript +db.collection.find({ : { $size: } }) +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-query/$size + +## Bitwise Query Operators + +### $bitsAllClear + +- **Description:** The $bitsAllClear operator is used to match documents where all the bit positions specified in a bitmask are clear. +- **Syntax:** + +```javascript +{ + : { $bitsAllClear: } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/bitwise-query/$bitsallclear + +### $bitsAllSet + +- **Description:** The bitsAllSet command is used to match documents where all the specified bit positions are set. +- **Syntax:** + +```javascript +{ + : { $bitsAllSet: } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/bitwise-query/$bitsallset + +### $bitsAnyClear + +- **Description:** The $bitsAnyClear operator matches documents where any of the specified bit positions in a bitmask are clear. +- **Syntax:** + +```javascript +{ + : { $bitsAnyClear: } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/bitwise-query/$bitsanyclear + +### $bitsAnySet + +- **Description:** The $bitsAnySet operator returns documents where any of the specified bit positions are set to 1. +- **Syntax:** + +```javascript +{ + : { $bitsAnySet: [ ] } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/bitwise-query/$bitsanyset + +## Projection Operators + +### $ + +- **Description:** The $ positional operator identifies an element in an array to update without explicitly specifying the position of the element in the array. +- **Syntax:** + +```javascript +db.collection.updateOne( + { : }, + { : { ".$": } } +) +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$ + +### $elemMatch + +- **Description:** The $elemmatch operator returns complete array, qualifying criteria with at least one matching array element. +- **Syntax:** + +```javascript +db.collection.find({ : { $elemMatch: { , , ... } } }) +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-query/$elemmatch + +### $slice + +- **Description:** The $slice operator returns a subset of an array from any element onwards in the array. +- **Syntax:** + +```javascript +{ + $slice: [ , ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$slice + +## Miscellaneous Query Operators + +### $comment + +- **Description:** The $comment operator adds a comment to a query to help identify the query in logs and profiler output. +- **Syntax:** + +```javascript +{ + $comment: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/miscellaneous-query/$comment + +### $rand + +- **Description:** The $rand operator generates a random float value between 0 and 1. +- **Syntax:** + +```javascript +{ + $rand: { + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/miscellaneous-query/$rand + +### $natural + +- **Description:** The $natural operator forces the query to use the natural order of documents in a collection, providing control over document ordering and retrieval. +- **Syntax:** + +```javascript +{ + $natural: <1 | -1> +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/miscellaneous-query/$natural + +## Field Update Operators + +### $currentDate + +- **Description:** The $currentDate operator sets the value of a field to the current date, either as a Date or a timestamp. +- **Syntax:** + +```javascript +{ + $currentDate: { + : , + : , + ... + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/field-update/$currentdate + +### $inc + +- **Description:** The $inc operator increments the value of a field by a specified amount. +- **Syntax:** + +```javascript +{ + $inc: { + : , + : , + ... + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/field-update/$inc + +### $min + +- **Description:** Retrieves the minimum value for a specified field +- **Syntax:** + +```javascript +$min: +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$min + +### $max + +- **Description:** The $max operator returns the maximum value from a set of input values. +- **Syntax:** + +```javascript +$max: +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$max + +### $mul + +- **Description:** The $mul operator multiplies the value of a field by a specified number. +- **Syntax:** + +```javascript +{ + $mul: { + : , + : , + ... + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/field-update/$mul + +### $rename + +- **Description:** The $rename operator allows renaming fields in documents during update operations. +- **Syntax:** + +```javascript +{ + $rename: { + : , + : , + ... + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/field-update/$rename + +### $set + +- **Description:** The $set operator in Azure DocumentDB updates or creates a new field with a specified value +- **Syntax:** + +```javascript +{ + $set: { + newField: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$set + +### $setOnInsert + +- **Description:** The $setOnInsert operator sets field values only when an upsert operation results in an insert of a new document. +- **Syntax:** + +```javascript +{ + $setOnInsert: { + : , + : , + ... + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/field-update/$setoninsert + +### $unset + +- **Description:** The $unset stage in the aggregation pipeline is used to remove specified fields from documents. +- **Syntax:** + +```javascript +{ + $unset: "" | ["", "", ...] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$unset + +## Array Update Operators + +### $ + +- **Description:** The $ positional operator identifies an element in an array to update without explicitly specifying the position of the element in the array. +- **Syntax:** + +```javascript +db.collection.updateOne( + { : }, + { : { ".$": } } +) +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$ + +### $[] + +### $[identifier] + +### $addToSet + +- **Description:** The addToSet operator adds elements to an array if they don't already exist, while ensuring uniqueness of elements within the set. +- **Syntax:** + +```javascript +{ + $addToSet: { : } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$addtoset + +### $pop + +- **Description:** Removes the first or last element of an array. +- **Syntax:** + +```javascript +{ + $pop: { + : + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$pop + +### $pull + +- **Description:** Removes all instances of a value from an array. +- **Syntax:** + +```javascript +{ + $pull: { : } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$pull + +### $push + +- **Description:** The $push operator adds a specified value to an array within a document. +- **Syntax:** + +```javascript +db.collection.update({ + < query > +}, { + $push: { + < field >: < value > + } +}, { + < options > +}) +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$push + +### $pullAll + +- **Description:** The $pullAll operator is used to remove all instances of the specified values from an array. +- **Syntax:** + +```javascript +{ + $pullAll: { : [ , ] } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$pullall + +### $each + +- **Description:** The $each operator is used within an `$addToSet`or`$push` operation to add multiple elements to an array field in a single update operation. +- **Syntax:** + +```javascript +{ + $push: { + : { + $each: [ , ], + : , + : + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$each + +### $position + +### $slice + +- **Description:** The $slice operator returns a subset of an array from any element onwards in the array. +- **Syntax:** + +```javascript +{ + $slice: [ , ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$slice + +### $sort + +- **Description:** The $sort stage in the aggregation pipeline is used to order the documents in the pipeline by a specified field or fields. +- **Syntax:** + +```javascript +{ + $sort: { + < field1 >: < sort order > , + < field2 >: < sort order > + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$sort + +## Bitwise Update Operators + +### $bit + +- **Description:** The `$bit` operator is used to perform bitwise operations on integer values. +- **Syntax:** + +```javascript +{ + $bit: { + < field >: { + < operator >: < number > + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/bitwise-update/$bit + +## Arithmetic Expression Operators + +### $abs + +- **Description:** The $abs operator returns the absolute value of a number. +- **Syntax:** + +```javascript +{ + $abs: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/arithmetic-expression/$abs + +### $add + +- **Description:** The $add operator returns the sum of two numbers or the sum of a date and numbers. +- **Syntax:** + +```javascript +{ + $add: [ ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/arithmetic-expression/$add + +### $ceil + +- **Description:** The $ceil operator returns the smallest integer greater than or equal to the specified number. +- **Syntax:** + +```javascript +{ + $ceil: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/arithmetic-expression/$ceil + +### $divide + +- **Description:** The $divide operator divides two numbers and returns the quotient. +- **Syntax:** + +```javascript +{ + $divide: [ , ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/arithmetic-expression/$divide + +### $exp + +- **Description:** The $exp operator raises e to the specified exponent and returns the result +- **Syntax:** + +```javascript +{ + $exp: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/arithmetic-expression/$exp + +### $floor + +- **Description:** The $floor operator returns the largest integer less than or equal to the specified number +- **Syntax:** + +```javascript +{ + $floor: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/arithmetic-expression/$floor + +### $ln + +- **Description:** The $ln operator calculates the natural logarithm of the input +- **Syntax:** + +```javascript +{ + $ln: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/arithmetic-expression/$ln + +### $log + +- **Description:** The $log operator calculates the logarithm of a number in the specified base +- **Syntax:** + +```javascript +{ + $log: [ , ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/arithmetic-expression/$log + +### $log10 + +- **Description:** The $log10 operator calculates the log of a specified number in base 10 +- **Syntax:** + +```javascript +{ + $log10: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/arithmetic-expression/$log10 + +### $mod + +- **Description:** The $mod operator performs a modulo operation on the value of a field and selects documents with a specified result. +- **Syntax:** + +```javascript +{ + : { $mod: [ , ] } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/evaluation-query/$mod + +### $multiply + +- **Description:** The $multiply operator multiplies the input numerical values +- **Syntax:** + +```javascript +{ + $multiply: [ ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/arithmetic-expression/$multiply + +### $pow + +- **Description:** The `$pow` operator calculates the value of a numerical value raised to the power of a specified exponent. +- **Syntax:** + +```javascript +{ + $pow: [ , ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/arithmetic-expression/$pow + +### $round + +- **Description:** The $round operator rounds a number to a specified decimal place. +- **Syntax:** + +```javascript +{ + $round: [ , ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/arithmetic-expression/$round + +### $sqrt + +- **Description:** The $sqrt operator calculates and returns the square root of an input number +- **Syntax:** + +```javascript +{ + $sqrt: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/arithmetic-expression/$sqrt + +### $subtract + +- **Description:** The $subtract operator subtracts two numbers and returns the result. +- **Syntax:** + +```javascript +{ + $subtract: [ , ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/arithmetic-expression/$subtract + +### $trunc + +- **Description:** The $trunc operator truncates a number to a specified decimal place. +- **Syntax:** + +```javascript +{ + $trunc: [ , ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/arithmetic-expression/$trunc + +## Array Expression Operators + +### $arrayElemAt + +- **Description:** The $arrayElemAt returns the element at the specified array index. +- **Syntax:** + +```javascript +{ + $arrayElemAt: ["", ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$arrayelemat + +### $arrayToObject + +- **Description:** The $arrayToObject allows converting an array into a single document. +- **Syntax:** + +```javascript +{ + $arrayToObject: ''; +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$arraytoobject + +### $concatArrays + +- **Description:** The $concatArrays is used to combine multiple arrays into a single array. +- **Syntax:** + +```javascript +{ + $concatArrays: ['', '']; +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$concatarrays + +### $filter + +- **Description:** The $filter operator filters for elements from an array based on a specified condition. +- **Syntax:** + +```javascript +{ + $filter: { + input: "", + as: "", + cond: "" + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$filter + +### $firstN + +- **Description:** The $firstN operator sorts documents on one or more fields specified by the query and returns the first N document matching the filtering criteria +- **Syntax:** + +```javascript +{ + $firstN: { + input: [listOfFields], + sortBy: { + : + }, + n: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$firstn + +### $in + +- **Description:** The $in operator matches value of a field against an array of specified values +- **Syntax:** + +```javascript +{ + field: { + $in: [listOfValues]; + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$in + +### $indexOfArray + +- **Description:** The $indexOfArray operator is used to search for an element in an array and return the index of the first occurrence of the element. +- **Syntax:** + +```javascript +{ + $indexOfArray: [ < array > , < searchElement > , < start > , < end > ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$indexofarray + +### $isArray + +- **Description:** The $isArray operator is used to determine if a specified value is an array. +- **Syntax:** + +```javascript +{ + $isArray: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$isarray + +### $lastN + +- **Description:** The $lastN accumulator operator returns the last N values in a group of documents. +- **Syntax:** + +```javascript +{ + $group: { + _id: < expression > , + < field >: { + $lastN: { + n: < number >, + input: < expression > + } + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$lastn + +### $map + +- **Description:** The $map operator allows applying an expression to each element in an array. +- **Syntax:** + +```javascript +{ + $map: { + input: , + as: , + in: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$map + +### $maxN + +- **Description:** Retrieves the top N values based on a specified filtering criteria +- **Syntax:** + +```javascript +$maxN: { + input: < field or expression > , + n: < number of values to retrieve > +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$maxn + +### $minN + +- **Description:** Retrieves the bottom N values based on a specified filtering criteria +- **Syntax:** + +```javascript +$minN: { + input: < field or expression > , + n: < number of values to retrieve > +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$minn + +### $objectToArray + +### $range + +- **Description:** The $range operator allows generating an array of sequential integers. +- **Syntax:** + +```javascript +{ + $range: [ , , ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$range + +### $reduce + +- **Description:** The $reduce operator applies an expression to each element in an array & accumulate result as single value. +- **Syntax:** + +```javascript +$reduce: { + input: , + initialValue: , + in: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$reduce + +### $reverseArray + +- **Description:** The $reverseArray operator is used to reverse the order of elements in an array. +- **Syntax:** + +```javascript +{ + $reverseArray: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$reversearray + +### $size + +- **Description:** The $size operator is used to query documents where an array field has a specified number of elements. +- **Syntax:** + +```javascript +db.collection.find({ : { $size: } }) +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-query/$size + +### $slice + +- **Description:** The $slice operator returns a subset of an array from any element onwards in the array. +- **Syntax:** + +```javascript +{ + $slice: [ , ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$slice + +### $sortArray + +- **Description:** The $sortArray operator helps in sorting the elements in an array. +- **Syntax:** + +```javascript +{ + $sortArray: { + input: , + sortBy: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$sortarray + +### $zip + +- **Description:** The $zip operator allows merging two or more arrays element-wise into a single array or arrays. +- **Syntax:** + +```javascript +{ + $zip: { + inputs: [ , , ... ], + useLongestLength: , // Optional + defaults: // Optional + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$zip + +## Bitwise Operators + +### $bitAnd + +- **Description:** The $bitAnd operator performs a bitwise AND operation on integer values and returns the result as an integer. +- **Syntax:** + +```javascript +{ + $bitAnd: [ , , ... ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/bitwise/$bitand + +### $bitNot + +- **Description:** The $bitNot operator performs a bitwise NOT operation on integer values and returns the result as an integer. +- **Syntax:** + +```javascript +{ + $bitNot: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/bitwise/$bitnot + +### $bitOr + +- **Description:** The $bitOr operator performs a bitwise OR operation on integer values and returns the result as an integer. +- **Syntax:** + +```javascript +{ + $bitOr: [ , , ... ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/bitwise/$bitor + +### $bitXor + +- **Description:** The $bitXor operator performs a bitwise XOR operation on integer values. +- **Syntax:** + +```javascript +{ + $bitXor: [ , , ... ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/bitwise/$bitxor + +## Boolean Expression Operators + +### $and + +- **Description:** The $and operator joins multiple query clauses and returns documents that match all specified conditions. +- **Syntax:** + +```javascript +{ + $and: [{ + < expression1 > + }, { + < expression2 > + }, ..., { + < expressionN > + }] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/logical-query/$and + +### $not + +- **Description:** The $not operator performs a logical NOT operation on a specified expression, selecting documents that don't match the expression. +- **Syntax:** + +```javascript +{ + field: { + $not: { + < operator - expression > + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/logical-query/$not + +### $or + +- **Description:** The $or operator joins query clauses with a logical OR and returns documents that match at least one of the specified conditions. +- **Syntax:** + +```javascript +{ + $or: [{ + < expression1 > + }, { + < expression2 > + }, ..., { + < expressionN > + }] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/logical-query/$or + +## Comparison Expression Operators + +### $cmp + +- **Description:** The $cmp operator compares two values +- **Syntax:** + +```javascript +{ + $cmp: [, ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$cmp + +### $eq + +- **Description:** The $eq query operator compares the value of a field to a specified value +- **Syntax:** + +```javascript +{ + field: { + $eq: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$eq + +### $gt + +- **Description:** The $gt query operator retrieves documents where the value of a field is greater than a specified value +- **Syntax:** + +```javascript +{ + field: { + $gt: value; + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$gt + +### $gte + +- **Description:** The $gte operator retrieves documents where the value of a field is greater than or equal to a specified value +- **Syntax:** + +```javascript +{ + field: { + $gte: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$gte + +### $lt + +- **Description:** The $lt operator retrieves documents where the value of field is less than a specified value +- **Syntax:** + +```javascript +{ + field: { + $lt: value; + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$lt + +### $lte + +- **Description:** The $lte operator retrieves documents where the value of a field is less than or equal to a specified value +- **Syntax:** + +```javascript +{ + field: { + $lte: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$lte + +### $ne + +- **Description:** The $ne operator retrieves documents where the value of a field doesn't equal a specified value +- **Syntax:** + +```javascript +{ + field: { + $ne: value; + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$ne + +## Data Size Operators + +### $bsonSize + +- **Description:** The $bsonSize operator returns the size of a document in bytes when encoded as BSON. +- **Syntax:** + +```javascript +{ + $bsonSize: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/data-size/$bsonsize + +### $binarySize + +- **Description:** The $binarySize operator is used to return the size of a binary data field. +- **Syntax:** + +```javascript +{ + $binarySize: ''; +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/data-size/$binarysize + +## Date Expression Operators + +### $dateAdd + +- **Description:** The $dateAdd operator adds a specified number of time units (day, hour, month etc) to a date. +- **Syntax:** + +```javascript +$dateAdd: { + startDate: , + unit: , + amount: , + timezone: // Optional +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$dateadd + +### $dateDiff + +- **Description:** The $dateDiff operator calculates the difference between two dates in various units such as years, months, days, etc. +- **Syntax:** + +```javascript +$dateDiff: { + startDate: , + endDate: , + unit: , + timezone: , // Optional + startOfWeek: // Optional +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$datediff + +### $dateFromParts + +- **Description:** The $dateFromParts operator constructs a date from individual components. +- **Syntax:** + +```javascript +{ + $dateFromParts: { + year: < year > , + month: < month > , + day: < day > , + hour: < hour > , + minute: < minute > , + second: < second > , + millisecond: < millisecond > , + timezone: < timezone > + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$datefromparts + +### $dateFromString + +- **Description:** The $dateDiff operator converts a date/time string to a date object. +- **Syntax:** + +```javascript +{ + $dateFromString: { + dateString: < string > , + format: < string > , + timezone: < string > , + onError: < expression > , + onNull: < expression > + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$datefromstring + +### $dateSubtract + +- **Description:** The $dateSubtract operator subtracts a specified amount of time from a date. +- **Syntax:** + +```javascript +{ + $dateSubtract: { + startDate: , + unit: "", + amount: , + timezone: "" // optional + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$datesubtract + +### $dateToParts + +- **Description:** The $dateToParts operator decomposes a date into its individual parts such as year, month, day, and more. +- **Syntax:** + +```javascript +$dateToParts: { + date: , + timezone: , // optional + iso8601: // optional +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$datetoparts + +### $dateToString + +- **Description:** The $dateToString operator converts a date object into a formatted string. +- **Syntax:** + +```javascript +{ + $dateToString: { + format: "", + date: , + timezone: "", + onNull: "" + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$datetostring + +### $dateTrunc + +- **Description:** The $dateTrunc operator truncates a date to a specified unit. +- **Syntax:** + +```javascript +$dateTrunc: { + date: , + unit: "", + binSize: , // optional + timezone: "", // optional + startOfWeek: "" // optional (used when unit is "week") + } +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$datetrunc + +### $dayOfMonth + +- **Description:** The $dayOfMonth operator extracts the day of the month from a date. +- **Syntax:** + +```javascript +{ + $dayOfMonth: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$dayofmonth + +### $dayOfWeek + +- **Description:** The $dayOfWeek operator extracts the day of the week from a date. +- **Syntax:** + +```javascript +{ + $dayOfWeek: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$dayofweek + +### $dayOfYear + +- **Description:** The $dayOfYear operator extracts the day of the year from a date. +- **Syntax:** + +```javascript +{ + $dayOfYear: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$dayofyear + +### $hour + +- **Description:** The $hour operator returns the hour portion of a date as a number between 0 and 23. +- **Syntax:** + +```javascript +{ + $hour: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$hour + +### $isoDayOfWeek + +- **Description:** The $isoDayOfWeek operator returns the weekday number in ISO 8601 format, ranging from 1 (Monday) to 7 (Sunday). +- **Syntax:** + +```javascript +{ + $isoDayOfWeek: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$isodayofweek + +### $isoWeek + +- **Description:** The $isoWeek operator returns the week number of the year in ISO 8601 format, ranging from 1 to 53. +- **Syntax:** + +```javascript +{ + $isoWeek: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$isoweek + +### $isoWeekYear + +- **Description:** The $isoWeekYear operator returns the year number in ISO 8601 format, which can differ from the calendar year for dates at the beginning or end of the year. +- **Syntax:** + +```javascript +{ + $isoWeekYear: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$isoweekyear + +### $millisecond + +- **Description:** The $millisecond operator extracts the milliseconds portion from a date value. +- **Syntax:** + +```javascript +{ + $millisecond: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$millisecond + +### $minute + +- **Description:** The $minute operator extracts the minute portion from a date value. +- **Syntax:** + +```javascript +{ + $minute: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$minute + +### $month + +- **Description:** The $month operator extracts the month portion from a date value. +- **Syntax:** + +```javascript +{ + $month: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$month + +### $second + +- **Description:** The $second operator extracts the seconds portion from a date value. +- **Syntax:** + +```javascript +{ + $second: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$second + +### $toDate + +- **Description:** The $toDate operator converts supported types to a proper Date object. +- **Syntax:** + +```javascript +{ + $toDate: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/type-expression/$todate + +### $week + +- **Description:** The $week operator returns the week number for a date as a value between 0 and 53. +- **Syntax:** + +```javascript +{ + $week: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$week + +### $year + +- **Description:** The $year operator returns the year for a date as a four-digit number. +- **Syntax:** + +```javascript +{ + $year: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$year + +## Literal Expression Operator + +### $literal + +- **Description:** The $literal operator returns the specified value without parsing it as an expression, allowing literal values to be used in aggregation pipelines. +- **Syntax:** + +```javascript +{ + $literal: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/literal-expression/$literal + +## Miscellaneous Operators + +### $getField + +- **Description:** The $getField operator allows retrieving the value of a specified field from a document. +- **Syntax:** + +```javascript +{ + $getField: { + field: , + input: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/miscellaneous/$getfield + +### $rand + +- **Description:** The $rand operator generates a random float value between 0 and 1. +- **Syntax:** + +```javascript +{ + $rand: { + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/miscellaneous-query/$rand + +### $sampleRate + +- **Description:** The $sampleRate operator randomly samples documents from a collection based on a specified probability rate, useful for statistical analysis and testing. +- **Syntax:** + +```javascript +{ + $match: { + $sampleRate: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/miscellaneous/$samplerate + +## Object Expression Operators + +### $mergeObjects + +- **Description:** The $mergeObjects operator merges multiple documents into a single document +- **Syntax:** + +```javascript +{ + $mergeObjects: [ < document1 > , < document2 > , ...] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/object-expression/$mergeobjects + +### $objectToArray + +- **Description:** The objectToArray command is used to transform a document (object) into an array of key-value pairs. +- **Syntax:** + +```javascript +{ + $objectToArray: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/object-expression/$objecttoarray + +### $setField + +- **Description:** The setField command is used to add, update, or remove fields in embedded documents. +- **Syntax:** + +```javascript +{ + $setField: { + field: , + input: , + value: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/object-expression/$setfield + +## Set Expression Operators + +### $allElementsTrue + +- **Description:** The $allElementsTrue operator returns true if all elements in an array evaluate to true. +- **Syntax:** + +```javascript +{ + $allElementsTrue: [ ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/set-expression/$allelementstrue + +### $anyElementTrue + +- **Description:** The $anyElementTrue operator returns true if any element in an array evaluates to a value of true. +- **Syntax:** + +```javascript +{ + $anyElementTrue: [ ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/set-expression/$anyelementtrue + +### $setDifference + +- **Description:** The $setDifference operator returns a set with elements that exist in one set but not in a second set. +- **Syntax:** + +```javascript +{ + $setDifference: [ , ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/set-expression/$setdifference + +### $setEquals + +- **Description:** The $setEquals operator returns true if two sets have the same distinct elements. +- **Syntax:** + +```javascript +{ + $setEquals: [ , , ... ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/set-expression/$setequals + +### $setIntersection + +- **Description:** The $setIntersection operator returns the common elements that appear in all input arrays. +- **Syntax:** + +```javascript +{ + $setIntersection: [ , , ... ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/set-expression/$setintersection + +### $setIsSubset + +- **Description:** The $setIsSubset operator determines if one array is a subset of a second array. +- **Syntax:** + +```javascript +{ + $setIsSubset: [ , ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/set-expression/$setissubset + +### $setUnion + +- **Description:** The $setUnion operator returns an array that contains all the unique elements from the input arrays. +- **Syntax:** + +```javascript +{ + $setUnion: [ , , ... ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/set-expression/$setunion + +## String Expression Operators + +### $concat + +### $dateFromString + +- **Description:** The $dateDiff operator converts a date/time string to a date object. +- **Syntax:** + +```javascript +{ + $dateFromString: { + dateString: < string > , + format: < string > , + timezone: < string > , + onError: < expression > , + onNull: < expression > + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$datefromstring + +### $dateToString + +- **Description:** The $dateToString operator converts a date object into a formatted string. +- **Syntax:** + +```javascript +{ + $dateToString: { + format: "", + date: , + timezone: "", + onNull: "" + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$datetostring + +### $indexOfBytes + +### $indexOfCP + +### $ltrim + +### $regexFind + +### $regexFindAll + +### $regexMatch + +### $replaceOne + +### $replaceAll + +### $rtrim + +### $split + +### $strLenBytes + +### $strLenCP + +### $strcasecmp + +### $substr + +### $substrBytes + +### $substrCP + +### $toLower + +### $toString + +- **Description:** The $toString operator converts an expression into a String +- **Syntax:** + +```javascript +{ + $toString: < expression > +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/type-expression/$tostring + +### $trim + +### $toUpper + +## Timestamp Expression Operators + +### $tsIncrement + +- **Description:** The $tsIncrement operator extracts the increment portion from a timestamp value. +- **Syntax:** + +```javascript +{ + $tsIncrement: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/timestamp-expression/$tsincrement + +### $tsSecond + +- **Description:** The $tsSecond operator extracts the seconds portion from a timestamp value. +- **Syntax:** + +```javascript +{ + $tsSecond: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/timestamp-expression/$tssecond + +## Trigonometry Expression Operators + +### $sin + +### $cos + +### $tan + +### $asin + +### $acos + +### $atan + +### $atan2 + +### $asinh + +### $acosh + +### $atanh + +### $sinh + +### $cosh + +### $tanh + +### $degreesToRadians + +### $radiansToDegrees + +## Type Expression Operators + +### $convert + +- **Description:** The $convert operator converts an expression into the specified type +- **Syntax:** + +```javascript +{ + $convert: { + input: < expression > , + to: < type > , + format: < binData format > , + onError: < value to return on error > , + onNull: < value to return on null > + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/type-expression/$convert + +### $isNumber + +- **Description:** The $isNumber operator checks if a specified expression is a numerical type +- **Syntax:** + +```javascript +{ + $isNumber: < expression > +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/type-expression/$isnumber + +### $toBool + +- **Description:** The $toBool operator converts an expression into a Boolean type +- **Syntax:** + +```javascript +{ + $toBool: < expression > +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/type-expression/$tobool + +### $toDate + +- **Description:** The $toDate operator converts supported types to a proper Date object. +- **Syntax:** + +```javascript +{ + $toDate: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/type-expression/$todate + +### $toDecimal + +- **Description:** The $toDecimal operator converts an expression into a Decimal type +- **Syntax:** + +```javascript +{ + $toDecimal: < expression > +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/type-expression/$todecimal + +### $toDouble + +- **Description:** The $toDouble operator converts an expression into a Double value +- **Syntax:** + +```javascript +{ + $toDouble: < expression > +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/type-expression/$todouble + +### $toInt + +- **Description:** The $toInt operator converts an expression into an Integer +- **Syntax:** + +```javascript +{ + $toInt: < expression > +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/type-expression/$toint + +### $toLong + +- **Description:** The $toLong operator converts an expression into a Long value +- **Syntax:** + +```javascript +{ + $toLong: < expression > +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/type-expression/$tolong + +### $toObjectId + +- **Description:** The $toObjectId operator converts an expression into an ObjectId +- **Syntax:** + +```javascript +{ + $toObject: < expression > +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/type-expression/$toobjectid + +### $toString + +- **Description:** The $toString operator converts an expression into a String +- **Syntax:** + +```javascript +{ + $toString: < expression > +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/type-expression/$tostring + +### $type + +- **Description:** The $type operator retrieves documents if the chosen field is of the specified type. +- **Syntax:** + +```javascript +{ + : { $type: | } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/element-query/$type + +## Accumulators ($group, $bucket, $bucketAuto, $setWindowFields) + +### $addToSet + +- **Description:** The addToSet operator adds elements to an array if they don't already exist, while ensuring uniqueness of elements within the set. +- **Syntax:** + +```javascript +{ + $addToSet: { : } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$addtoset + +### $avg + +- **Description:** Computes the average of numeric values for documents in a group, bucket, or window. +- **Syntax:** + +```javascript +$avg: +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$avg + +### $bottom + +- **Description:** The $bottom operator returns the last document from the query's result set sorted by one or more fields +- **Syntax:** + +```javascript +{ + $bottom: { + output: [listOfFields], + sortBy: { + : < sortOrder > + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$bottom + +### $bottomN + +- **Description:** The $bottomN operator returns the last N documents from the result sorted by one or more fields +- **Syntax:** + +```javascript +{ + $bottomN: { + output: [listOfFields], + sortBy: { + : < sortOrder > + }, + n: < numDocumentsToReturn > + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$bottomn + +### $count + +- **Description:** The `$count` operator is used to count the number of documents that match a query filtering criteria. +- **Syntax:** + +```javascript +{ + $count: ''; +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$count + +### $first + +- **Description:** The $first operator returns the first value in a group according to the group's sorting order. +- **Syntax:** + +```javascript +{ + $first: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$first + +### $firstN + +- **Description:** The $firstN operator sorts documents on one or more fields specified by the query and returns the first N document matching the filtering criteria +- **Syntax:** + +```javascript +{ + $firstN: { + input: [listOfFields], + sortBy: { + : + }, + n: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$firstn + +### $last + +- **Description:** The $last operator returns the last document from the result sorted by one or more fields +- **Syntax:** + +```javascript +{ + "$last": +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$last + +### $lastN + +- **Description:** The $lastN accumulator operator returns the last N values in a group of documents. +- **Syntax:** + +```javascript +{ + $group: { + _id: < expression > , + < field >: { + $lastN: { + n: < number >, + input: < expression > + } + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$lastn + +### $max + +- **Description:** The $max operator returns the maximum value from a set of input values. +- **Syntax:** + +```javascript +$max: +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$max + +### $maxN + +- **Description:** Retrieves the top N values based on a specified filtering criteria +- **Syntax:** + +```javascript +$maxN: { + input: < field or expression > , + n: < number of values to retrieve > +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$maxn + +### $median + +- **Description:** The $median operator calculates the median value of a numeric field in a group of documents. +- **Syntax:** + +```javascript +{ + $group: { + _id: < expression > , + medianValue: { + $median: { + input: < field or expression > , + method: < > + } + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$median + +### $mergeObjects + +- **Description:** The $mergeObjects operator merges multiple documents into a single document +- **Syntax:** + +```javascript +{ + $mergeObjects: [ < document1 > , < document2 > , ...] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/object-expression/$mergeobjects + +### $min + +- **Description:** Retrieves the minimum value for a specified field +- **Syntax:** + +```javascript +$min: +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$min + +### $percentile + +- **Description:** The $percentile operator calculates the percentile of numerical values that match a filtering criteria +- **Syntax:** + +```javascript +$percentile: { + input: < field or expression > , + p: [ < percentile values > ], + method: < method > +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$percentile + +### $push + +- **Description:** The $push operator adds a specified value to an array within a document. +- **Syntax:** + +```javascript +db.collection.update({ + < query > +}, { + $push: { + < field >: < value > + } +}, { + < options > +}) +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$push + +### $stdDevPop + +- **Description:** The $stddevpop operator calculates the standard deviation of the specified values +- **Syntax:** + +```javascript +{ + $stddevpop: { + fieldName; + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$stddevpop + +### $stdDevSamp + +- **Description:** The $stddevsamp operator calculates the standard deviation of a specified sample of values and not the entire population +- **Syntax:** + +```javascript +{ + $stddevsamp: { + fieldName; + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$stddevsamp + +### $sum + +- **Description:** The $sum operator calculates the sum of the values of a field based on a filtering criteria +- **Syntax:** + +```javascript +{ + $sum: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$sum + +### $top + +- **Description:** The $top operator returns the first document from the result set sorted by one or more fields +- **Syntax:** + +```javascript +{ + $top: { + output: [listOfFields], + sortBy: { + < fieldName >: < sortOrder > + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$top + +### $topN + +- **Description:** The $topN operator returns the first N documents from the result sorted by one or more fields +- **Syntax:** + +```javascript +{ + $topN: { + output: [listOfFields], + sortBy: { + : < sortOrder > + }, + n: < numDocumentsToReturn > + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$topn + +## Accumulators (in Other Stages) + +### $avg + +- **Description:** Computes the average of numeric values for documents in a group, bucket, or window. +- **Syntax:** + +```javascript +$avg: +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$avg + +### $first + +- **Description:** The $first operator returns the first value in a group according to the group's sorting order. +- **Syntax:** + +```javascript +{ + $first: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$first + +### $last + +- **Description:** The $last operator returns the last document from the result sorted by one or more fields +- **Syntax:** + +```javascript +{ + "$last": +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$last + +### $max + +- **Description:** The $max operator returns the maximum value from a set of input values. +- **Syntax:** + +```javascript +$max: +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$max + +### $median + +- **Description:** The $median operator calculates the median value of a numeric field in a group of documents. +- **Syntax:** + +```javascript +{ + $group: { + _id: < expression > , + medianValue: { + $median: { + input: < field or expression > , + method: < > + } + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$median + +### $min + +- **Description:** Retrieves the minimum value for a specified field +- **Syntax:** + +```javascript +$min: +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$min + +### $percentile + +- **Description:** The $percentile operator calculates the percentile of numerical values that match a filtering criteria +- **Syntax:** + +```javascript +$percentile: { + input: < field or expression > , + p: [ < percentile values > ], + method: < method > +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$percentile + +### $stdDevPop + +- **Description:** The $stddevpop operator calculates the standard deviation of the specified values +- **Syntax:** + +```javascript +{ + $stddevpop: { + fieldName; + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$stddevpop + +### $stdDevSamp + +- **Description:** The $stddevsamp operator calculates the standard deviation of a specified sample of values and not the entire population +- **Syntax:** + +```javascript +{ + $stddevsamp: { + fieldName; + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$stddevsamp + +### $sum + +- **Description:** The $sum operator calculates the sum of the values of a field based on a filtering criteria +- **Syntax:** + +```javascript +{ + $sum: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$sum + +## Variable Expression Operators + +### $let + +- **Description:** The $let operator allows defining variables for use in a specified expression, enabling complex calculations and reducing code repetition. +- **Syntax:** + +```javascript +{ + $let: { + vars: { + : , + : , + ... + }, + in: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/variable-expression/$let + +## Window Operators + +### $sum + +- **Description:** The $sum operator calculates the sum of the values of a field based on a filtering criteria +- **Syntax:** + +```javascript +{ + $sum: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$sum + +### $push + +- **Description:** The $push operator adds a specified value to an array within a document. +- **Syntax:** + +```javascript +db.collection.update({ + < query > +}, { + $push: { + < field >: < value > + } +}, { + < options > +}) +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$push + +### $addToSet + +- **Description:** The addToSet operator adds elements to an array if they don't already exist, while ensuring uniqueness of elements within the set. +- **Syntax:** + +```javascript +{ + $addToSet: { : } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$addtoset + +### $count + +- **Description:** The `$count` operator is used to count the number of documents that match a query filtering criteria. +- **Syntax:** + +```javascript +{ + $count: ''; +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$count + +### $max + +- **Description:** The $max operator returns the maximum value from a set of input values. +- **Syntax:** + +```javascript +$max: +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$max + +### $min + +- **Description:** Retrieves the minimum value for a specified field +- **Syntax:** + +```javascript +$min: +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$min + +### $avg + +- **Description:** Computes the average of numeric values for documents in a group, bucket, or window. +- **Syntax:** + +```javascript +$avg: +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$avg + +### $stdDevPop + +- **Description:** The $stddevpop operator calculates the standard deviation of the specified values +- **Syntax:** + +```javascript +{ + $stddevpop: { + fieldName; + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$stddevpop + +### $bottom + +- **Description:** The $bottom operator returns the last document from the query's result set sorted by one or more fields +- **Syntax:** + +```javascript +{ + $bottom: { + output: [listOfFields], + sortBy: { + : < sortOrder > + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$bottom + +### $bottomN + +- **Description:** The $bottomN operator returns the last N documents from the result sorted by one or more fields +- **Syntax:** + +```javascript +{ + $bottomN: { + output: [listOfFields], + sortBy: { + : < sortOrder > + }, + n: < numDocumentsToReturn > + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$bottomn + +### $covariancePop + +- **Description:** The $covariancePop operator returns the covariance of two numerical expressions +- **Syntax:** + +```javascript +{ + $covariancePop: [ < numericalExpression1 > , < numericalExpression2 > ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/window-operators/$covariancepop + +### $covarianceSamp + +- **Description:** The $covarianceSamp operator returns the covariance of a sample of two numerical expressions +- **Syntax:** + +```javascript +{ + $covarianceSamp: [ < numericalExpression1 > , < numericalExpression2 > ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/window-operators/$covariancesamp + +### $denseRank + +- **Description:** The $denseRank operator assigns and returns a positional ranking for each document within a partition based on a specified sort order +- **Syntax:** + +```javascript +{ + $denseRank: { + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/window-operators/$denserank + +### $derivative + +- **Description:** The $derivative operator calculates the average rate of change of the value of a field within a specified window. +- **Syntax:** + +```javascript +{ + $derivative: { + input: < expression >, + unit: < timeWindow > + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/window-operators/$derivative + +### $documentNumber + +- **Description:** The $documentNumber operator assigns and returns a position for each document within a partition based on a specified sort order +- **Syntax:** + +```javascript +{ + $documentNumber: { + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/window-operators/$documentnumber + +### $expMovingAvg + +- **Description:** The $expMovingAvg operator calculates the moving average of a field based on the specified number of documents to hold the highest weight +- **Syntax:** + +```javascript +{ + $expMovingAvg: { + input: < field to use for calculation >, + N: < number of recent documents with the highest weight + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/window-operators/$expmovingavg + +### $first + +- **Description:** The $first operator returns the first value in a group according to the group's sorting order. +- **Syntax:** + +```javascript +{ + $first: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$first + +### $integral + +- **Description:** The $integral operator calculates the area under a curve with the specified range of documents forming the adjacent documents for the calculation. +- **Syntax:** + +```javascript +{ + $integral: { + input: < expression > , + unit: < time window > + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/window-operators/$integral + +### $last + +- **Description:** The $last operator returns the last document from the result sorted by one or more fields +- **Syntax:** + +```javascript +{ + "$last": +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$last + +### $linearFill + +- **Description:** The $linearFill operator interpolates missing values in a sequence of documents using linear interpolation. +- **Syntax:** + +```javascript +{ + $linearFill: { + input: < expression > , + sortBy: { + < field >: < 1 or - 1 > + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/window-operators/$linearfill + +### $locf + +- **Description:** The $locf operator propagates the last observed non-null value forward within a partition in a windowed query. +- **Syntax:** + +```javascript +{ + $locf: { + input: , + sortBy: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/window-operators/$locf + +### $minN + +- **Description:** Retrieves the bottom N values based on a specified filtering criteria +- **Syntax:** + +```javascript +$minN: { + input: < field or expression > , + n: < number of values to retrieve > +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$minn + +### $rank + +- **Description:** The $rank operator ranks documents within a partition based on a specified sort order. +- **Syntax:** + +```javascript +{ + $setWindowFields: { + partitionBy: < expression > , + sortBy: { + < field >: < order > + }, + output: { + < outputField >: { + $rank: {} + } + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/window-operators/$rank + +### $shift + +- **Description:** A window operator that shifts values within a partition and returns the shifted value. +- **Syntax:** + +```javascript +{ + $shift: { + output: , + by: , + default: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/window-operators/$shift + +### $stdDevSamp + +- **Description:** The $stddevsamp operator calculates the standard deviation of a specified sample of values and not the entire population +- **Syntax:** + +```javascript +{ + $stddevsamp: { + fieldName; + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$stddevsamp + +### $top + +- **Description:** The $top operator returns the first document from the result set sorted by one or more fields +- **Syntax:** + +```javascript +{ + $top: { + output: [listOfFields], + sortBy: { + < fieldName >: < sortOrder > + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$top + +### $topN + +- **Description:** The $topN operator returns the first N documents from the result sorted by one or more fields +- **Syntax:** + +```javascript +{ + $topN: { + output: [listOfFields], + sortBy: { + : < sortOrder > + }, + n: < numDocumentsToReturn > + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$topn + +## Conditional Expression Operators + +### $cond + +- **Description:** The $cond operator is used to evaluate a condition and return one of two expressions based on the result. +- **Syntax:** + +```javascript +{ + $cond: { + if: , + then: , + else: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/conditional-expression/$cond + +### $ifNull + +- **Description:** The $ifNull operator is used to evaluate an expression and return a specified value if the expression resolves to null. +- **Syntax:** + +```javascript +{ + $ifNull: [ , ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/conditional-expression/$ifnull + +### $switch + +- **Description:** The $switch operator is used to evaluate a series of conditions and return a value based on the first condition that evaluates to true. +- **Syntax:** + +```javascript +{ + $switch: { + branches: [ + { case: , then: }, + { case: , then: } + ], + default: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/conditional-expression/$switch + +## Aggregation Pipeline Stages + +### $addFields + +- **Description:** The $addFields stage in the aggregation pipeline is used to add new fields to documents. +- **Syntax:** + +```javascript +{ + $addFields: { + : , + : , + ... + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$addfields + +### $bucket + +- **Description:** Groups input documents into buckets based on specified boundaries. +- **Syntax:** + +```javascript +{ + $bucket: { + groupBy: , + boundaries: [ , , ... ], + default: , + output: { + : { }, + ... + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$bucket + +### $bucketAuto + +### $changeStream + +- **Description:** The $changeStream stage opens a change stream cursor to track data changes in real-time. +- **Syntax:** + +```javascript +{ + $changeStream: { + allChangesForCluster: , + fullDocument: , + fullDocumentBeforeChange: , + resumeAfter: , + startAfter: , + startAtOperationTime: , + showExpandedEvents: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$changestream + +### $collStats + +- **Description:** The $collStats stage in the aggregation pipeline is used to return statistics about a collection. +- **Syntax:** + +```javascript +{ + $collStats: { + latencyStats: { histograms: }, + storageStats: { scale: }, + count: {} + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$collstats + +### $count + +- **Description:** The `$count` operator is used to count the number of documents that match a query filtering criteria. +- **Syntax:** + +```javascript +{ + $count: ''; +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$count + +### $densify + +- **Description:** Adds missing data points in a sequence of values within an array or collection. +- **Syntax:** + +```javascript +{ + $densify: { + field: , + range: { + step: , + unit: , // Optional, e.g., "hour", "day", "month", etc. + bounds: [, ] // Optional + }, + partitionByFields: [, , ...] // Optional + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$densify + +### $documents + +- **Description:** The $documents stage creates a pipeline from a set of provided documents. +- **Syntax:** + +```javascript +{ + $documents: [ + , + , + ... + ] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$documents + +### $facet + +- **Description:** The $facet allows for multiple parallel aggregations to be executed within a single pipeline stage. +- **Syntax:** + +```javascript +{ + "$facet": { + "outputField1": [ { "stage1": {} }, { "stage2": {} } ], + "outputField2": [ { "stage1": {} }, { "stage2": {} } ] + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$facet + +### $fill + +- **Description:** The $fill stage allows filling missing values in documents based on specified methods and criteria. +- **Syntax:** + +```javascript +{ + $fill: { + sortBy: , + partitionBy: , + partitionByFields: , + output: { + : { value: }, + : { method: } + } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$fill + +### $geoNear + +- **Description:** The $geoNear operator finds and sorts documents by their proximity to a geospatial point, returning distance information for each document. +- **Syntax:** + +```javascript +{ + $geoNear: { + near: { + type: "Point", + coordinates: [, ] + }, + distanceField: , + maxDistance: , + minDistance: , + query: , + includeLocs: , + distanceMultiplier: , + spherical: , + key: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$geonear + +### $graphLookup + +### $group + +- **Description:** The $group stage groups documents by specified identifier expressions and applies accumulator expressions. +- **Syntax:** + +```javascript +{ + $group: { + _id: , + : { : }, + : { : } + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$group + +### $indexStats + +- **Description:** The $indexStats stage returns usage statistics for each index in the collection. +- **Syntax:** + +```javascript +{ + $indexStats: { + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$indexstats + +### $limit + +### $lookup + +- **Description:** The $lookup stage in the Aggregation Framework is used to perform left outer joins with other collections. +- **Syntax:** + +```javascript +{ + $lookup: { + from: , + localField: , + foreignField: , + as: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$lookup + +### $match + +- **Description:** The $match stage in the aggregation pipeline is used to filter documents that match a specified condition. +- **Syntax:** + +```javascript +{ + $match: { + + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$match + +### $merge + +- **Description:** The $merge stage in an aggregation pipeline writes the results of the aggregation to a specified collection. +- **Syntax:** + +```javascript +{ + $merge: { + into: , + on: , + whenMatched: , + whenNotMatched: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$merge + +### $out + +- **Description:** The `$out` stage in an aggregation pipeline writes the resulting documents to a specified collection. +- **Syntax:** + +```javascript +{ + $out: ''; +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$out + +### $project + +### $redact + +- **Description:** Filters the content of the documents based on access rights. +- **Syntax:** + +```javascript +{ + $redact: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$redact + +### $replaceRoot + +### $replaceWith + +- **Description:** The $replaceWith operator in Azure DocumentDB returns a document after replacing a document with the specified document +- **Syntax:** + +```javascript +{ + "$replaceWith": +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$replacewith + +### $sample + +- **Description:** The $sample operator in Azure DocumentDB returns a randomly selected number of documents +- **Syntax:** + +```javascript +{ + $sample: { size: } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$sample + +### $search + +### $searchMeta + +### $set + +- **Description:** The $set operator in Azure DocumentDB updates or creates a new field with a specified value +- **Syntax:** + +```javascript +{ + $set: { + newField: + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$set + +### $setWindowFields + +### $skip + +- **Description:** The $skip stage in the aggregation pipeline is used to skip a specified number of documents from the input and pass the remaining documents to the next stage in the pipeline. +- **Syntax:** + +```javascript +{ + $skip: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$skip + +### $sort + +- **Description:** The $sort stage in the aggregation pipeline is used to order the documents in the pipeline by a specified field or fields. +- **Syntax:** + +```javascript +{ + $sort: { + < field1 >: < sort order > , + < field2 >: < sort order > + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$sort + +### $sortByCount + +- **Description:** The $sortByCount stage in the aggregation pipeline is used to group documents by a specified expression and then sort the count of documents in each group in descending order. +- **Syntax:** + +```javascript +{ + $sortByCount: +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$sortbycount + +### $unionWith + +### $unset + +- **Description:** The $unset stage in the aggregation pipeline is used to remove specified fields from documents. +- **Syntax:** + +```javascript +{ + $unset: "" | ["", "", ...] +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$unset + +### $unwind + +- **Description:** The $unwind stage in the aggregation framework is used to deconstruct an array field from the input documents to output a document for each element. +- **Syntax:** + +```javascript +{ + $unwind: { + path: , + includeArrayIndex: , // Optional + preserveNullAndEmptyArrays: // Optional + } +} +``` + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$unwind + +### $currentOp + +## Variables in Aggregation Expressions + +### $$NOW + +### $$ROOT + +### $$REMOVE + +### $$CURRENT + +### $$DESCEND + +### $$PRUNE + +### $$KEEP + +## Not Listed + +Operators below are present on the compatibility page but are not in scope +for this package (deprecated or not available in DocumentDB). + +- **$where** (Evaluation Query Operators) — Deprecated in Mongo version 8.0 +- **$meta** (Projection Operators) — Not in scope +- **$accumulator** (Custom Aggregation Expression Operators) — Deprecated in Mongo version 8.0 +- **$function** (Custom Aggregation Expression Operators) — Deprecated in Mongo version 8.0 +- **$meta** (Text Expression Operator) — Not in scope +- **$accumulator** (Accumulators ($group, $bucket, $bucketAuto, $setWindowFields)) — Deprecated in Mongo version 8.0 +- **$changeStreamSplitLargeEvent** (Aggregation Pipeline Stages) — Not in scope +- **$listSampledQueries** (Aggregation Pipeline Stages) — Not in scope +- **$listSearchIndexes** (Aggregation Pipeline Stages) — Not in scope +- **$listSessions** (Aggregation Pipeline Stages) — Not in scope +- **$planCacheStats** (Aggregation Pipeline Stages) — Not in scope +- **$shardedDataDistribution** (Aggregation Pipeline Stages) — Not in scope +- **$listLocalSessions** (Aggregation Pipeline Stages) — Not in scope +- **$$CLUSTER_TIME** (Variables in Aggregation Expressions) — Not in scope +- **$$SEARCH_META** (Variables in Aggregation Expressions) — Not in scope +- **$$USER_ROLES** (Variables in Aggregation Expressions) — Not in scope diff --git a/packages/documentdb-constants/scripts/scrape-operator-docs.ts b/packages/documentdb-constants/scripts/scrape-operator-docs.ts new file mode 100644 index 000000000..7e1191625 --- /dev/null +++ b/packages/documentdb-constants/scripts/scrape-operator-docs.ts @@ -0,0 +1,778 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * scrape-operator-docs.ts + * + * Scrapes the DocumentDB compatibility page and per-operator documentation + * to generate the resources/operator-reference.md dump file. + * + * Usage: + * npx ts-node packages/documentdb-constants/scripts/scrape-operator-docs.ts + * + * The scraper has three phases: + * Phase 1: Fetch and parse the compatibility page (operator list + support status) + * Phase 2: Fetch per-operator doc pages (descriptions + syntax) + * Phase 3: Generate the Markdown dump file + * + * Before doing real work, a verification step checks that the upstream + * documentation structure is as expected by fetching a few known URLs. + */ + +import * as fs from 'fs'; +import * as path from 'path'; + +// --------------------------------------------------------------------------- +// Types +// --------------------------------------------------------------------------- + +interface OperatorInfo { + operator: string; + category: string; + listed: boolean; + /** Human-readable reason if not listed */ + notListedReason?: string; + /** Description from the per-operator doc page YAML frontmatter */ + description?: string; + /** Syntax snippet from the per-operator doc page */ + syntax?: string; + /** Documentation URL */ + docLink?: string; +} + +// --------------------------------------------------------------------------- +// Constants +// --------------------------------------------------------------------------- + +const COMPAT_PAGE_URL = + 'https://raw.githubusercontent.com/MicrosoftDocs/azure-databases-docs/main/articles/documentdb/compatibility-query-language.md'; + +const OPERATOR_DOC_BASE = + 'https://raw.githubusercontent.com/MicrosoftDocs/azure-databases-docs/main/articles/documentdb/operators'; + +const DOC_LINK_BASE = 'https://learn.microsoft.com/en-us/azure/documentdb/operators'; + +/** + * Maps category names (as they appear in column 1 of the compat page table) + * to the docs directory used for per-operator doc pages. + * + * This mapping is derived from the operators TOC.yml in the azure-databases-docs repo. + * Category names are trimmed before lookup, so leading/trailing spaces are OK. + */ +const CATEGORY_TO_DIR: Record = { + // Query operators + 'Comparison Query Operators': 'comparison-query', + 'Logical Query Operators': 'logical-query', + 'Element Query Operators': 'element-query', + 'Evaluation Query Operators': 'evaluation-query', + 'Array Query Operators': 'array-query', + 'Bitwise Query Operators': 'bitwise-query', + 'Geospatial Operators': 'geospatial', + 'Projection Operators': 'projection', + 'Miscellaneous Query Operators': 'miscellaneous-query', + // Update operators + 'Field Update Operators': 'field-update', + 'Array Update Operators': 'array-update', + 'Bitwise Update Operators': 'bitwise-update', + // Aggregation + 'Aggregation Pipeline Stages': 'aggregation', + 'Accumulators ($group, $bucket, $bucketAuto, $setWindowFields)': 'accumulators', + 'Accumulators (in Other Stages)': 'accumulators', + // Expression operators + 'Arithmetic Expression Operators': 'arithmetic-expression', + 'Array Expression Operators': 'array-expression', + 'Bitwise Operators': 'bitwise', + 'Boolean Expression Operators': 'boolean-expression', + 'Comparison Expression Operators': 'comparison-expression', + 'Conditional Expression Operators': 'conditional-expression', + 'Data Size Operators': 'data-size', + 'Date Expression Operators': 'date-expression', + 'Literal Expression Operator': 'literal-expression', + 'Miscellaneous Operators': 'miscellaneous', + 'Object Expression Operators': 'object-expression', + 'Set Expression Operators': 'set-expression', + 'String Expression Operators': 'string-expression', + 'Trigonometry Expression Operators': 'trigonometry-expression', + 'Type Expression Operators': 'aggregation/type-expression', + 'Timestamp Expression Operators': 'timestamp-expression', + 'Variable Expression Operators': 'variable-expression', + 'Text Expression Operator': 'miscellaneous', + 'Custom Aggregation Expression Operators': 'miscellaneous', + // Window + 'Window Operators': 'window-operators', + // System variables — no per-operator doc pages + 'Variables in Aggregation Expressions': '', +}; + +/** Delay between batches of concurrent requests (ms) */ +const BATCH_DELAY_MS = 200; + +/** Number of concurrent requests per batch */ +const BATCH_SIZE = 10; + +// --------------------------------------------------------------------------- +// Utilities +// --------------------------------------------------------------------------- + +async function fetchText(url: string): Promise { + try { + const response = await fetch(url); + if (!response.ok) { + return null; + } + return await response.text(); + } catch { + return null; + } +} + +function sleep(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +/** + * Resolves a category name to its docs directory. + */ +function getCategoryDir(category: string): string | undefined { + return CATEGORY_TO_DIR[category]; +} + +/** + * Extracts the YAML frontmatter description from a docs Markdown file. + * Normalizes CRLF line endings before parsing. + */ +function extractDescription(markdown: string): string | undefined { + const normalized = markdown.replace(/\r\n/g, '\n').replace(/\r/g, '\n'); + const fmMatch = normalized.match(/^---\s*\n([\s\S]*?)\n---/); + if (!fmMatch) return undefined; + + const frontmatter = fmMatch[1]; + // Look for description field — may be indented (e.g. " description: ...") + const descMatch = frontmatter.match(/^\s*description:\s*(.+)$/m); + if (descMatch) { + return descMatch[1].trim().replace(/^['"]|['"]$/g, ''); + } + return undefined; +} + +/** + * Extracts the first code block after a ## Syntax heading. + * Normalizes CRLF line endings to LF. + */ +function extractSyntax(markdown: string): string | undefined { + // Find ## Syntax (or ### Syntax) section + const syntaxSectionMatch = markdown.match(/##\s*Syntax\s*\n([\s\S]*?)(?=\n##\s|\n$)/i); + if (!syntaxSectionMatch) return undefined; + + const section = syntaxSectionMatch[1]; + // Find first code block in this section + const codeBlockMatch = section.match(/```[\w]*\s*\n([\s\S]*?)```/); + if (codeBlockMatch) { + return codeBlockMatch[1].replace(/\r\n/g, '\n').replace(/\r/g, '\n').trim(); + } + return undefined; +} + +/** + * Escape pipe characters and collapse whitespace in table cell content. + * Handles both \n and \r\n line endings (GitHub raw content may use CRLF). + */ +function escapeTableCell(text: string): string { + return text + .replace(/\r\n|\r|\n/g, ' ') + .replace(/\|/g, '\\|') + .replace(/\s+/g, ' ') + .trim(); +} + +// --------------------------------------------------------------------------- +// Phase 0: Verification +// --------------------------------------------------------------------------- + +interface VerificationResult { + passed: boolean; + checks: Array<{ name: string; passed: boolean; detail: string }>; +} + +async function runVerification(): Promise { + console.log(''); + console.log('='.repeat(60)); + console.log(' VERIFICATION STEP'); + console.log(' Checking that upstream documentation structure is as expected'); + console.log('='.repeat(60)); + console.log(''); + + const checks: VerificationResult['checks'] = []; + + // Check 1: Compatibility page is accessible and has expected structure + console.log(' [1/4] Fetching compatibility page...'); + const compatContent = await fetchText(COMPAT_PAGE_URL); + if (compatContent) { + const hasTable = /\|.*\|.*\|/.test(compatContent); + const hasOperators = /\$\w+/.test(compatContent); + const passed = hasTable && hasOperators; + checks.push({ + name: 'Compatibility page accessible & has tables + operators', + passed, + detail: passed + ? `OK — ${(compatContent.length / 1024).toFixed(1)} KB, tables found` + : `FAIL — tables: ${hasTable}, operators: ${hasOperators}`, + }); + } else { + checks.push({ + name: 'Compatibility page accessible', + passed: false, + detail: `FAIL — could not fetch ${COMPAT_PAGE_URL}`, + }); + } + + // Check 2: A known operator doc page exists ($match — aggregation stage) + console.log(' [2/4] Fetching known operator page ($match)...'); + const matchUrl = `${OPERATOR_DOC_BASE}/aggregation/$match.md`; + const matchContent = await fetchText(matchUrl); + if (matchContent) { + const hasDescription = extractDescription(matchContent) !== undefined; + checks.push({ + name: '$match doc page has YAML frontmatter with description', + passed: hasDescription, + detail: hasDescription + ? `OK — description: "${extractDescription(matchContent)}"` + : 'FAIL — no description in frontmatter', + }); + } else { + checks.push({ + name: '$match doc page accessible', + passed: false, + detail: `FAIL — could not fetch ${matchUrl}`, + }); + } + + // Check 3: A known query operator doc page exists ($eq — comparison query) + console.log(' [3/4] Fetching known operator page ($eq)...'); + const eqUrl = `${OPERATOR_DOC_BASE}/comparison-query/$eq.md`; + const eqContent = await fetchText(eqUrl); + if (eqContent) { + const desc = extractDescription(eqContent); + const syntax = extractSyntax(eqContent); + const passed = desc !== undefined; + checks.push({ + name: '$eq doc page has frontmatter description', + passed, + detail: passed + ? `OK — description: "${desc}", syntax: ${syntax ? 'found' : 'not found'}` + : 'FAIL — no description in frontmatter', + }); + } else { + checks.push({ + name: '$eq doc page accessible', + passed: false, + detail: `FAIL — could not fetch ${eqUrl}`, + }); + } + + // Check 4: A known accumulator doc page exists ($sum) + console.log(' [4/4] Fetching known operator page ($sum)...'); + const sumUrl = `${OPERATOR_DOC_BASE}/accumulators/$sum.md`; + const sumContent = await fetchText(sumUrl); + if (sumContent) { + const desc = extractDescription(sumContent); + const passed = desc !== undefined; + checks.push({ + name: '$sum doc page has frontmatter description', + passed, + detail: passed ? `OK — description: "${desc}"` : 'FAIL — no description in frontmatter', + }); + } else { + checks.push({ + name: '$sum doc page accessible', + passed: false, + detail: `FAIL — could not fetch ${sumUrl}`, + }); + } + + // Print results + console.log(''); + console.log('-'.repeat(60)); + console.log(' Verification Results:'); + console.log('-'.repeat(60)); + const allPassed = checks.every((c) => c.passed); + for (const check of checks) { + const icon = check.passed ? '✅' : '❌'; + console.log(` ${icon} ${check.name}`); + console.log(` ${check.detail}`); + } + console.log('-'.repeat(60)); + if (allPassed) { + console.log(' ✅ VERIFICATION PASSED — all checks succeeded'); + } else { + console.log(' ❌ VERIFICATION FAILED — some checks did not pass'); + console.log(' The documentation structure may have changed.'); + console.log(' Review the failures above before proceeding.'); + } + console.log('='.repeat(60)); + console.log(''); + + return { passed: allPassed, checks }; +} + +// --------------------------------------------------------------------------- +// Phase 1: Compatibility table extraction +// --------------------------------------------------------------------------- + +/** + * Sections we explicitly skip (not operators — commands, indexes, etc.) + */ +const SKIP_SECTIONS = ['Database commands', 'Index types', 'Index properties', 'Related content']; + +function parseCompatibilityTables(markdown: string): OperatorInfo[] { + const operators: OperatorInfo[] = []; + const lines = markdown.split('\n'); + + // The compatibility page has a single "## Operators" section with one big table: + // | Category | Operator | Supported (v5.0) | Supported (v6.0) | Supported (v7.0) | Supported (v8.0) | + // | --- | --- | --- | --- | --- | --- | + // | Comparison Query Operators | `$eq` | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | + + let currentSection = ''; + let inTable = false; + let separatorSeen = false; + + for (const line of lines) { + // Detect section headings + const h2Match = line.match(/^##\s+(.+)/); + if (h2Match) { + currentSection = h2Match[1].trim(); + inTable = false; + separatorSeen = false; + continue; + } + + // Skip sections we don't care about + if (SKIP_SECTIONS.some((s) => currentSection.startsWith(s))) { + continue; + } + + // Only process lines that start with | + if (!line.startsWith('|')) { + if (inTable) { + inTable = false; + separatorSeen = false; + } + continue; + } + + // Parse table rows + const cells = line + .split('|') + .map((c) => c.trim()) + .filter((c) => c.length > 0); + + if (cells.length < 2) continue; + + // Detect separator row (| --- | --- | ... |) + if (cells.every((c) => /^-+$/.test(c) || /^:?-+:?$/.test(c))) { + separatorSeen = true; + inTable = true; + continue; + } + + // Skip header row (before separator) + if (!separatorSeen) { + continue; + } + + // Data row: | Category | Operator | v5.0 | v6.0 | v7.0 | v8.0 | + if (inTable && cells.length >= 2) { + const rawCategory = cells[0].replace(/`/g, '').replace(/\*\*/g, '').trim(); + let rawOperator = cells[1]; + + // Extract from markdown links like [`$eq`](...) + const linkMatch = rawOperator.match(/\[([^\]]+)\]/); + if (linkMatch) { + rawOperator = linkMatch[1]; + } + rawOperator = rawOperator.replace(/`/g, '').replace(/\*+$/, '').trim(); + + // Handle $[identifier] which may be parsed incorrectly + // The compat page shows `$[identifier]` — square brackets get stripped by link parsing + if (rawOperator === 'identifier' && rawCategory.includes('Array Update')) { + rawOperator = '$[identifier]'; + } + + // For Variables in Aggregation Expressions, add $$ prefix + if (rawCategory === 'Variables in Aggregation Expressions' && !rawOperator.startsWith('$')) { + rawOperator = '$$' + rawOperator; + } + + if (!rawOperator || rawOperator === 'Operator' || rawOperator === 'Command') { + continue; + } + + // Skip summary table rows where "operator" column contains numbers + // (e.g., "| **Aggregation Stages** | 60 | 58 | 96.67% |") + if (/^\d+$/.test(rawOperator)) { + continue; + } + + // Skip rows where category contains percentage or "Total" + if (rawCategory.includes('%') || rawCategory === 'Total') { + continue; + } + + // Check support status from version columns (cells 2+) + const versionCells = cells.slice(2); + const hasYes = versionCells.some((c) => c.includes('Yes') || c.includes('✅') || c.includes('✓')); + const hasNo = versionCells.some((c) => c.includes('No') || c.includes('❌') || c.includes('✗')); + const hasDeprecated = versionCells.some((c) => c.toLowerCase().includes('deprecated')); + + let listed: boolean; + let notListedReason: string | undefined; + + if (hasDeprecated) { + listed = false; + const depCell = versionCells.find((c) => c.toLowerCase().includes('deprecated')); + notListedReason = depCell?.replace(/[*`]/g, '').trim() || 'Deprecated'; + } else if (hasNo && !hasYes) { + listed = false; + notListedReason = 'Not in scope'; + } else { + listed = true; + } + + operators.push({ + operator: rawOperator, + category: rawCategory, + listed, + notListedReason, + }); + } + } + + return operators; +} + +// --------------------------------------------------------------------------- +// Phase 2: Per-operator doc fetching +// --------------------------------------------------------------------------- + +/** + * Builds a global index of all operator doc files in the docs repo + * by crawling each known directory. Returns a map from lowercase filename + * (e.g. "$eq.md") to the directory path it lives in. + * + * This allows the scraper to find operators that are filed in a different + * directory than expected (e.g. $cmp is a comparison expression operator + * but lives in comparison-query/). + */ +async function buildGlobalFileIndex(): Promise> { + const GITHUB_API_BASE = + 'https://api.github.com/repos/MicrosoftDocs/azure-databases-docs/contents/articles/documentdb/operators'; + + const index = new Map(); + + try { + const response = await fetch(GITHUB_API_BASE); + if (!response.ok) { + console.log(' ⚠ Could not fetch directory listing from GitHub API — skipping global index'); + return index; + } + + const items = (await response.json()) as Array<{ name: string; type: string }>; + const dirs = items.filter((d) => d.type === 'dir' && d.name !== 'includes'); + + for (const dir of dirs) { + await sleep(300); // Rate limit GitHub API + try { + const dirResponse = await fetch(`${GITHUB_API_BASE}/${dir.name}`); + if (!dirResponse.ok) continue; + + const dirItems = (await dirResponse.json()) as Array<{ name: string; type: string }>; + const files = dirItems.filter((f) => f.name.endsWith('.md')); + const subdirs = dirItems.filter((f) => f.type === 'dir'); + + for (const file of files) { + index.set(file.name.toLowerCase(), dir.name); + } + + // Also check subdirectories (e.g., aggregation/type-expression/) + for (const sub of subdirs) { + await sleep(300); + try { + const subResponse = await fetch(`${GITHUB_API_BASE}/${dir.name}/${sub.name}`); + if (!subResponse.ok) continue; + + const subItems = (await subResponse.json()) as Array<{ name: string; type: string }>; + for (const file of subItems.filter((f) => f.name.endsWith('.md'))) { + index.set(file.name.toLowerCase(), `${dir.name}/${sub.name}`); + } + } catch { + // Ignore subdirectory fetch failures + } + } + } catch { + // Ignore individual directory fetch failures + } + } + } catch { + console.log(' ⚠ GitHub API request failed — skipping global index'); + } + + return index; +} + +async function fetchOperatorDocs(operators: OperatorInfo[]): Promise { + // Build a global index of all doc files to use as fallback + console.log(' Building global file index from GitHub API...'); + const globalIndex = await buildGlobalFileIndex(); + console.log(` Global index: ${globalIndex.size} files found across all directories`); + console.log(''); + + // Only fetch for listed operators that have a doc directory or are in global index + const fetchable = operators.filter((op) => { + if (!op.listed) return false; + const dir = getCategoryDir(op.category); + // Skip operators whose category maps to empty string (e.g. system variables) + if (dir === '') return false; + // Include if we have a directory mapping OR if the file exists in the global index + const opFileName = op.operator.toLowerCase() + '.md'; + return dir !== undefined || globalIndex.has(opFileName); + }); + const total = fetchable.length; + let fetched = 0; + let succeeded = 0; + let failed = 0; + const skipped = operators.filter((op) => op.listed).length - total; + + console.log(` Phase 2: Fetching per-operator doc pages (${total} operators, ${skipped} skipped)...`); + console.log(''); + + // Process in batches + for (let i = 0; i < fetchable.length; i += BATCH_SIZE) { + const batch = fetchable.slice(i, i + BATCH_SIZE); + + const promises = batch.map(async (op) => { + const primaryDir = getCategoryDir(op.category); + const opNameLower = op.operator.toLowerCase(); + const opNameOriginal = op.operator; + const opFileName = opNameLower + '.md'; + + // Strategy: + // 1. Try primary directory (lowercase filename) + // 2. Try primary directory (original casing) + // 3. Try global index fallback directory (lowercase filename) + // 4. Try global index fallback directory (original casing) + let content: string | null = null; + let resolvedDir: string | undefined; + + if (primaryDir) { + content = await fetchText(`${OPERATOR_DOC_BASE}/${primaryDir}/${opNameLower}.md`); + if (content) { + resolvedDir = primaryDir; + } else if (opNameLower !== opNameOriginal) { + content = await fetchText(`${OPERATOR_DOC_BASE}/${primaryDir}/${opNameOriginal}.md`); + if (content) resolvedDir = primaryDir; + } + } + + // Fallback: check global index for a different directory + if (!content && globalIndex.has(opFileName)) { + const fallbackDir = globalIndex.get(opFileName)!; + if (fallbackDir !== primaryDir) { + content = await fetchText(`${OPERATOR_DOC_BASE}/${fallbackDir}/${opFileName}`); + if (content) { + resolvedDir = fallbackDir; + } + } + } + + if (content) { + op.description = extractDescription(content); + op.syntax = extractSyntax(content); + op.docLink = `${DOC_LINK_BASE}/${resolvedDir}/${opNameLower}`; + succeeded++; + } else { + failed++; + } + fetched++; + }); + + await Promise.all(promises); + + // Progress output + const pct = ((fetched / total) * 100).toFixed(0); + process.stdout.write(`\r Progress: ${fetched}/${total} (${pct}%) — ${succeeded} succeeded, ${failed} failed`); + + // Rate limiting between batches + if (i + BATCH_SIZE < fetchable.length) { + await sleep(BATCH_DELAY_MS); + } + } + + console.log(''); // newline after progress + console.log(` Phase 2 complete: ${succeeded}/${total} docs fetched successfully`); + if (failed > 0) { + console.log(` ⚠ ${failed} operators could not be fetched (will have empty descriptions)`); + // List the failed operators for debugging + const failedOps = fetchable.filter((op) => !op.description && !op.syntax); + if (failedOps.length <= 120) { + for (const op of failedOps) { + const dir = getCategoryDir(op.category) || '???'; + const fallback = globalIndex.get(op.operator.toLowerCase() + '.md'); + const extra = fallback && fallback !== dir ? ` (also tried ${fallback})` : ''; + console.log(` - ${op.operator} (${op.category} → ${dir}${extra})`); + } + } + } +} + +// --------------------------------------------------------------------------- +// Phase 3: Dump generation +// --------------------------------------------------------------------------- + +function generateDump(operators: OperatorInfo[]): string { + const now = new Date().toISOString().split('T')[0]; + const lines: string[] = []; + + lines.push('# DocumentDB Operator Reference'); + lines.push(''); + lines.push(''); + lines.push(``); + lines.push(''); + lines.push(''); + + // Summary table (compact — stays as a table) + const categories = new Map(); + for (const op of operators) { + if (!categories.has(op.category)) { + categories.set(op.category, { listed: 0, notListed: 0 }); + } + const cat = categories.get(op.category)!; + if (op.listed) { + cat.listed++; + } else { + cat.notListed++; + } + } + + lines.push('## Summary'); + lines.push(''); + lines.push('| Category | Listed | Total |'); + lines.push('| --- | --- | --- |'); + let totalListed = 0; + let totalAll = 0; + for (const [cat, counts] of categories) { + const total = counts.listed + counts.notListed; + totalListed += counts.listed; + totalAll += total; + lines.push(`| ${escapeTableCell(cat)} | ${counts.listed} | ${total} |`); + } + lines.push(`| **Total** | **${totalListed}** | **${totalAll}** |`); + lines.push(''); + + // Per-category sections with structured operator entries + const categoriesInOrder = [...categories.keys()]; + for (const cat of categoriesInOrder) { + const catOps = operators.filter((op) => op.category === cat && op.listed); + if (catOps.length === 0) continue; + + lines.push(`## ${cat}`); + lines.push(''); + + for (const op of catOps) { + lines.push(`### ${op.operator}`); + lines.push(''); + if (op.description) { + lines.push(`- **Description:** ${op.description}`); + } + if (op.syntax) { + lines.push('- **Syntax:**'); + lines.push(''); + lines.push('```javascript'); + lines.push(op.syntax); + lines.push('```'); + lines.push(''); + } + if (op.docLink) { + lines.push(`- **Doc Link:** ${op.docLink}`); + } + lines.push(''); + } + } + + // Not-listed operators section + const notListed = operators.filter((op) => !op.listed); + if (notListed.length > 0) { + lines.push('## Not Listed'); + lines.push(''); + lines.push('Operators below are present on the compatibility page but are not in scope'); + lines.push('for this package (deprecated or not available in DocumentDB).'); + lines.push(''); + for (const op of notListed) { + lines.push(`- **${op.operator}** (${op.category}) — ${op.notListedReason || 'Not in scope'}`); + } + lines.push(''); + } + + return lines.join('\n'); +} + +// --------------------------------------------------------------------------- +// Main +// --------------------------------------------------------------------------- + +async function main(): Promise { + console.log('DocumentDB Operator Documentation Scraper'); + console.log('========================================='); + console.log(''); + + // Phase 0: Verification + const verification = await runVerification(); + if (!verification.passed) { + console.error('Aborting due to verification failure.'); + console.error('If the documentation structure has changed, update the scraper accordingly.'); + process.exit(1); + } + + // Phase 1: Fetch and parse compatibility page + console.log(' Phase 1: Fetching compatibility page...'); + const compatContent = await fetchText(COMPAT_PAGE_URL); + if (!compatContent) { + console.error('ERROR: Could not fetch compatibility page'); + process.exit(1); + } + console.log(` Fetched ${(compatContent.length / 1024).toFixed(1)} KB`); + + const operators = parseCompatibilityTables(compatContent); + const listed = operators.filter((op) => op.listed); + const notListed = operators.filter((op) => !op.listed); + console.log(` Parsed ${operators.length} operators (${listed.length} listed, ${notListed.length} not listed)`); + console.log(''); + + // Phase 2: Fetch per-operator docs + await fetchOperatorDocs(operators); + console.log(''); + + // Phase 3: Generate dump + console.log(' Phase 3: Generating operator-reference.md...'); + const dump = generateDump(operators); + + const outputDir = path.join(__dirname, '..', 'resources'); + if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir, { recursive: true }); + } + + const outputPath = path.join(outputDir, 'operator-reference.md'); + fs.writeFileSync(outputPath, dump, 'utf-8'); + + console.log(` Written to: ${outputPath}`); + console.log(` File size: ${(dump.length / 1024).toFixed(1)} KB`); + console.log(''); + console.log('Done! Review the generated file and commit it to the repo.'); +} + +main().catch((err) => { + console.error('Scraper failed:', err); + process.exit(1); +}); diff --git a/packages/documentdb-constants/src/docLinks.ts b/packages/documentdb-constants/src/docLinks.ts new file mode 100644 index 000000000..460112548 --- /dev/null +++ b/packages/documentdb-constants/src/docLinks.ts @@ -0,0 +1,77 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * URL generation helpers for DocumentDB documentation pages. + * + * Each operator has a documentation page at: + * https://learn.microsoft.com/en-us/azure/documentdb/operators/{category}/{operatorName} + */ + +const DOC_BASE = 'https://learn.microsoft.com/en-us/azure/documentdb/operators'; + +/** + * Maps meta tag prefixes to the docs directory name used in the + * DocumentDB documentation URL path. + */ +const META_TO_DOC_DIR: Record = { + 'query:comparison': 'comparison-query', + 'query:logical': 'logical-query', + 'query:element': 'element-query', + 'query:evaluation': 'evaluation-query', + 'query:array': 'array-query', + 'query:bitwise': 'bitwise-query', + 'query:geospatial': 'geospatial', + 'query:projection': 'projection', + 'query:misc': 'miscellaneous-query', + 'update:field': 'field-update', + 'update:array': 'array-update', + 'update:bitwise': 'bitwise-update', + stage: 'aggregation', + accumulator: 'accumulators', + 'expr:arith': 'arithmetic-expression', + 'expr:array': 'array-expression', + 'expr:bool': 'boolean-expression', + 'expr:comparison': 'comparison-expression', + 'expr:conditional': 'conditional-expression', + 'expr:date': 'date-expression', + 'expr:object': 'object-expression', + 'expr:set': 'set-expression', + 'expr:string': 'string-expression', + 'expr:trig': 'trigonometry-expression', + 'expr:type': 'aggregation/type-expression', + 'expr:datasize': 'data-size', + 'expr:timestamp': 'timestamp-expression', + 'expr:bitwise': 'bitwise', + 'expr:literal': 'literal-expression', + 'expr:misc': 'miscellaneous', + 'expr:variable': 'variable-expression', + window: 'window-operators', +}; + +/** + * Generates a documentation URL for a DocumentDB operator. + * + * @param operatorValue - the operator name, e.g. "$bucket", "$gt" + * @param meta - the meta tag, e.g. "stage", "query:comparison" + * @returns URL string or undefined if no mapping exists for the meta tag + */ +export function getDocLink(operatorValue: string, meta: string): string | undefined { + const dir = META_TO_DOC_DIR[meta]; + if (!dir) { + return undefined; + } + + // Operator names in URLs keep their $ prefix and are lowercased + const name = operatorValue.toLowerCase(); + return `${DOC_BASE}/${dir}/${name}`; +} + +/** + * Returns the base URL for the DocumentDB operators documentation. + */ +export function getDocBase(): string { + return DOC_BASE; +} diff --git a/packages/documentdb-constants/src/getFilteredCompletions.ts b/packages/documentdb-constants/src/getFilteredCompletions.ts new file mode 100644 index 000000000..dad83f262 --- /dev/null +++ b/packages/documentdb-constants/src/getFilteredCompletions.ts @@ -0,0 +1,76 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Primary consumer API for the documentdb-constants package. + * + * Provides filtered access to the operator entries based on meta tags + * and optional BSON type constraints. + */ + +import { type CompletionFilter, type OperatorEntry } from './types'; + +/** + * Internal registry of all operator entries. Populated by the + * individual operator module files (queryOperators, stages, etc.) + * via {@link registerOperators}. + */ +const allOperators: OperatorEntry[] = []; + +/** + * Registers operator entries into the global registry. + * Called by each operator module during module initialization. + * + * @param entries - array of OperatorEntry objects to register + */ +export function registerOperators(entries: readonly OperatorEntry[]): void { + allOperators.push(...entries); +} + +/** + * Returns operator entries matching the given filter. + * + * Meta tag matching uses **prefix matching**: a filter meta of 'query' + * matches 'query', 'query:comparison', 'query:logical', etc. + * A filter meta of 'expr' matches all 'expr:*' entries. + * + * BSON type filtering is applied as an intersection: if `filter.bsonTypes` + * is provided, only operators whose `applicableBsonTypes` includes at least + * one of the requested types are returned. Operators without + * `applicableBsonTypes` (universal operators) are always included. + * + * @param filter - the filtering criteria + * @returns matching operator entries (frozen array) + */ +export function getFilteredCompletions(filter: CompletionFilter): readonly OperatorEntry[] { + return allOperators.filter((entry) => { + // Meta tag prefix matching + const metaMatch = filter.meta.some((prefix) => entry.meta === prefix || entry.meta.startsWith(prefix + ':')); + if (!metaMatch) { + return false; + } + + // BSON type filtering (if specified) + if (filter.bsonTypes && filter.bsonTypes.length > 0) { + // Universal operators (no applicableBsonTypes) always pass + if (entry.applicableBsonTypes && entry.applicableBsonTypes.length > 0) { + const hasMatch = entry.applicableBsonTypes.some((t) => filter.bsonTypes!.includes(t)); + if (!hasMatch) { + return false; + } + } + } + + return true; + }); +} + +/** + * Returns all operator entries (unfiltered). + * Useful for validation, testing, and diagnostics. + */ +export function getAllCompletions(): readonly OperatorEntry[] { + return allOperators; +} diff --git a/packages/documentdb-constants/src/index.ts b/packages/documentdb-constants/src/index.ts new file mode 100644 index 000000000..7b5debffb --- /dev/null +++ b/packages/documentdb-constants/src/index.ts @@ -0,0 +1,71 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * @vscode-documentdb/documentdb-constants + * + * Static operator metadata for DocumentDB-supported operators, stages, + * accumulators, update operators, BSON constructors, and system variables. + */ + +// -- Core types -- +export type { CompletionFilter, MetaTag, OperatorEntry } from './types'; + +// -- Meta tag constants and presets -- +export { + ALL_META_TAGS, + EXPRESSION_COMPLETION_META, + // Completion context presets + FILTER_COMPLETION_META, + GROUP_EXPRESSION_COMPLETION_META, + META_ACCUMULATOR, + META_BSON, + META_EXPR_ARITH, + META_EXPR_ARRAY, + META_EXPR_BITWISE, + META_EXPR_BOOL, + META_EXPR_COMPARISON, + META_EXPR_CONDITIONAL, + META_EXPR_DATASIZE, + META_EXPR_DATE, + META_EXPR_LITERAL, + META_EXPR_MISC, + META_EXPR_OBJECT, + META_EXPR_SET, + META_EXPR_STRING, + META_EXPR_TIMESTAMP, + META_EXPR_TRIG, + META_EXPR_TYPE, + META_EXPR_VARIABLE, + META_FIELD_IDENTIFIER, + // Individual meta tags + META_QUERY, + META_QUERY_ARRAY, + META_QUERY_BITWISE, + META_QUERY_COMPARISON, + META_QUERY_ELEMENT, + META_QUERY_EVALUATION, + META_QUERY_GEOSPATIAL, + META_QUERY_LOGICAL, + META_QUERY_MISC, + META_QUERY_PROJECTION, + META_STAGE, + META_UPDATE, + META_UPDATE_ARRAY, + META_UPDATE_BITWISE, + META_UPDATE_FIELD, + META_VARIABLE, + META_WINDOW, + PROJECTION_COMPLETION_META, + STAGE_COMPLETION_META, + UPDATE_COMPLETION_META, + WINDOW_COMPLETION_META, +} from './metaTags'; + +// -- Consumer API -- +export { getAllCompletions, getFilteredCompletions, registerOperators } from './getFilteredCompletions'; + +// -- Documentation URL helpers -- +export { getDocBase, getDocLink } from './docLinks'; diff --git a/packages/documentdb-constants/src/metaTags.ts b/packages/documentdb-constants/src/metaTags.ts new file mode 100644 index 000000000..6e939a58c --- /dev/null +++ b/packages/documentdb-constants/src/metaTags.ts @@ -0,0 +1,130 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Meta tag constants for categorizing operators in the DocumentDB constants package. + * + * Tags use a hierarchical scheme where prefix matching is supported: + * filtering by 'query' matches 'query', 'query:comparison', 'query:logical', etc. + */ + +// -- Query operators -- +export const META_QUERY = 'query' as const; +export const META_QUERY_COMPARISON = 'query:comparison' as const; +export const META_QUERY_LOGICAL = 'query:logical' as const; +export const META_QUERY_ELEMENT = 'query:element' as const; +export const META_QUERY_EVALUATION = 'query:evaluation' as const; +export const META_QUERY_ARRAY = 'query:array' as const; +export const META_QUERY_BITWISE = 'query:bitwise' as const; +export const META_QUERY_GEOSPATIAL = 'query:geospatial' as const; +export const META_QUERY_PROJECTION = 'query:projection' as const; +export const META_QUERY_MISC = 'query:misc' as const; + +// -- Update operators -- +export const META_UPDATE = 'update' as const; +export const META_UPDATE_FIELD = 'update:field' as const; +export const META_UPDATE_ARRAY = 'update:array' as const; +export const META_UPDATE_BITWISE = 'update:bitwise' as const; + +// -- Aggregation pipeline -- +export const META_STAGE = 'stage' as const; +export const META_ACCUMULATOR = 'accumulator' as const; + +// -- Expression operators -- +export const META_EXPR_ARITH = 'expr:arith' as const; +export const META_EXPR_ARRAY = 'expr:array' as const; +export const META_EXPR_BOOL = 'expr:bool' as const; +export const META_EXPR_COMPARISON = 'expr:comparison' as const; +export const META_EXPR_CONDITIONAL = 'expr:conditional' as const; +export const META_EXPR_DATE = 'expr:date' as const; +export const META_EXPR_OBJECT = 'expr:object' as const; +export const META_EXPR_SET = 'expr:set' as const; +export const META_EXPR_STRING = 'expr:string' as const; +export const META_EXPR_TRIG = 'expr:trig' as const; +export const META_EXPR_TYPE = 'expr:type' as const; +export const META_EXPR_DATASIZE = 'expr:datasize' as const; +export const META_EXPR_TIMESTAMP = 'expr:timestamp' as const; +export const META_EXPR_BITWISE = 'expr:bitwise' as const; +export const META_EXPR_LITERAL = 'expr:literal' as const; +export const META_EXPR_MISC = 'expr:misc' as const; +export const META_EXPR_VARIABLE = 'expr:variable' as const; + +// -- Window operators -- +export const META_WINDOW = 'window' as const; + +// -- BSON constructors -- +export const META_BSON = 'bson' as const; + +// -- System variables -- +export const META_VARIABLE = 'variable' as const; + +// -- Schema-injected field names (not static — provided at runtime) -- +export const META_FIELD_IDENTIFIER = 'field:identifier' as const; + +/** + * All known meta tag values for validation purposes. + */ +export const ALL_META_TAGS = [ + META_QUERY, + META_QUERY_COMPARISON, + META_QUERY_LOGICAL, + META_QUERY_ELEMENT, + META_QUERY_EVALUATION, + META_QUERY_ARRAY, + META_QUERY_BITWISE, + META_QUERY_GEOSPATIAL, + META_QUERY_PROJECTION, + META_QUERY_MISC, + META_UPDATE, + META_UPDATE_FIELD, + META_UPDATE_ARRAY, + META_UPDATE_BITWISE, + META_STAGE, + META_ACCUMULATOR, + META_EXPR_ARITH, + META_EXPR_ARRAY, + META_EXPR_BOOL, + META_EXPR_COMPARISON, + META_EXPR_CONDITIONAL, + META_EXPR_DATE, + META_EXPR_OBJECT, + META_EXPR_SET, + META_EXPR_STRING, + META_EXPR_TRIG, + META_EXPR_TYPE, + META_EXPR_DATASIZE, + META_EXPR_TIMESTAMP, + META_EXPR_BITWISE, + META_EXPR_LITERAL, + META_EXPR_MISC, + META_EXPR_VARIABLE, + META_WINDOW, + META_BSON, + META_VARIABLE, + META_FIELD_IDENTIFIER, +] as const; + +// -- Completion context presets -- + +/** Query filter contexts: find filter bar, $match stage body */ +export const FILTER_COMPLETION_META: readonly string[] = ['query', 'bson', 'variable']; + +/** Projection/sort contexts */ +export const PROJECTION_COMPLETION_META: readonly string[] = ['field:identifier']; + +/** $group/$project/$addFields stage body: expressions + accumulators */ +export const GROUP_EXPRESSION_COMPLETION_META: readonly string[] = ['expr', 'accumulator', 'bson', 'variable']; + +/** Other stage bodies: expressions only (no accumulators) */ +export const EXPRESSION_COMPLETION_META: readonly string[] = ['expr', 'bson', 'variable']; + +/** Update operations: update operators */ +export const UPDATE_COMPLETION_META: readonly string[] = ['update']; + +/** Top-level aggregation pipeline: stage names */ +export const STAGE_COMPLETION_META: readonly string[] = ['stage']; + +/** Window fields: window operators + accumulators + expressions */ +export const WINDOW_COMPLETION_META: readonly string[] = ['window', 'accumulator', 'expr', 'bson', 'variable']; diff --git a/packages/documentdb-constants/src/types.ts b/packages/documentdb-constants/src/types.ts new file mode 100644 index 000000000..785bf812d --- /dev/null +++ b/packages/documentdb-constants/src/types.ts @@ -0,0 +1,112 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Represents a single operator, stage, accumulator, or BSON constructor + * for use in autocomplete, hover docs, and diagnostics. + */ +export interface OperatorEntry { + /** The operator string, e.g. "$gt", "$match", "ObjectId" */ + readonly value: string; + + /** + * Category tag for filtering. Determines which contexts this entry + * appears in. See {@link MetaTag} for the full set. + * + * Examples: "query", "query:comparison", "stage", "accumulator", + * "expr:arith", "expr:date", "bson", "field:identifier" + */ + readonly meta: MetaTag; + + /** Human-readable one-line description. */ + readonly description: string; + + /** + * Monaco snippet with tab stops for insertion. + * Example: '{ \\$match: { ${1:field}: ${2:value} } }' + * If absent, `value` is inserted as-is. + */ + readonly snippet?: string; + + /** + * URL to the DocumentDB documentation page for this operator. + * Generated from `docLinks.ts` helpers. + */ + readonly link?: string; + + /** + * Applicable BSON types for type-aware filtering. + * If set, this operator only appears when the field's bsonType + * matches one of these values. If absent, the operator is universal. + * + * Example: $regex → ['string'], $size → ['array'] + */ + readonly applicableBsonTypes?: readonly string[]; + + /** + * Operator return type or value type hint. + * Used by CompletionItemProvider for contextual snippet generation. + * Example: "$gt" → "same" (same type as input), "$size" → "number" + */ + readonly returnType?: string; +} + +/** + * Filter configuration for {@link getFilteredCompletions}. + */ +export interface CompletionFilter { + /** + * Meta tag prefixes to include. Supports prefix matching: + * 'query' matches 'query', 'query:comparison', 'query:logical', etc. + * 'expr' matches all 'expr:*' entries. + */ + readonly meta: readonly string[]; + + /** Optional: only return operators applicable to these BSON types. */ + readonly bsonTypes?: readonly string[]; +} + +/** + * Meta tag constants. Tags use a hierarchical scheme: + * + * - 'query' — top-level query operators (in find filter, $match) + * - 'query:comparison' — comparison subset ($eq, $gt, etc.) + * - 'query:logical' — logical ($and, $or, $not, $nor) + * - 'query:element' — element ($exists, $type) + * - 'query:evaluation' — evaluation ($expr, $regex, $mod, $text) + * - 'query:array' — array ($all, $elemMatch, $size) + * - 'query:bitwise' — bitwise ($bitsAllSet, etc.) + * - 'query:geospatial' — geospatial ($geoWithin, $near, etc.) + * - 'query:projection' — projection ($, $elemMatch, $slice) + * - 'query:misc' — miscellaneous ($comment, $rand, $natural) + * - 'update' — update operators ($set, $unset, $inc, etc.) + * - 'update:field' — field update subset + * - 'update:array' — array update subset ($push, $pull, etc.) + * - 'update:bitwise' — bitwise update ($bit) + * - 'stage' — aggregation pipeline stages ($match, $group, etc.) + * - 'accumulator' — accumulators ($sum, $avg, $first, etc.) + * - 'expr:arith' — arithmetic expressions ($add, $subtract, etc.) + * - 'expr:array' — array expressions ($arrayElemAt, $filter, etc.) + * - 'expr:bool' — boolean expressions ($and, $or, $not) + * - 'expr:comparison' — comparison expressions ($cmp, $eq, etc.) + * - 'expr:conditional' — conditional ($cond, $ifNull, $switch) + * - 'expr:date' — date expressions ($dateAdd, $year, etc.) + * - 'expr:object' — object expressions ($mergeObjects, etc.) + * - 'expr:set' — set expressions ($setUnion, etc.) + * - 'expr:string' — string expressions ($concat, $substr, etc.) + * - 'expr:trig' — trigonometry ($sin, $cos, etc.) + * - 'expr:type' — type conversion ($convert, $toInt, etc.) + * - 'expr:datasize' — data size ($bsonSize, $binarySize) + * - 'expr:timestamp' — timestamp ($tsIncrement, $tsSecond) + * - 'expr:bitwise' — bitwise expressions ($bitAnd, $bitOr, etc.) + * - 'expr:literal' — $literal + * - 'expr:misc' — miscellaneous expressions ($getField, $rand, etc.) + * - 'expr:variable' — variable expressions ($let) + * - 'window' — window operators ($rank, $denseRank, etc.) + * - 'bson' — BSON constructor functions (ObjectId, ISODate, etc.) + * - 'variable' — system variables ($$NOW, $$ROOT, etc.) + * - 'field:identifier' — injected field names from schema (not static) + */ +export type MetaTag = string; diff --git a/packages/documentdb-constants/tsconfig.json b/packages/documentdb-constants/tsconfig.json new file mode 100644 index 000000000..8688f97ff --- /dev/null +++ b/packages/documentdb-constants/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "composite": true, + "declaration": true, + "declarationMap": true, + "module": "commonjs", + "target": "ES2023", + "lib": ["ES2023"], + "rootDir": "./src", + "outDir": "./dist", + "strict": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "sourceMap": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/tsconfig.json b/tsconfig.json index ae69b6474..f8f79d3a5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -31,5 +31,5 @@ */ }, "exclude": ["node_modules", ".vscode-test", "packages/*/dist"], - "references": [{ "path": "packages/schema-analyzer" }] + "references": [{ "path": "packages/schema-analyzer" }, { "path": "packages/documentdb-constants" }] } From df1d7d6fa228faa8577c4f83fc594e5f89d44bb0 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Thu, 19 Feb 2026 13:04:26 +0000 Subject: [PATCH 027/128] refactor: enhance fetchText function to return detailed error information --- .../scripts/scrape-operator-docs.ts | 125 ++++++++++++------ 1 file changed, 81 insertions(+), 44 deletions(-) diff --git a/packages/documentdb-constants/scripts/scrape-operator-docs.ts b/packages/documentdb-constants/scripts/scrape-operator-docs.ts index 7e1191625..557b91489 100644 --- a/packages/documentdb-constants/scripts/scrape-operator-docs.ts +++ b/packages/documentdb-constants/scripts/scrape-operator-docs.ts @@ -116,15 +116,22 @@ const BATCH_SIZE = 10; // Utilities // --------------------------------------------------------------------------- -async function fetchText(url: string): Promise { +interface FetchResult { + content: string | null; + /** Non-null when content is null — e.g. "404 Not Found" or "NetworkError: ..." */ + failReason?: string; +} + +async function fetchText(url: string): Promise { try { const response = await fetch(url); if (!response.ok) { - return null; + return { content: null, failReason: `${response.status} ${response.statusText}` }; } - return await response.text(); - } catch { - return null; + return { content: await response.text() }; + } catch (error) { + const msg = error instanceof Error ? error.message : String(error); + return { content: null, failReason: `NetworkError: ${msg}` }; } } @@ -208,54 +215,54 @@ async function runVerification(): Promise { // Check 1: Compatibility page is accessible and has expected structure console.log(' [1/4] Fetching compatibility page...'); - const compatContent = await fetchText(COMPAT_PAGE_URL); - if (compatContent) { - const hasTable = /\|.*\|.*\|/.test(compatContent); - const hasOperators = /\$\w+/.test(compatContent); + const compatResult = await fetchText(COMPAT_PAGE_URL); + if (compatResult.content) { + const hasTable = /\|.*\|.*\|/.test(compatResult.content); + const hasOperators = /\$\w+/.test(compatResult.content); const passed = hasTable && hasOperators; checks.push({ name: 'Compatibility page accessible & has tables + operators', passed, detail: passed - ? `OK — ${(compatContent.length / 1024).toFixed(1)} KB, tables found` + ? `OK — ${(compatResult.content.length / 1024).toFixed(1)} KB, tables found` : `FAIL — tables: ${hasTable}, operators: ${hasOperators}`, }); } else { checks.push({ name: 'Compatibility page accessible', passed: false, - detail: `FAIL — could not fetch ${COMPAT_PAGE_URL}`, + detail: `FAIL — could not fetch ${COMPAT_PAGE_URL} (${compatResult.failReason})`, }); } // Check 2: A known operator doc page exists ($match — aggregation stage) console.log(' [2/4] Fetching known operator page ($match)...'); const matchUrl = `${OPERATOR_DOC_BASE}/aggregation/$match.md`; - const matchContent = await fetchText(matchUrl); - if (matchContent) { - const hasDescription = extractDescription(matchContent) !== undefined; + const matchResult = await fetchText(matchUrl); + if (matchResult.content) { + const hasDescription = extractDescription(matchResult.content) !== undefined; checks.push({ name: '$match doc page has YAML frontmatter with description', passed: hasDescription, detail: hasDescription - ? `OK — description: "${extractDescription(matchContent)}"` + ? `OK — description: "${extractDescription(matchResult.content)}"` : 'FAIL — no description in frontmatter', }); } else { checks.push({ name: '$match doc page accessible', passed: false, - detail: `FAIL — could not fetch ${matchUrl}`, + detail: `FAIL — could not fetch ${matchUrl} (${matchResult.failReason})`, }); } // Check 3: A known query operator doc page exists ($eq — comparison query) console.log(' [3/4] Fetching known operator page ($eq)...'); const eqUrl = `${OPERATOR_DOC_BASE}/comparison-query/$eq.md`; - const eqContent = await fetchText(eqUrl); - if (eqContent) { - const desc = extractDescription(eqContent); - const syntax = extractSyntax(eqContent); + const eqResult = await fetchText(eqUrl); + if (eqResult.content) { + const desc = extractDescription(eqResult.content); + const syntax = extractSyntax(eqResult.content); const passed = desc !== undefined; checks.push({ name: '$eq doc page has frontmatter description', @@ -268,16 +275,16 @@ async function runVerification(): Promise { checks.push({ name: '$eq doc page accessible', passed: false, - detail: `FAIL — could not fetch ${eqUrl}`, + detail: `FAIL — could not fetch ${eqUrl} (${eqResult.failReason})`, }); } // Check 4: A known accumulator doc page exists ($sum) console.log(' [4/4] Fetching known operator page ($sum)...'); const sumUrl = `${OPERATOR_DOC_BASE}/accumulators/$sum.md`; - const sumContent = await fetchText(sumUrl); - if (sumContent) { - const desc = extractDescription(sumContent); + const sumResult = await fetchText(sumUrl); + if (sumResult.content) { + const desc = extractDescription(sumResult.content); const passed = desc !== undefined; checks.push({ name: '$sum doc page has frontmatter description', @@ -288,7 +295,7 @@ async function runVerification(): Promise { checks.push({ name: '$sum doc page accessible', passed: false, - detail: `FAIL — could not fetch ${sumUrl}`, + detail: `FAIL — could not fetch ${sumUrl} (${sumResult.failReason})`, }); } @@ -545,6 +552,8 @@ async function fetchOperatorDocs(operators: OperatorInfo[]): Promise { let failed = 0; const skipped = operators.filter((op) => op.listed).length - total; + const failureDetails: { operator: string; category: string; reason: string }[] = []; + console.log(` Phase 2: Fetching per-operator doc pages (${total} operators, ${skipped} skipped)...`); console.log(''); @@ -565,14 +574,24 @@ async function fetchOperatorDocs(operators: OperatorInfo[]): Promise { // 4. Try global index fallback directory (original casing) let content: string | null = null; let resolvedDir: string | undefined; + let lastFailReason: string | undefined; if (primaryDir) { - content = await fetchText(`${OPERATOR_DOC_BASE}/${primaryDir}/${opNameLower}.md`); - if (content) { + const result = await fetchText(`${OPERATOR_DOC_BASE}/${primaryDir}/${opNameLower}.md`); + if (result.content) { + content = result.content; resolvedDir = primaryDir; - } else if (opNameLower !== opNameOriginal) { - content = await fetchText(`${OPERATOR_DOC_BASE}/${primaryDir}/${opNameOriginal}.md`); - if (content) resolvedDir = primaryDir; + } else { + lastFailReason = result.failReason; + if (opNameLower !== opNameOriginal) { + const result2 = await fetchText(`${OPERATOR_DOC_BASE}/${primaryDir}/${opNameOriginal}.md`); + if (result2.content) { + content = result2.content; + resolvedDir = primaryDir; + } else { + lastFailReason = result2.failReason; + } + } } } @@ -580,9 +599,12 @@ async function fetchOperatorDocs(operators: OperatorInfo[]): Promise { if (!content && globalIndex.has(opFileName)) { const fallbackDir = globalIndex.get(opFileName)!; if (fallbackDir !== primaryDir) { - content = await fetchText(`${OPERATOR_DOC_BASE}/${fallbackDir}/${opFileName}`); - if (content) { + const result3 = await fetchText(`${OPERATOR_DOC_BASE}/${fallbackDir}/${opFileName}`); + if (result3.content) { + content = result3.content; resolvedDir = fallbackDir; + } else { + lastFailReason = result3.failReason; } } } @@ -593,6 +615,11 @@ async function fetchOperatorDocs(operators: OperatorInfo[]): Promise { op.docLink = `${DOC_LINK_BASE}/${resolvedDir}/${opNameLower}`; succeeded++; } else { + failureDetails.push({ + operator: op.operator, + category: op.category, + reason: lastFailReason ?? 'Unknown', + }); failed++; } fetched++; @@ -614,15 +641,25 @@ async function fetchOperatorDocs(operators: OperatorInfo[]): Promise { console.log(` Phase 2 complete: ${succeeded}/${total} docs fetched successfully`); if (failed > 0) { console.log(` ⚠ ${failed} operators could not be fetched (will have empty descriptions)`); - // List the failed operators for debugging - const failedOps = fetchable.filter((op) => !op.description && !op.syntax); - if (failedOps.length <= 120) { - for (const op of failedOps) { - const dir = getCategoryDir(op.category) || '???'; - const fallback = globalIndex.get(op.operator.toLowerCase() + '.md'); + console.log(''); + + // Group failures by reason for a clear summary + const byReason = new Map(); + for (const f of failureDetails) { + const list = byReason.get(f.reason) ?? []; + list.push(f); + byReason.set(f.reason, list); + } + + for (const [reason, ops] of byReason) { + console.log(` [${reason}] (${ops.length} operators):`); + for (const f of ops) { + const dir = getCategoryDir(f.category) || '???'; + const fallback = globalIndex.get(f.operator.toLowerCase() + '.md'); const extra = fallback && fallback !== dir ? ` (also tried ${fallback})` : ''; - console.log(` - ${op.operator} (${op.category} → ${dir}${extra})`); + console.log(` - ${f.operator} (${f.category} → ${dir}${extra})`); } + console.log(''); } } } @@ -737,14 +774,14 @@ async function main(): Promise { // Phase 1: Fetch and parse compatibility page console.log(' Phase 1: Fetching compatibility page...'); - const compatContent = await fetchText(COMPAT_PAGE_URL); - if (!compatContent) { - console.error('ERROR: Could not fetch compatibility page'); + const compatResult = await fetchText(COMPAT_PAGE_URL); + if (!compatResult.content) { + console.error(`ERROR: Could not fetch compatibility page (${compatResult.failReason})`); process.exit(1); } - console.log(` Fetched ${(compatContent.length / 1024).toFixed(1)} KB`); + console.log(` Fetched ${(compatResult.content.length / 1024).toFixed(1)} KB`); - const operators = parseCompatibilityTables(compatContent); + const operators = parseCompatibilityTables(compatResult.content); const listed = operators.filter((op) => op.listed); const notListed = operators.filter((op) => !op.listed); console.log(` Parsed ${operators.length} operators (${listed.length} listed, ${notListed.length} not listed)`); From bfe91f7ab45b79c53ccb0d2551e19dcda382cb38 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Fri, 20 Feb 2026 10:53:17 +0000 Subject: [PATCH 028/128] chore: add prettier for code formatting in documentdb-constants package --- package-lock.json | 1 + packages/documentdb-constants/package.json | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index fb55eb5d5..25a846b9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22228,6 +22228,7 @@ "version": "1.0.0", "license": "MIT", "devDependencies": { + "prettier": "~3.6.2", "ts-node": "^10.9.2" } }, diff --git a/packages/documentdb-constants/package.json b/packages/documentdb-constants/package.json index b38e59034..e6ee5b405 100644 --- a/packages/documentdb-constants/package.json +++ b/packages/documentdb-constants/package.json @@ -11,6 +11,7 @@ "build": "tsc -p .", "clean": "rimraf dist tsconfig.tsbuildinfo", "test": "jest --config jest.config.js", + "prettier-fix": "prettier -w \"(scripts|src)/**/*.@(js|ts|jsx|tsx|json)\" \"./*.@(js|ts|jsx|tsx|json|md)\"", "scrape": "ts-node scripts/scrape-operator-docs.ts && prettier --write resources/operator-reference.md" }, "repository": { @@ -20,6 +21,7 @@ }, "license": "MIT", "devDependencies": { - "ts-node": "^10.9.2" + "ts-node": "^10.9.2", + "prettier": "~3.6.2" } } From 7c244e0f76058a71c959be3e32df6836f215a47c Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Fri, 20 Feb 2026 11:56:00 +0000 Subject: [PATCH 029/128] Add aggregation pipeline stages, system variables, update operators, and window operators - Created `stages.ts` to define various aggregation pipeline stages with descriptions, snippets, and documentation links. - Added `systemVariables.ts` to include system variables used in aggregation expressions. - Introduced `updateOperators.ts` for field, array, and bitwise update operators with relevant details. - Implemented `windowOperators.ts` to define window operators along with their descriptions and usage examples. --- packages/documentdb-constants/README.md | 22 +- packages/documentdb-constants/package.json | 5 +- .../resources/operator-reference-overrides.md | 260 ++++ ...rence.md => operator-reference-scraped.md} | 0 .../documentdb-constants/scripts/README.md | 71 + .../scripts/generate-from-reference.ts | 1020 ++++++++++++++ .../scripts/scrape-operator-docs.ts | 6 +- .../documentdb-constants/src/accumulators.ts | 183 +++ .../src/bsonConstructors.ts | 81 ++ .../src/expressionOperators.ts | 1213 +++++++++++++++++ packages/documentdb-constants/src/index.ts | 10 + .../src/queryOperators.ts | 446 ++++++ packages/documentdb-constants/src/stages.ts | 298 ++++ .../src/systemVariables.ts | 79 ++ .../src/updateOperators.ts | 203 +++ .../src/windowOperators.ts | 230 ++++ 16 files changed, 4111 insertions(+), 16 deletions(-) create mode 100644 packages/documentdb-constants/resources/operator-reference-overrides.md rename packages/documentdb-constants/resources/{operator-reference.md => operator-reference-scraped.md} (100%) create mode 100644 packages/documentdb-constants/scripts/README.md create mode 100644 packages/documentdb-constants/scripts/generate-from-reference.ts create mode 100644 packages/documentdb-constants/src/accumulators.ts create mode 100644 packages/documentdb-constants/src/bsonConstructors.ts create mode 100644 packages/documentdb-constants/src/expressionOperators.ts create mode 100644 packages/documentdb-constants/src/queryOperators.ts create mode 100644 packages/documentdb-constants/src/stages.ts create mode 100644 packages/documentdb-constants/src/systemVariables.ts create mode 100644 packages/documentdb-constants/src/updateOperators.ts create mode 100644 packages/documentdb-constants/src/windowOperators.ts diff --git a/packages/documentdb-constants/README.md b/packages/documentdb-constants/README.md index 2f2625ffd..f4c04b4ff 100644 --- a/packages/documentdb-constants/README.md +++ b/packages/documentdb-constants/README.md @@ -19,7 +19,7 @@ All operator data is derived from the official DocumentDB documentation: - **Per-operator docs:** [DocumentDB Operators](https://learn.microsoft.com/en-us/azure/documentdb/operators/) — individual pages with descriptions and syntax for each operator. - **Source repository:** [MicrosoftDocs/azure-databases-docs](https://github.com/MicrosoftDocs/azure-databases-docs) — the GitHub repo containing the raw Markdown source for all documentation pages above (under `articles/documentdb/`). -The scraper (`scripts/scrape-operator-docs.ts`) fetches data from these sources and generates the `resources/operator-reference.md` dump file that serves as the contract between the documentation and the TypeScript implementation. +The scraper (`scripts/scrape-operator-docs.ts`) fetches data from these sources and generates the `resources/operator-reference-scraped.md` dump file that serves as the contract between the documentation and the TypeScript implementation. ## Usage @@ -57,18 +57,18 @@ This runs the scraper and then formats the output with Prettier. The scraper: 1. **Verifies** upstream doc structure (early fail-fast) 2. **Extracts** all operators from the [compatibility page](https://learn.microsoft.com/en-us/azure/documentdb/compatibility-query-language) 3. **Fetches** per-operator documentation (descriptions, syntax) with a global file index fallback for operators filed in unexpected directories -4. **Generates** `resources/operator-reference.md` in a structured heading format (`### $operator` with description, syntax, and doc link) +4. **Generates** `resources/operator-reference-scraped.md` in a structured heading format (`### $operator` with description, syntax, and doc link) The dump serves as the authoritative reference for the TypeScript implementation. A Jest test (`test/operatorReference.test.ts`) will validate that the implementation matches the dump. ## Structure -| File | Purpose | -| --------------------------------- | -------------------------------------------- | -| `src/types.ts` | `OperatorEntry` interface and `MetaTag` type | -| `src/metaTags.ts` | Meta tag constants and completion presets | -| `src/docLinks.ts` | Documentation URL generation | -| `src/getFilteredCompletions.ts` | Primary consumer API: filter by meta tags | -| `src/index.ts` | Barrel exports for all public API | -| `resources/operator-reference.md` | Scraped operator dump (source of truth) | -| `scripts/scrape-operator-docs.ts` | Scraper script | +| File | Purpose | +| ----------------------------------------- | -------------------------------------------- | +| `src/types.ts` | `OperatorEntry` interface and `MetaTag` type | +| `src/metaTags.ts` | Meta tag constants and completion presets | +| `src/docLinks.ts` | Documentation URL generation | +| `src/getFilteredCompletions.ts` | Primary consumer API: filter by meta tags | +| `src/index.ts` | Barrel exports for all public API | +| `resources/operator-reference-scraped.md` | Auto-generated scraped operator dump | +| `scripts/scrape-operator-docs.ts` | Scraper script | diff --git a/packages/documentdb-constants/package.json b/packages/documentdb-constants/package.json index e6ee5b405..bdcd8420a 100644 --- a/packages/documentdb-constants/package.json +++ b/packages/documentdb-constants/package.json @@ -11,8 +11,9 @@ "build": "tsc -p .", "clean": "rimraf dist tsconfig.tsbuildinfo", "test": "jest --config jest.config.js", - "prettier-fix": "prettier -w \"(scripts|src)/**/*.@(js|ts|jsx|tsx|json)\" \"./*.@(js|ts|jsx|tsx|json|md)\"", - "scrape": "ts-node scripts/scrape-operator-docs.ts && prettier --write resources/operator-reference.md" + "prettier-fix": "prettier -w \"(scripts|src)/**/*.@(js|ts|jsx|tsx|json|md)\" \"./*.@(js|ts|jsx|tsx|json|md)\"", + "scrape": "ts-node scripts/scrape-operator-docs.ts && prettier --write resources/operator-reference-scraped.md", + "generate": "ts-node scripts/generate-from-reference.ts && prettier --write \"src/queryOperators.ts\" \"src/updateOperators.ts\" \"src/expressionOperators.ts\" \"src/accumulators.ts\" \"src/windowOperators.ts\" \"src/stages.ts\" \"src/systemVariables.ts\"" }, "repository": { "type": "git", diff --git a/packages/documentdb-constants/resources/operator-reference-overrides.md b/packages/documentdb-constants/resources/operator-reference-overrides.md new file mode 100644 index 000000000..834c78259 --- /dev/null +++ b/packages/documentdb-constants/resources/operator-reference-overrides.md @@ -0,0 +1,260 @@ +# DocumentDB Operator Reference — Overrides + + + + + + + + + + + + + + + + + + + + + + +--- + +## String Expression Operators + +### $concat + +- **Description:** Concatenates two or more strings and returns the resulting string. + +### $indexOfBytes + +- **Description:** Returns the byte index of the first occurrence of a substring within a string. + +### $indexOfCP + +- **Description:** Returns the code point index of the first occurrence of a substring within a string. + +### $ltrim + +- **Description:** Removes whitespace or specified characters from the beginning of a string. + +### $regexFind + +- **Description:** Applies a regular expression to a string and returns the first match. + +### $regexFindAll + +- **Description:** Applies a regular expression to a string and returns all matches as an array. + +### $regexMatch + +- **Description:** Applies a regular expression to a string and returns a boolean indicating if a match was found. + +### $replaceOne + +- **Description:** Replaces the first occurrence of a search string with a replacement string. + +### $replaceAll + +- **Description:** Replaces all occurrences of a search string with a replacement string. + +### $rtrim + +- **Description:** Removes whitespace or specified characters from the end of a string. + +### $split + +- **Description:** Splits a string by a delimiter and returns an array of substrings. + +### $strLenBytes + +- **Description:** Returns the number of UTF-8 encoded bytes in the specified string. + +### $strLenCP + +- **Description:** Returns the number of UTF-8 code points in the specified string. + +### $strcasecmp + +- **Description:** Performs a case-insensitive comparison of two strings and returns an integer. + +### $substr + +- **Description:** Returns a substring of a string, starting at a specified index for a specified length. Deprecated — use $substrBytes or $substrCP. + +### $substrBytes + +- **Description:** Returns a substring of a string by byte index, starting at a specified index for a specified number of bytes. + +### $substrCP + +- **Description:** Returns a substring of a string by code point index, starting at a specified index for a specified number of code points. + +### $toLower + +- **Description:** Converts a string to lowercase and returns the result. + +### $toUpper + +- **Description:** Converts a string to uppercase and returns the result. + +### $trim + +- **Description:** Removes whitespace or specified characters from both ends of a string. + +## Trigonometry Expression Operators + +### $sin + +- **Description:** Returns the sine of a value measured in radians. + +### $cos + +- **Description:** Returns the cosine of a value measured in radians. + +### $tan + +- **Description:** Returns the tangent of a value measured in radians. + +### $asin + +- **Description:** Returns the arcsine (inverse sine) of a value in radians. + +### $acos + +- **Description:** Returns the arccosine (inverse cosine) of a value in radians. + +### $atan + +- **Description:** Returns the arctangent (inverse tangent) of a value in radians. + +### $atan2 + +- **Description:** Returns the arctangent of the quotient of two values, using the signs to determine the quadrant. + +### $asinh + +- **Description:** Returns the inverse hyperbolic sine of a value. + +### $acosh + +- **Description:** Returns the inverse hyperbolic cosine of a value. + +### $atanh + +- **Description:** Returns the inverse hyperbolic tangent of a value. + +### $sinh + +- **Description:** Returns the hyperbolic sine of a value. + +### $cosh + +- **Description:** Returns the hyperbolic cosine of a value. + +### $tanh + +- **Description:** Returns the hyperbolic tangent of a value. + +### $degreesToRadians + +- **Description:** Converts a value from degrees to radians. + +### $radiansToDegrees + +- **Description:** Converts a value from radians to degrees. + +## Aggregation Pipeline Stages + +### $bucketAuto + +- **Description:** Categorizes documents into a specified number of groups based on a given expression, automatically determining bucket boundaries. + +### $graphLookup + +- **Description:** Performs a recursive search on a collection to return documents connected by a specified field relationship. + +### $limit + +- **Description:** Restricts the number of documents passed to the next stage in the pipeline. + +### $project + +- **Description:** Reshapes documents by including, excluding, or computing new fields. + +### $replaceRoot + +- **Description:** Replaces the input document with a specified embedded document, promoting it to the top level. + +### $search + +- **Description:** Performs full-text search on string fields using Atlas Search or compatible search indexes. + +### $searchMeta + +- **Description:** Returns metadata about an Atlas Search query without returning the matching documents. + +### $setWindowFields + +- **Description:** Adds computed fields to documents using window functions over a specified partition and sort order. + +### $unionWith + +- **Description:** Combines the results of two collections into a single result set, similar to SQL UNION ALL. + +### $currentOp + +- **Description:** Returns information on active and queued operations for the database instance. + +## Array Update Operators + +### $[] + +- **Description:** Positional all operator. Acts as a placeholder to update all elements in an array field. + +### $[identifier] + +- **Description:** Filtered positional operator. Acts as a placeholder to update elements that match an arrayFilters condition. + +### $position + +- **Description:** Specifies the position in the array at which the $push operator inserts elements. Used with $each. + +## Array Expression Operators + +### $objectToArray + +- **Description:** Converts an object into an array of key-value pair documents. + +## Variables in Aggregation Expressions + +### $$NOW + +- **Description:** Returns the current datetime as a Date object. Constant throughout a single aggregation pipeline. + +### $$ROOT + +- **Description:** References the root document — the top-level document currently being processed in the pipeline stage. + +### $$REMOVE + +- **Description:** Removes a field from the output document. Used with $project or $addFields to conditionally exclude fields. + +### $$CURRENT + +- **Description:** References the current document in the pipeline stage. Equivalent to $$ROOT at the start of the pipeline. + +### $$DESCEND + +- **Description:** Used with $redact. Returns the document fields at the current level and continues descending into subdocuments. + +### $$PRUNE + +- **Description:** Used with $redact. Excludes all fields at the current document level and stops descending into subdocuments. + +### $$KEEP + +- **Description:** Used with $redact. Keeps all fields at the current document level without further descending into subdocuments. diff --git a/packages/documentdb-constants/resources/operator-reference.md b/packages/documentdb-constants/resources/operator-reference-scraped.md similarity index 100% rename from packages/documentdb-constants/resources/operator-reference.md rename to packages/documentdb-constants/resources/operator-reference-scraped.md diff --git a/packages/documentdb-constants/scripts/README.md b/packages/documentdb-constants/scripts/README.md new file mode 100644 index 000000000..1938af370 --- /dev/null +++ b/packages/documentdb-constants/scripts/README.md @@ -0,0 +1,71 @@ +# Scripts + +Helper scripts for maintaining the `@vscode-documentdb/documentdb-constants` package. + +## scrape-operator-docs.ts + +Scrapes the DocumentDB compatibility page and per-operator documentation to produce `resources/operator-reference-scraped.md`. + +```bash +npm run scrape +``` + +**When to run:** When the upstream DocumentDB documentation changes (new operators, updated descriptions, etc.). This is infrequent — typically once per DocumentDB release. + +**Output:** `resources/operator-reference-scraped.md` — a machine-generated Markdown dump of all supported operators, their descriptions, syntax blocks, and doc links. + +## generate-from-reference.ts + +Reads the scraped dump and the hand-maintained overrides file, then generates the TypeScript operator data files in `src/`. + +```bash +npm run generate +``` + +**When to run:** + +- After running the scraper (`npm run scrape`) +- After editing `resources/operator-reference-overrides.md` + +**Inputs:** + +| File | Purpose | +| ------------------------------------------- | ---------------------------------- | +| `resources/operator-reference-scraped.md` | Primary data (machine-generated) | +| `resources/operator-reference-overrides.md` | Manual overrides (hand-maintained) | + +**Outputs:** Seven TypeScript files in `src/`: + +- `queryOperators.ts` — comparison, logical, element, evaluation, geospatial, array, bitwise, projection, misc query operators +- `updateOperators.ts` — field, array, and bitwise update operators +- `expressionOperators.ts` — arithmetic, array, bitwise, boolean, comparison, conditional, data-size, date, literal, misc, object, set, string, timestamp, trig, type, and variable expression operators +- `accumulators.ts` — group and other-stage accumulators +- `windowOperators.ts` — window function operators +- `stages.ts` — aggregation pipeline stages +- `systemVariables.ts` — system variables (`$$NOW`, `$$ROOT`, etc.) + +> **Do not edit the generated `src/` files by hand.** Put corrections in `resources/operator-reference-overrides.md` instead. The generated files contain a header warning to this effect. + +## Workflow + +``` + ┌──────────────────────┐ + │ Upstream docs change │ + └──────────┬───────────┘ + ▼ + npm run scrape + │ + ▼ + operator-reference-scraped.md + │ + ├──── operator-reference-overrides.md (manual) + │ + ▼ + npm run generate + │ + ▼ + src/*.ts (generated) + │ + ▼ + npm run build +``` diff --git a/packages/documentdb-constants/scripts/generate-from-reference.ts b/packages/documentdb-constants/scripts/generate-from-reference.ts new file mode 100644 index 000000000..244561003 --- /dev/null +++ b/packages/documentdb-constants/scripts/generate-from-reference.ts @@ -0,0 +1,1020 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Generates TypeScript operator data files from the scraped reference dump. + * + * Reads: + * resources/operator-reference-scraped.md — scraped operator data (primary) + * resources/operator-reference-overrides.md — hand-written overrides (wins) + * + * Writes: + * src/queryOperators.ts, src/updateOperators.ts, src/expressionOperators.ts, + * src/accumulators.ts, src/windowOperators.ts, src/stages.ts, + * src/systemVariables.ts + * + * The override file uses the same Markdown format as the dump. Any field + * specified in an override entry replaces the corresponding scraped value. + * Omitted fields keep their scraped values. + * + * Usage: npm run generate + * Note: This script overwrites the generated src/ files. Do NOT edit + * those files by hand — put corrections in the overrides file instead. + */ + +import * as fs from 'fs'; +import * as path from 'path'; + +// --------------------------------------------------------------------------- +// Types +// --------------------------------------------------------------------------- + +interface ParsedOperator { + value: string; + description: string; + syntax: string; + docLink: string; + category: string; + snippetOverride?: string; +} + +interface FileSpec { + fileName: string; + variableName: string; + metaImport: string; + metaValue: string; + operators: ParsedOperator[]; + extraImports?: string; +} + +// --------------------------------------------------------------------------- +// Category → meta tag mapping +// --------------------------------------------------------------------------- + +const CATEGORY_TO_META: Record = { + 'Comparison Query Operators': 'META_QUERY_COMPARISON', + 'Logical Query Operators': 'META_QUERY_LOGICAL', + 'Element Query Operators': 'META_QUERY_ELEMENT', + 'Evaluation Query Operators': 'META_QUERY_EVALUATION', + 'Geospatial Operators': 'META_QUERY_GEOSPATIAL', + 'Array Query Operators': 'META_QUERY_ARRAY', + 'Bitwise Query Operators': 'META_QUERY_BITWISE', + 'Projection Operators': 'META_QUERY_PROJECTION', + 'Miscellaneous Query Operators': 'META_QUERY_MISC', + 'Field Update Operators': 'META_UPDATE_FIELD', + 'Array Update Operators': 'META_UPDATE_ARRAY', + 'Bitwise Update Operators': 'META_UPDATE_BITWISE', + 'Arithmetic Expression Operators': 'META_EXPR_ARITH', + 'Array Expression Operators': 'META_EXPR_ARRAY', + 'Bitwise Operators': 'META_EXPR_BITWISE', + 'Boolean Expression Operators': 'META_EXPR_BOOL', + 'Comparison Expression Operators': 'META_EXPR_COMPARISON', + 'Data Size Operators': 'META_EXPR_DATASIZE', + 'Date Expression Operators': 'META_EXPR_DATE', + 'Literal Expression Operator': 'META_EXPR_LITERAL', + 'Miscellaneous Operators': 'META_EXPR_MISC', + 'Object Expression Operators': 'META_EXPR_OBJECT', + 'Set Expression Operators': 'META_EXPR_SET', + 'String Expression Operators': 'META_EXPR_STRING', + 'Timestamp Expression Operators': 'META_EXPR_TIMESTAMP', + 'Trigonometry Expression Operators': 'META_EXPR_TRIG', + 'Type Expression Operators': 'META_EXPR_TYPE', + 'Accumulators ($group, $bucket, $bucketAuto, $setWindowFields)': 'META_ACCUMULATOR', + 'Accumulators (in Other Stages)': 'META_ACCUMULATOR', + 'Variable Expression Operators': 'META_EXPR_VARIABLE', + 'Window Operators': 'META_WINDOW', + 'Conditional Expression Operators': 'META_EXPR_CONDITIONAL', + 'Aggregation Pipeline Stages': 'META_STAGE', + 'Variables in Aggregation Expressions': 'META_VARIABLE', +}; + +// Category → output file mapping +const CATEGORY_TO_FILE: Record = { + 'Comparison Query Operators': 'queryOperators', + 'Logical Query Operators': 'queryOperators', + 'Element Query Operators': 'queryOperators', + 'Evaluation Query Operators': 'queryOperators', + 'Geospatial Operators': 'queryOperators', + 'Array Query Operators': 'queryOperators', + 'Bitwise Query Operators': 'queryOperators', + 'Projection Operators': 'queryOperators', + 'Miscellaneous Query Operators': 'queryOperators', + 'Field Update Operators': 'updateOperators', + 'Array Update Operators': 'updateOperators', + 'Bitwise Update Operators': 'updateOperators', + 'Arithmetic Expression Operators': 'expressionOperators', + 'Array Expression Operators': 'expressionOperators', + 'Bitwise Operators': 'expressionOperators', + 'Boolean Expression Operators': 'expressionOperators', + 'Comparison Expression Operators': 'expressionOperators', + 'Data Size Operators': 'expressionOperators', + 'Date Expression Operators': 'expressionOperators', + 'Literal Expression Operator': 'expressionOperators', + 'Miscellaneous Operators': 'expressionOperators', + 'Object Expression Operators': 'expressionOperators', + 'Set Expression Operators': 'expressionOperators', + 'String Expression Operators': 'expressionOperators', + 'Timestamp Expression Operators': 'expressionOperators', + 'Trigonometry Expression Operators': 'expressionOperators', + 'Type Expression Operators': 'expressionOperators', + 'Conditional Expression Operators': 'expressionOperators', + 'Variable Expression Operators': 'expressionOperators', + 'Accumulators ($group, $bucket, $bucketAuto, $setWindowFields)': 'accumulators', + 'Accumulators (in Other Stages)': 'accumulators', + 'Window Operators': 'windowOperators', + 'Aggregation Pipeline Stages': 'stages', + 'Variables in Aggregation Expressions': 'systemVariables', +}; + +// --------------------------------------------------------------------------- +// Parser +// --------------------------------------------------------------------------- + +function parseDump(content: string): Map { + const lines = content.split('\n'); + const categorizedOps = new Map(); + + let currentCategory = ''; + let currentOp: Partial | null = null; + let inCodeBlock = false; + let syntaxLines: string[] = []; + + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + + // Track code blocks + if (line.startsWith('```')) { + if (inCodeBlock) { + // End of code block + inCodeBlock = false; + if (currentOp) { + currentOp.syntax = syntaxLines.join('\n').trim(); + } + syntaxLines = []; + continue; + } else { + inCodeBlock = true; + continue; + } + } + + if (inCodeBlock) { + syntaxLines.push(line); + continue; + } + + // H2 = category + const h2Match = line.match(/^## (.+)$/); + if (h2Match) { + // Save previous operator + if (currentOp && currentCategory) { + saveOperator(categorizedOps, currentCategory, currentOp as ParsedOperator); + } + currentOp = null; + + const cat = h2Match[1].trim(); + if (cat === 'Summary' || cat === 'Not Listed') { + currentCategory = ''; + continue; + } + currentCategory = cat; + if (!categorizedOps.has(currentCategory)) { + categorizedOps.set(currentCategory, []); + } + continue; + } + + // H3 = operator + const h3Match = line.match(/^### (.+)$/); + if (h3Match && currentCategory) { + // Save previous operator + if (currentOp) { + saveOperator(categorizedOps, currentCategory, currentOp as ParsedOperator); + } + currentOp = { + value: h3Match[1].trim(), + description: '', + syntax: '', + docLink: '', + category: currentCategory, + }; + continue; + } + + // Description line + if (currentOp && line.startsWith('- **Description:**')) { + currentOp.description = line.replace('- **Description:**', '').trim(); + continue; + } + + // Doc link line + if (currentOp && line.startsWith('- **Doc Link:**')) { + currentOp.docLink = line.replace('- **Doc Link:**', '').trim(); + continue; + } + } + + // Save last operator + if (currentOp && currentCategory) { + saveOperator(categorizedOps, currentCategory, currentOp as ParsedOperator); + } + + return categorizedOps; +} + +function saveOperator(map: Map, category: string, op: Partial): void { + if (!op.value) return; + const list = map.get(category) || []; + list.push({ + value: op.value || '', + description: op.description || '', + syntax: op.syntax || '', + docLink: op.docLink || '', + category: category, + snippetOverride: op.snippetOverride, + }); + map.set(category, list); +} + +// --------------------------------------------------------------------------- +// Override parsing and merging +// --------------------------------------------------------------------------- + +interface OverrideEntry { + description?: string; + syntax?: string; + docLink?: string; + snippet?: string; +} + +function parseOverrides(content: string): Map> { + const lines = content.split('\n'); + const result = new Map>(); + + let currentCategory = ''; + let currentOp: { value: string; entry: OverrideEntry } | null = null; + let inCodeBlock = false; + let syntaxLines: string[] = []; + + for (const line of lines) { + if (line.startsWith('```')) { + if (inCodeBlock) { + inCodeBlock = false; + if (currentOp) { + currentOp.entry.syntax = syntaxLines.join('\n').trim(); + } + syntaxLines = []; + continue; + } else { + inCodeBlock = true; + continue; + } + } + if (inCodeBlock) { + syntaxLines.push(line); + continue; + } + + const h2 = line.match(/^## (.+)$/); + if (h2) { + if (currentOp && currentCategory) { + saveOverride(result, currentCategory, currentOp); + } + currentOp = null; + currentCategory = h2[1].trim(); + continue; + } + + const h3 = line.match(/^### (.+)$/); + if (h3 && currentCategory) { + if (currentOp) { + saveOverride(result, currentCategory, currentOp); + } + currentOp = { value: h3[1].trim(), entry: {} }; + continue; + } + + if (currentOp && line.startsWith('- **Description:**')) { + currentOp.entry.description = line.replace('- **Description:**', '').trim(); + } + if (currentOp && line.startsWith('- **Doc Link:**')) { + currentOp.entry.docLink = line.replace('- **Doc Link:**', '').trim(); + } + if (currentOp && line.startsWith('- **Snippet:**')) { + currentOp.entry.snippet = line.replace('- **Snippet:**', '').trim(); + } + } + + if (currentOp && currentCategory) { + saveOverride(result, currentCategory, currentOp); + } + + return result; +} + +function saveOverride( + map: Map>, + category: string, + op: { value: string; entry: OverrideEntry }, +): void { + if (!map.has(category)) map.set(category, new Map()); + map.get(category)!.set(op.value, op.entry); +} + +function applyOverrides( + categorizedOps: Map, + overrides: Map>, +): void { + let applied = 0; + let missed = 0; + + for (const [category, opOverrides] of overrides) { + const ops = categorizedOps.get(category); + if (!ops) { + // Try to find operators across all categories (override category + // may not match dump category exactly for cross-category operators) + for (const [opName, override] of opOverrides) { + let found = false; + for (const [, catOps] of categorizedOps) { + const op = catOps.find((o) => o.value === opName); + if (op) { + mergeOverride(op, override); + applied++; + found = true; + break; + } + } + if (!found) { + console.warn(`⚠️ Override target not found: ${opName} in "${category}"`); + missed++; + } + } + continue; + } + + for (const [opName, override] of opOverrides) { + const op = ops.find((o) => o.value === opName); + if (op) { + mergeOverride(op, override); + applied++; + } else { + console.warn(`⚠️ Override target not found: ${opName} in "${category}"`); + missed++; + } + } + } + + console.log(` Applied ${applied} overrides (${missed} missed)`); +} + +function mergeOverride(op: ParsedOperator, override: OverrideEntry): void { + if (override.description !== undefined && override.description !== '') { + op.description = override.description; + } + if (override.syntax !== undefined && override.syntax !== '') { + op.syntax = override.syntax; + } + if (override.docLink !== undefined && override.docLink !== '') { + op.docLink = override.docLink; + } + if (override.snippet !== undefined && override.snippet !== '') { + op.snippetOverride = override.snippet; + } +} + +// --------------------------------------------------------------------------- +// Snippet generation +// --------------------------------------------------------------------------- + +function generateSnippet(op: ParsedOperator, meta: string): string | undefined { + const v = op.value; + + // System variables don't need snippets + if (meta === 'META_VARIABLE') return undefined; + + // Stages: wrap in { $stage: { ... } } + if (meta === 'META_STAGE') { + return getStageSinppet(v); + } + + // Query comparison operators: { $op: value } + if (meta === 'META_QUERY_COMPARISON') { + if (v === '$in' || v === '$nin') { + return `{ ${v}: [\${1:value}] }`; + } + return `{ ${v}: \${1:value} }`; + } + + // Logical query operators + if (meta === 'META_QUERY_LOGICAL') { + if (v === '$not') { + return `{ ${v}: { \${1:expression} } }`; + } + return `{ ${v}: [{ \${1:expression} }] }`; + } + + // Element query operators + if (meta === 'META_QUERY_ELEMENT') { + if (v === '$exists') return `{ ${v}: \${1:true} }`; + if (v === '$type') return `{ ${v}: "\${1:type}" }`; + return undefined; + } + + // Evaluation query operators + if (meta === 'META_QUERY_EVALUATION') { + if (v === '$expr') return `{ ${v}: { \${1:expression} } }`; + if (v === '$regex') return `{ ${v}: /\${1:pattern}/ }`; + if (v === '$mod') return `{ ${v}: [\${1:divisor}, \${2:remainder}] }`; + if (v === '$text') return `{ ${v}: { \\$search: "\${1:text}" } }`; + if (v === '$jsonSchema') return `{ ${v}: { bsonType: "\${1:object}" } }`; + return undefined; + } + + // Array query operators + if (meta === 'META_QUERY_ARRAY') { + if (v === '$all') return `{ ${v}: [\${1:value}] }`; + if (v === '$elemMatch') return `{ ${v}: { \${1:query} } }`; + if (v === '$size') return `{ ${v}: \${1:number} }`; + return undefined; + } + + // Bitwise query operators + if (meta === 'META_QUERY_BITWISE') { + return `{ ${v}: \${1:bitmask} }`; + } + + // Geospatial operators + if (meta === 'META_QUERY_GEOSPATIAL') { + if (v === '$near' || v === '$nearSphere') { + return `{ ${v}: { \\$geometry: { type: "Point", coordinates: [\${1:lng}, \${2:lat}] }, \\$maxDistance: \${3:distance} } }`; + } + if (v === '$geoIntersects' || v === '$geoWithin') { + return `{ ${v}: { \\$geometry: { type: "\${1:GeoJSON type}", coordinates: \${2:coordinates} } } }`; + } + if (v === '$box') return `[[\${1:bottomLeftX}, \${2:bottomLeftY}], [\${3:upperRightX}, \${4:upperRightY}]]`; + if (v === '$center') return `[[\${1:x}, \${2:y}], \${3:radius}]`; + if (v === '$centerSphere') return `[[\${1:x}, \${2:y}], \${3:radiusInRadians}]`; + if (v === '$geometry') return `{ type: "\${1:Point}", coordinates: [\${2:coordinates}] }`; + if (v === '$maxDistance' || v === '$minDistance') return `\${1:distance}`; + if (v === '$polygon') return `[[\${1:x1}, \${2:y1}], [\${3:x2}, \${4:y2}], [\${5:x3}, \${6:y3}]]`; + return undefined; + } + + // Projection operators + if (meta === 'META_QUERY_PROJECTION') { + if (v === '$') return undefined; // Positional, no snippet + if (v === '$elemMatch') return `{ ${v}: { \${1:query} } }`; + if (v === '$slice') return `{ ${v}: \${1:number} }`; + return undefined; + } + + // Misc query operators + if (meta === 'META_QUERY_MISC') { + if (v === '$comment') return `{ ${v}: "\${1:comment}" }`; + if (v === '$rand') return `{ ${v}: {} }`; + if (v === '$natural') return `{ ${v}: \${1:1} }`; + return undefined; + } + + // Update field operators + if (meta === 'META_UPDATE_FIELD') { + if (v === '$rename') return `{ ${v}: { "\${1:oldField}": "\${2:newField}" } }`; + if (v === '$currentDate') return `{ ${v}: { "\${1:field}": true } }`; + return `{ ${v}: { "\${1:field}": \${2:value} } }`; + } + + // Update array operators + if (meta === 'META_UPDATE_ARRAY') { + if (v === '$' || v === '$[]' || v === '$[identifier]') return undefined; // Positional, no snippet + if (v === '$addToSet') return `{ ${v}: { "\${1:field}": \${2:value} } }`; + if (v === '$pop') return `{ ${v}: { "\${1:field}": \${2:1} } }`; + if (v === '$pull') return `{ ${v}: { "\${1:field}": \${2:condition} } }`; + if (v === '$push') return `{ ${v}: { "\${1:field}": \${2:value} } }`; + if (v === '$pullAll') return `{ ${v}: { "\${1:field}": [\${2:values}] } }`; + if (v === '$each') return `{ ${v}: [\${1:values}] }`; + if (v === '$position') return `{ ${v}: \${1:index} }`; + if (v === '$slice') return `{ ${v}: \${1:number} }`; + if (v === '$sort') return `{ ${v}: { "\${1:field}": \${2:1} } }`; + return undefined; + } + + // Bitwise update operator + if (meta === 'META_UPDATE_BITWISE') { + return `{ ${v}: { "\${1:field}": { "\${2:and|or|xor}": \${3:value} } } }`; + } + + // Accumulators + if (meta === 'META_ACCUMULATOR') { + if (v === '$push' || v === '$addToSet') return `{ ${v}: "\${1:\\$field}" }`; + if (v === '$mergeObjects') return `{ ${v}: "\${1:\\$field}" }`; + if (v === '$count') return `{ ${v}: {} }`; + if (v === '$bottom' || v === '$top') + return `{ ${v}: { sortBy: { \${1:field}: \${2:1} }, output: "\${3:\\$field}" } }`; + if (v === '$bottomN' || v === '$topN') + return `{ ${v}: { n: \${1:number}, sortBy: { \${2:field}: \${3:1} }, output: "\${4:\\$field}" } }`; + if (v === '$firstN' || v === '$lastN' || v === '$maxN' || v === '$minN') + return `{ ${v}: { input: "\${1:\\$field}", n: \${2:number} } }`; + if (v === '$percentile') return `{ ${v}: { input: "\${1:\\$field}", p: [\${2:0.5}], method: "approximate" } }`; + if (v === '$median') return `{ ${v}: { input: "\${1:\\$field}", method: "approximate" } }`; + if (v === '$stdDevPop' || v === '$stdDevSamp') return `{ ${v}: "\${1:\\$field}" }`; + return `{ ${v}: "\${1:\\$field}" }`; + } + + // Window operators + if (meta === 'META_WINDOW') { + if (v === '$shift') return `{ ${v}: { output: "\${1:\\$field}", by: \${2:1}, default: \${3:null} } }`; + if (v === '$rank' || v === '$denseRank' || v === '$documentNumber') return `{ ${v}: {} }`; + if (v === '$linearFill' || v === '$locf') return `{ ${v}: "\${1:\\$field}" }`; + if (v === '$expMovingAvg') return `{ ${v}: { input: "\${1:\\$field}", N: \${2:number} } }`; + if (v === '$derivative' || v === '$integral') + return `{ ${v}: { input: "\${1:\\$field}", unit: "\${2:hour}" } }`; + // Window accumulators use accumulator-style snippets + return `{ ${v}: "\${1:\\$field}" }`; + } + + // Expression operators — general patterns + if (meta.startsWith('META_EXPR_')) { + return getExpressionSnippet(v, meta); + } + + return undefined; +} + +function getExpressionSnippet(v: string, meta: string): string | undefined { + // Arithmetic + if (meta === 'META_EXPR_ARITH') { + if ( + v === '$abs' || + v === '$ceil' || + v === '$floor' || + v === '$exp' || + v === '$ln' || + v === '$log10' || + v === '$sqrt' || + v === '$trunc' + ) { + return `{ ${v}: "\${1:\\$field}" }`; + } + if (v === '$add' || v === '$subtract' || v === '$multiply' || v === '$divide' || v === '$mod' || v === '$pow') { + return `{ ${v}: ["\${1:\\$field1}", "\${2:\\$field2}"] }`; + } + if (v === '$log') return `{ ${v}: ["\${1:\\$number}", \${2:base}] }`; + if (v === '$round') return `{ ${v}: ["\${1:\\$field}", \${2:place}] }`; + return `{ ${v}: "\${1:\\$field}" }`; + } + + // Array expressions + if (meta === 'META_EXPR_ARRAY') { + if (v === '$arrayElemAt') return `{ ${v}: ["\${1:\\$array}", \${2:index}] }`; + if (v === '$arrayToObject') return `{ ${v}: "\${1:\\$array}" }`; + if (v === '$concatArrays') return `{ ${v}: ["\${1:\\$array1}", "\${2:\\$array2}"] }`; + if (v === '$filter') + return `{ ${v}: { input: "\${1:\\$array}", as: "\${2:item}", cond: { \${3:expression} } } }`; + if (v === '$first' || v === '$last') return `{ ${v}: "\${1:\\$array}" }`; + if (v === '$in') return `{ ${v}: ["\${1:\\$field}", "\${2:\\$array}"] }`; + if (v === '$indexOfArray') return `{ ${v}: ["\${1:\\$array}", "\${2:value}"] }`; + if (v === '$isArray') return `{ ${v}: "\${1:\\$field}" }`; + if (v === '$map') return `{ ${v}: { input: "\${1:\\$array}", as: "\${2:item}", in: { \${3:expression} } } }`; + if (v === '$objectToArray') return `{ ${v}: "\${1:\\$object}" }`; + if (v === '$range') return `{ ${v}: [\${1:start}, \${2:end}, \${3:step}] }`; + if (v === '$reduce') + return `{ ${v}: { input: "\${1:\\$array}", initialValue: \${2:0}, in: { \${3:expression} } } }`; + if (v === '$reverseArray') return `{ ${v}: "\${1:\\$array}" }`; + if (v === '$size') return `{ ${v}: "\${1:\\$array}" }`; + if (v === '$slice') return `{ ${v}: ["\${1:\\$array}", \${2:n}] }`; + if (v === '$sortArray') return `{ ${v}: { input: "\${1:\\$array}", sortBy: { \${2:field}: \${3:1} } } }`; + if (v === '$zip') return `{ ${v}: { inputs: ["\${1:\\$array1}", "\${2:\\$array2}"] } }`; + if (v === '$maxN' || v === '$minN' || v === '$firstN' || v === '$lastN') + return `{ ${v}: { input: "\${1:\\$array}", n: \${2:number} } }`; + return `{ ${v}: "\${1:\\$array}" }`; + } + + // Boolean expressions + if (meta === 'META_EXPR_BOOL') { + if (v === '$not') return `{ ${v}: ["\${1:expression}"] }`; + return `{ ${v}: ["\${1:expression1}", "\${2:expression2}"] }`; + } + + // Comparison expressions + if (meta === 'META_EXPR_COMPARISON') { + return `{ ${v}: ["\${1:\\$field1}", "\${2:\\$field2}"] }`; + } + + // Conditional expressions + if (meta === 'META_EXPR_CONDITIONAL') { + if (v === '$cond') + return `{ ${v}: { if: { \${1:expression} }, then: \${2:trueValue}, else: \${3:falseValue} } }`; + if (v === '$ifNull') return `{ ${v}: ["\${1:\\$field}", \${2:replacement}] }`; + if (v === '$switch') + return `{ ${v}: { branches: [{ case: { \${1:expression} }, then: \${2:value} }], default: \${3:defaultValue} } }`; + return undefined; + } + + // Date expressions + if (meta === 'META_EXPR_DATE') { + if (v === '$dateAdd' || v === '$dateSubtract') + return `{ ${v}: { startDate: "\${1:\\$dateField}", unit: "\${2:day}", amount: \${3:1} } }`; + if (v === '$dateDiff') + return `{ ${v}: { startDate: "\${1:\\$startDate}", endDate: "\${2:\\$endDate}", unit: "\${3:day}" } }`; + if (v === '$dateFromParts') return `{ ${v}: { year: \${1:2024}, month: \${2:1}, day: \${3:1} } }`; + if (v === '$dateToParts') return `{ ${v}: { date: "\${1:\\$dateField}" } }`; + if (v === '$dateFromString') return `{ ${v}: { dateString: "\${1:dateString}" } }`; + if (v === '$dateToString') return `{ ${v}: { format: "\${1:%Y-%m-%d}", date: "\${2:\\$dateField}" } }`; + if (v === '$dateTrunc') return `{ ${v}: { date: "\${1:\\$dateField}", unit: "\${2:day}" } }`; + if (v === '$toDate') return `{ ${v}: "\${1:\\$field}" }`; + // Date part extractors: $year, $month, $dayOfMonth, etc. + return `{ ${v}: "\${1:\\$dateField}" }`; + } + + // Object expressions + if (meta === 'META_EXPR_OBJECT') { + if (v === '$mergeObjects') return `{ ${v}: ["\${1:\\$object1}", "\${2:\\$object2}"] }`; + if (v === '$objectToArray') return `{ ${v}: "\${1:\\$object}" }`; + if (v === '$setField') + return `{ ${v}: { field: "\${1:fieldName}", input: "\${2:\\$object}", value: \${3:value} } }`; + return `{ ${v}: "\${1:\\$object}" }`; + } + + // Set expressions + if (meta === 'META_EXPR_SET') { + if (v === '$setIsSubset') return `{ ${v}: ["\${1:\\$set1}", "\${2:\\$set2}"] }`; + if (v === '$anyElementTrue' || v === '$allElementsTrue') return `{ ${v}: ["\${1:\\$array}"] }`; + return `{ ${v}: ["\${1:\\$set1}", "\${2:\\$set2}"] }`; + } + + // String expressions + if (meta === 'META_EXPR_STRING') { + if (v === '$concat') return `{ ${v}: ["\${1:\\$string1}", "\${2:\\$string2}"] }`; + if (v === '$indexOfBytes' || v === '$indexOfCP') return `{ ${v}: ["\${1:\\$string}", "\${2:substring}"] }`; + if (v === '$regexFind' || v === '$regexFindAll' || v === '$regexMatch') + return `{ ${v}: { input: "\${1:\\$string}", regex: "\${2:pattern}" } }`; + if (v === '$replaceOne' || v === '$replaceAll') + return `{ ${v}: { input: "\${1:\\$string}", find: "\${2:find}", replacement: "\${3:replacement}" } }`; + if (v === '$split') return `{ ${v}: ["\${1:\\$string}", "\${2:delimiter}"] }`; + if (v === '$substr' || v === '$substrBytes' || v === '$substrCP') + return `{ ${v}: ["\${1:\\$string}", \${2:start}, \${3:length}] }`; + if (v === '$strcasecmp') return `{ ${v}: ["\${1:\\$string1}", "\${2:\\$string2}"] }`; + if (v === '$trim' || v === '$ltrim' || v === '$rtrim') return `{ ${v}: { input: "\${1:\\$string}" } }`; + return `{ ${v}: "\${1:\\$string}" }`; + } + + // Trig expressions + if (meta === 'META_EXPR_TRIG') { + if (v === '$degreesToRadians' || v === '$radiansToDegrees') return `{ ${v}: "\${1:\\$angle}" }`; + return `{ ${v}: "\${1:\\$value}" }`; + } + + // Type expressions + if (meta === 'META_EXPR_TYPE') { + if (v === '$convert') return `{ ${v}: { input: "\${1:\\$field}", to: "\${2:type}" } }`; + if (v === '$type') return `{ ${v}: "\${1:\\$field}" }`; + return `{ ${v}: "\${1:\\$field}" }`; + } + + // Data size + if (meta === 'META_EXPR_DATASIZE') { + return `{ ${v}: "\${1:\\$field}" }`; + } + + // Timestamp + if (meta === 'META_EXPR_TIMESTAMP') { + return `{ ${v}: "\${1:\\$timestampField}" }`; + } + + // Bitwise expressions + if (meta === 'META_EXPR_BITWISE') { + if (v === '$bitNot') return `{ ${v}: "\${1:\\$field}" }`; + return `{ ${v}: [\${1:value1}, \${2:value2}] }`; + } + + // Literal + if (meta === 'META_EXPR_LITERAL') { + return `{ ${v}: \${1:value} }`; + } + + // Misc expressions + if (meta === 'META_EXPR_MISC') { + if (v === '$getField') return `{ ${v}: { field: "\${1:fieldName}", input: "\${2:\\$object}" } }`; + if (v === '$rand') return `{ ${v}: {} }`; + if (v === '$sampleRate') return `{ ${v}: \${1:0.5} }`; + return `{ ${v}: \${1:value} }`; + } + + // Variable expression + if (meta === 'META_EXPR_VARIABLE') { + if (v === '$let') return `{ ${v}: { vars: { \${1:var}: \${2:expression} }, in: \${3:expression} } }`; + return undefined; + } + + return undefined; +} + +function getStageSinppet(v: string): string | undefined { + switch (v) { + case '$match': + return `{ ${v}: { \${1:query} } }`; + case '$group': + return `{ ${v}: { _id: "\${1:\\$field}", \${2:accumulator}: { \${3:\\$sum}: 1 } } }`; + case '$project': + return `{ ${v}: { \${1:field}: 1 } }`; + case '$sort': + return `{ ${v}: { \${1:field}: \${2:1} } }`; + case '$limit': + return `{ ${v}: \${1:number} }`; + case '$skip': + return `{ ${v}: \${1:number} }`; + case '$unwind': + return `{ ${v}: "\${1:\\$arrayField}" }`; + case '$lookup': + return `{ ${v}: { from: "\${1:collection}", localField: "\${2:field}", foreignField: "\${3:field}", as: "\${4:result}" } }`; + case '$addFields': + return `{ ${v}: { \${1:newField}: \${2:expression} } }`; + case '$set': + return `{ ${v}: { \${1:field}: \${2:expression} } }`; + case '$unset': + return `{ ${v}: "\${1:field}" }`; + case '$replaceRoot': + return `{ ${v}: { newRoot: "\${1:\\$field}" } }`; + case '$replaceWith': + return `{ ${v}: "\${1:\\$field}" }`; + case '$count': + return `{ ${v}: "\${1:countField}" }`; + case '$out': + return `{ ${v}: "\${1:collection}" }`; + case '$merge': + return `{ ${v}: { into: "\${1:collection}" } }`; + case '$bucket': + return `{ ${v}: { groupBy: "\${1:\\$field}", boundaries: [\${2:values}], default: "\${3:Other}" } }`; + case '$bucketAuto': + return `{ ${v}: { groupBy: "\${1:\\$field}", buckets: \${2:number} } }`; + case '$facet': + return `{ ${v}: { \${1:outputField}: [{ \${2:stage} }] } }`; + case '$graphLookup': + return `{ ${v}: { from: "\${1:collection}", startWith: "\${2:\\$field}", connectFromField: "\${3:field}", connectToField: "\${4:field}", as: "\${5:result}" } }`; + case '$sample': + return `{ ${v}: { size: \${1:number} } }`; + case '$sortByCount': + return `{ ${v}: "\${1:\\$field}" }`; + case '$redact': + return `{ ${v}: { \\$cond: { if: { \${1:expression} }, then: "\${2:\\$\\$DESCEND}", else: "\${3:\\$\\$PRUNE}" } } }`; + case '$unionWith': + return `{ ${v}: { coll: "\${1:collection}", pipeline: [\${2}] } }`; + case '$setWindowFields': + return `{ ${v}: { partitionBy: "\${1:\\$field}", sortBy: { \${2:field}: \${3:1} }, output: { \${4:newField}: { \${5:windowFunc} } } } }`; + case '$densify': + return `{ ${v}: { field: "\${1:field}", range: { step: \${2:1}, bounds: "full" } } }`; + case '$fill': + return `{ ${v}: { output: { \${1:field}: { method: "\${2:linear}" } } } }`; + case '$documents': + return `{ ${v}: [\${1:documents}] }`; + case '$changeStream': + return `{ ${v}: {} }`; + case '$collStats': + return `{ ${v}: { storageStats: {} } }`; + case '$currentOp': + return `{ ${v}: { allUsers: true } }`; + case '$indexStats': + return `{ ${v}: {} }`; + case '$listLocalSessions': + return `{ ${v}: { allUsers: true } }`; + case '$geoNear': + return `{ ${v}: { near: { type: "Point", coordinates: [\${1:lng}, \${2:lat}] }, distanceField: "\${3:distance}" } }`; + default: + return `{ ${v}: { \${1} } }`; + } +} + +// --------------------------------------------------------------------------- +// BSON type applicability +// --------------------------------------------------------------------------- + +function getApplicableBsonTypes(op: ParsedOperator, meta: string): string[] | undefined { + const v = op.value; + + // String-specific operators + if (v === '$regex' || v === '$text') return ['string']; + if (meta === 'META_EXPR_STRING' || meta === 'META_EXPR_TRIG') return undefined; // expression context, not filter-level + + // Array-specific operators (query context) + if (meta === 'META_QUERY_ARRAY') return ['array']; + + // Bitwise query operators + if (meta === 'META_QUERY_BITWISE') return ['int', 'long']; + + return undefined; +} + +// --------------------------------------------------------------------------- +// File generation +// --------------------------------------------------------------------------- + +function generateFileContent(specs: FileSpec[]): string { + const copyright = `/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// AUTO-GENERATED — DO NOT EDIT BY HAND +// +// Generated by: npm run generate (scripts/generate-from-reference.ts) +// Sources: resources/operator-reference-scraped.md +// resources/operator-reference-overrides.md +// +// To change operator data, edit the overrides file and re-run the generator. +`; + + // Collect all unique meta imports + const allMetaImports = new Set(); + for (const spec of specs) { + allMetaImports.add(spec.metaImport); + } + + const metaImportsList = [...allMetaImports].sort().join(',\n '); + + let content = `${copyright} +import { type OperatorEntry } from './types'; +import { ${metaImportsList} } from './metaTags'; +import { getDocLink } from './docLinks'; +import { registerOperators } from './getFilteredCompletions'; + +`; + + for (const spec of specs) { + content += generateSection(spec); + content += '\n'; + } + + // Registration call + const allVarNames = specs.map((s) => `...${s.variableName}`).join(',\n '); + content += `// ---------------------------------------------------------------------------\n`; + content += `// Registration\n`; + content += `// ---------------------------------------------------------------------------\n\n`; + content += `registerOperators([\n ${allVarNames},\n]);\n`; + + return content; +} + +function generateSection(spec: FileSpec): string { + let section = `// ---------------------------------------------------------------------------\n`; + section += `// ${spec.operators[0]?.category || spec.variableName}\n`; + section += `// ---------------------------------------------------------------------------\n\n`; + + section += `const ${spec.variableName}: readonly OperatorEntry[] = [\n`; + + for (const op of spec.operators) { + const snippet = op.snippetOverride || generateSnippet(op, spec.metaImport); + const bsonTypes = getApplicableBsonTypes(op, spec.metaImport); + + section += ` {\n`; + section += ` value: '${escapeString(op.value)}',\n`; + section += ` meta: ${spec.metaImport},\n`; + section += ` description: '${escapeString(op.description)}',\n`; + if (snippet) { + section += ` snippet: '${escapeString(snippet)}',\n`; + } + section += ` link: getDocLink('${escapeString(op.value)}', ${spec.metaImport}),\n`; + if (bsonTypes) { + section += ` applicableBsonTypes: [${bsonTypes.map((t) => `'${t}'`).join(', ')}],\n`; + } + section += ` },\n`; + } + + section += `];\n\n`; + return section; +} + +function escapeString(s: string): string { + return s.replace(/\\/g, '\\\\').replace(/'/g, "\\'"); +} + +// --------------------------------------------------------------------------- +// Group operators by file and generate +// --------------------------------------------------------------------------- + +function buildFileSpecs(categorizedOps: Map): Map { + const fileGroups = new Map(); + + // Track seen operators per file to deduplicate + const seenPerFile = new Map>(); + + for (const [category, ops] of categorizedOps) { + const fileName = CATEGORY_TO_FILE[category]; + const metaConst = CATEGORY_TO_META[category]; + + if (!fileName || !metaConst) { + console.warn(`⚠️ No mapping for category: "${category}" (${ops.length} operators)`); + continue; + } + + if (!seenPerFile.has(fileName)) { + seenPerFile.set(fileName, new Set()); + } + const seen = seenPerFile.get(fileName)!; + + // Deduplicate operators (e.g., $elemMatch appears in both query:array and projection) + const uniqueOps = ops.filter((op) => { + if (seen.has(op.value + ':' + metaConst)) return false; + seen.add(op.value + ':' + metaConst); + return true; + }); + + if (uniqueOps.length === 0) continue; + + // Create a camelCase variable name from the category + const varName = categoryToVarName(category); + + const spec: FileSpec = { + fileName, + variableName: varName, + metaImport: metaConst, + metaValue: metaConst, + operators: uniqueOps, + }; + + if (!fileGroups.has(fileName)) { + fileGroups.set(fileName, []); + } + fileGroups.get(fileName)!.push(spec); + } + + return fileGroups; +} + +function categoryToVarName(category: string): string { + // "Comparison Query Operators" → "comparisonQueryOperators" + // "Accumulators ($group, $bucket, $bucketAuto, $setWindowFields)" → "groupAccumulators" + + if (category === 'Accumulators ($group, $bucket, $bucketAuto, $setWindowFields)') { + return 'groupAccumulators'; + } + if (category === 'Accumulators (in Other Stages)') { + return 'otherStageAccumulators'; + } + if (category === 'Variables in Aggregation Expressions') { + return 'systemVariables'; + } + + const words = category + .replace(/[()$,]/g, '') + .split(/\s+/) + .filter((w) => w.length > 0); + return words + .map((w, i) => (i === 0 ? w.toLowerCase() : w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())) + .join(''); +} + +// --------------------------------------------------------------------------- +// Main +// --------------------------------------------------------------------------- + +function main(): void { + const dumpPath = path.join(__dirname, '..', 'resources', 'operator-reference-scraped.md'); + const overridePath = path.join(__dirname, '..', 'resources', 'operator-reference-overrides.md'); + const srcDir = path.join(__dirname, '..', 'src'); + + console.log('📖 Reading operator reference dump...'); + const content = fs.readFileSync(dumpPath, 'utf-8'); + + console.log('🔍 Parsing operators...'); + const categorizedOps = parseDump(content); + + let totalOps = 0; + for (const [cat, ops] of categorizedOps) { + console.log(` ${cat}: ${ops.length} operators`); + totalOps += ops.length; + } + console.log(` Total: ${totalOps} operators\n`); + + // Apply overrides if the file exists + if (fs.existsSync(overridePath)) { + console.log('📝 Reading overrides...'); + const overrideContent = fs.readFileSync(overridePath, 'utf-8'); + const overrides = parseOverrides(overrideContent); + applyOverrides(categorizedOps, overrides); + console.log(''); + } else { + console.log('ℹ️ No overrides file found, skipping.\n'); + } + + console.log('📁 Building file specs...'); + const fileGroups = buildFileSpecs(categorizedOps); + + for (const [fileName, specs] of fileGroups) { + const filePath = path.join(srcDir, `${fileName}.ts`); + console.log( + `✍️ Generating ${fileName}.ts (${specs.reduce((n, s) => n + s.operators.length, 0)} operators)...`, + ); + const fileContent = generateFileContent(specs); + fs.writeFileSync(filePath, fileContent, 'utf-8'); + } + + console.log('\n✅ Done! Generated files:'); + for (const [fileName, specs] of fileGroups) { + const count = specs.reduce((n, s) => n + s.operators.length, 0); + console.log(` src/${fileName}.ts — ${count} operators`); + } +} + +main(); diff --git a/packages/documentdb-constants/scripts/scrape-operator-docs.ts b/packages/documentdb-constants/scripts/scrape-operator-docs.ts index 557b91489..8f9a35d11 100644 --- a/packages/documentdb-constants/scripts/scrape-operator-docs.ts +++ b/packages/documentdb-constants/scripts/scrape-operator-docs.ts @@ -7,7 +7,7 @@ * scrape-operator-docs.ts * * Scrapes the DocumentDB compatibility page and per-operator documentation - * to generate the resources/operator-reference.md dump file. + * to generate the resources/operator-reference-scraped.md dump file. * * Usage: * npx ts-node packages/documentdb-constants/scripts/scrape-operator-docs.ts @@ -792,7 +792,7 @@ async function main(): Promise { console.log(''); // Phase 3: Generate dump - console.log(' Phase 3: Generating operator-reference.md...'); + console.log(' Phase 3: Generating operator-reference-scraped.md...'); const dump = generateDump(operators); const outputDir = path.join(__dirname, '..', 'resources'); @@ -800,7 +800,7 @@ async function main(): Promise { fs.mkdirSync(outputDir, { recursive: true }); } - const outputPath = path.join(outputDir, 'operator-reference.md'); + const outputPath = path.join(outputDir, 'operator-reference-scraped.md'); fs.writeFileSync(outputPath, dump, 'utf-8'); console.log(` Written to: ${outputPath}`); diff --git a/packages/documentdb-constants/src/accumulators.ts b/packages/documentdb-constants/src/accumulators.ts new file mode 100644 index 000000000..57fffd843 --- /dev/null +++ b/packages/documentdb-constants/src/accumulators.ts @@ -0,0 +1,183 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// AUTO-GENERATED — DO NOT EDIT BY HAND +// +// Generated by: npm run generate (scripts/generate-from-reference.ts) +// Sources: resources/operator-reference-scraped.md +// resources/operator-reference-overrides.md +// +// To change operator data, edit the overrides file and re-run the generator. + +import { getDocLink } from './docLinks'; +import { registerOperators } from './getFilteredCompletions'; +import { META_ACCUMULATOR } from './metaTags'; +import { type OperatorEntry } from './types'; + +// --------------------------------------------------------------------------- +// Accumulators ($group, $bucket, $bucketAuto, $setWindowFields) +// --------------------------------------------------------------------------- + +const groupAccumulators: readonly OperatorEntry[] = [ + { + value: '$addToSet', + meta: META_ACCUMULATOR, + description: + "The addToSet operator adds elements to an array if they don't already exist, while ensuring uniqueness of elements within the set.", + snippet: '{ $addToSet: "${1:\\$field}" }', + link: getDocLink('$addToSet', META_ACCUMULATOR), + }, + { + value: '$avg', + meta: META_ACCUMULATOR, + description: 'Computes the average of numeric values for documents in a group, bucket, or window.', + snippet: '{ $avg: "${1:\\$field}" }', + link: getDocLink('$avg', META_ACCUMULATOR), + }, + { + value: '$bottom', + meta: META_ACCUMULATOR, + description: + "The $bottom operator returns the last document from the query's result set sorted by one or more fields", + snippet: '{ $bottom: { sortBy: { ${1:field}: ${2:1} }, output: "${3:\\$field}" } }', + link: getDocLink('$bottom', META_ACCUMULATOR), + }, + { + value: '$bottomN', + meta: META_ACCUMULATOR, + description: 'The $bottomN operator returns the last N documents from the result sorted by one or more fields', + snippet: '{ $bottomN: { n: ${1:number}, sortBy: { ${2:field}: ${3:1} }, output: "${4:\\$field}" } }', + link: getDocLink('$bottomN', META_ACCUMULATOR), + }, + { + value: '$count', + meta: META_ACCUMULATOR, + description: + 'The `$count` operator is used to count the number of documents that match a query filtering criteria.', + snippet: '{ $count: {} }', + link: getDocLink('$count', META_ACCUMULATOR), + }, + { + value: '$first', + meta: META_ACCUMULATOR, + description: "The $first operator returns the first value in a group according to the group's sorting order.", + snippet: '{ $first: "${1:\\$field}" }', + link: getDocLink('$first', META_ACCUMULATOR), + }, + { + value: '$firstN', + meta: META_ACCUMULATOR, + description: + 'The $firstN operator sorts documents on one or more fields specified by the query and returns the first N document matching the filtering criteria', + snippet: '{ $firstN: { input: "${1:\\$field}", n: ${2:number} } }', + link: getDocLink('$firstN', META_ACCUMULATOR), + }, + { + value: '$last', + meta: META_ACCUMULATOR, + description: 'The $last operator returns the last document from the result sorted by one or more fields', + snippet: '{ $last: "${1:\\$field}" }', + link: getDocLink('$last', META_ACCUMULATOR), + }, + { + value: '$lastN', + meta: META_ACCUMULATOR, + description: 'The $lastN accumulator operator returns the last N values in a group of documents.', + snippet: '{ $lastN: { input: "${1:\\$field}", n: ${2:number} } }', + link: getDocLink('$lastN', META_ACCUMULATOR), + }, + { + value: '$max', + meta: META_ACCUMULATOR, + description: 'The $max operator returns the maximum value from a set of input values.', + snippet: '{ $max: "${1:\\$field}" }', + link: getDocLink('$max', META_ACCUMULATOR), + }, + { + value: '$maxN', + meta: META_ACCUMULATOR, + description: 'Retrieves the top N values based on a specified filtering criteria', + snippet: '{ $maxN: { input: "${1:\\$field}", n: ${2:number} } }', + link: getDocLink('$maxN', META_ACCUMULATOR), + }, + { + value: '$median', + meta: META_ACCUMULATOR, + description: 'The $median operator calculates the median value of a numeric field in a group of documents.', + snippet: '{ $median: { input: "${1:\\$field}", method: "approximate" } }', + link: getDocLink('$median', META_ACCUMULATOR), + }, + { + value: '$mergeObjects', + meta: META_ACCUMULATOR, + description: 'The $mergeObjects operator merges multiple documents into a single document', + snippet: '{ $mergeObjects: "${1:\\$field}" }', + link: getDocLink('$mergeObjects', META_ACCUMULATOR), + }, + { + value: '$min', + meta: META_ACCUMULATOR, + description: 'Retrieves the minimum value for a specified field', + snippet: '{ $min: "${1:\\$field}" }', + link: getDocLink('$min', META_ACCUMULATOR), + }, + { + value: '$percentile', + meta: META_ACCUMULATOR, + description: + 'The $percentile operator calculates the percentile of numerical values that match a filtering criteria', + snippet: '{ $percentile: { input: "${1:\\$field}", p: [${2:0.5}], method: "approximate" } }', + link: getDocLink('$percentile', META_ACCUMULATOR), + }, + { + value: '$push', + meta: META_ACCUMULATOR, + description: 'The $push operator adds a specified value to an array within a document.', + snippet: '{ $push: "${1:\\$field}" }', + link: getDocLink('$push', META_ACCUMULATOR), + }, + { + value: '$stdDevPop', + meta: META_ACCUMULATOR, + description: 'The $stddevpop operator calculates the standard deviation of the specified values', + snippet: '{ $stdDevPop: "${1:\\$field}" }', + link: getDocLink('$stdDevPop', META_ACCUMULATOR), + }, + { + value: '$stdDevSamp', + meta: META_ACCUMULATOR, + description: + 'The $stddevsamp operator calculates the standard deviation of a specified sample of values and not the entire population', + snippet: '{ $stdDevSamp: "${1:\\$field}" }', + link: getDocLink('$stdDevSamp', META_ACCUMULATOR), + }, + { + value: '$sum', + meta: META_ACCUMULATOR, + description: 'The $sum operator calculates the sum of the values of a field based on a filtering criteria', + snippet: '{ $sum: "${1:\\$field}" }', + link: getDocLink('$sum', META_ACCUMULATOR), + }, + { + value: '$top', + meta: META_ACCUMULATOR, + description: 'The $top operator returns the first document from the result set sorted by one or more fields', + snippet: '{ $top: { sortBy: { ${1:field}: ${2:1} }, output: "${3:\\$field}" } }', + link: getDocLink('$top', META_ACCUMULATOR), + }, + { + value: '$topN', + meta: META_ACCUMULATOR, + description: 'The $topN operator returns the first N documents from the result sorted by one or more fields', + snippet: '{ $topN: { n: ${1:number}, sortBy: { ${2:field}: ${3:1} }, output: "${4:\\$field}" } }', + link: getDocLink('$topN', META_ACCUMULATOR), + }, +]; + +// --------------------------------------------------------------------------- +// Registration +// --------------------------------------------------------------------------- + +registerOperators([...groupAccumulators]); diff --git a/packages/documentdb-constants/src/bsonConstructors.ts b/packages/documentdb-constants/src/bsonConstructors.ts new file mode 100644 index 000000000..fbe25bb0d --- /dev/null +++ b/packages/documentdb-constants/src/bsonConstructors.ts @@ -0,0 +1,81 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerOperators } from './getFilteredCompletions'; +import { META_BSON } from './metaTags'; +import { type OperatorEntry } from './types'; + +// --------------------------------------------------------------------------- +// BSON Constructor Functions +// --------------------------------------------------------------------------- + +const bsonConstructors: readonly OperatorEntry[] = [ + { + value: 'ObjectId', + meta: META_BSON, + description: 'Creates a new ObjectId value, a 12-byte unique identifier.', + snippet: 'ObjectId("${1:hex}")', + }, + { + value: 'ISODate', + meta: META_BSON, + description: 'Creates a date object from an ISO 8601 date string.', + snippet: 'ISODate("${1:yyyy-MM-ddTHH:mm:ssZ}")', + }, + { + value: 'NumberLong', + meta: META_BSON, + description: 'Creates a 64-bit integer (long) value.', + snippet: 'NumberLong(${1:value})', + }, + { + value: 'NumberInt', + meta: META_BSON, + description: 'Creates a 32-bit integer value.', + snippet: 'NumberInt(${1:value})', + }, + { + value: 'NumberDecimal', + meta: META_BSON, + description: 'Creates a 128-bit decimal value for high-precision calculations.', + snippet: 'NumberDecimal("${1:value}")', + }, + { + value: 'BinData', + meta: META_BSON, + description: 'Creates a binary data value with a specified subtype.', + snippet: 'BinData(${1:subtype}, "${2:base64}")', + }, + { + value: 'UUID', + meta: META_BSON, + description: 'Creates a UUID (Universally Unique Identifier) value.', + snippet: 'UUID("${1:uuid}")', + }, + { + value: 'Timestamp', + meta: META_BSON, + description: 'Creates a BSON timestamp value for internal replication use.', + snippet: 'Timestamp(${1:seconds}, ${2:increment})', + }, + { + value: 'MinKey', + meta: META_BSON, + description: 'Represents the lowest possible BSON value, comparing less than all other types.', + snippet: 'MinKey()', + }, + { + value: 'MaxKey', + meta: META_BSON, + description: 'Represents the highest possible BSON value, comparing greater than all other types.', + snippet: 'MaxKey()', + }, +]; + +// --------------------------------------------------------------------------- +// Registration +// --------------------------------------------------------------------------- + +registerOperators(bsonConstructors); diff --git a/packages/documentdb-constants/src/expressionOperators.ts b/packages/documentdb-constants/src/expressionOperators.ts new file mode 100644 index 000000000..6761b0786 --- /dev/null +++ b/packages/documentdb-constants/src/expressionOperators.ts @@ -0,0 +1,1213 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// AUTO-GENERATED — DO NOT EDIT BY HAND +// +// Generated by: npm run generate (scripts/generate-from-reference.ts) +// Sources: resources/operator-reference-scraped.md +// resources/operator-reference-overrides.md +// +// To change operator data, edit the overrides file and re-run the generator. + +import { getDocLink } from './docLinks'; +import { registerOperators } from './getFilteredCompletions'; +import { + META_EXPR_ARITH, + META_EXPR_ARRAY, + META_EXPR_BITWISE, + META_EXPR_BOOL, + META_EXPR_COMPARISON, + META_EXPR_CONDITIONAL, + META_EXPR_DATASIZE, + META_EXPR_DATE, + META_EXPR_LITERAL, + META_EXPR_MISC, + META_EXPR_OBJECT, + META_EXPR_SET, + META_EXPR_STRING, + META_EXPR_TIMESTAMP, + META_EXPR_TRIG, + META_EXPR_TYPE, + META_EXPR_VARIABLE, +} from './metaTags'; +import { type OperatorEntry } from './types'; + +// --------------------------------------------------------------------------- +// Arithmetic Expression Operators +// --------------------------------------------------------------------------- + +const arithmeticExpressionOperators: readonly OperatorEntry[] = [ + { + value: '$abs', + meta: META_EXPR_ARITH, + description: 'The $abs operator returns the absolute value of a number.', + snippet: '{ $abs: "${1:\\$field}" }', + link: getDocLink('$abs', META_EXPR_ARITH), + }, + { + value: '$add', + meta: META_EXPR_ARITH, + description: 'The $add operator returns the sum of two numbers or the sum of a date and numbers.', + snippet: '{ $add: ["${1:\\$field1}", "${2:\\$field2}"] }', + link: getDocLink('$add', META_EXPR_ARITH), + }, + { + value: '$ceil', + meta: META_EXPR_ARITH, + description: 'The $ceil operator returns the smallest integer greater than or equal to the specified number.', + snippet: '{ $ceil: "${1:\\$field}" }', + link: getDocLink('$ceil', META_EXPR_ARITH), + }, + { + value: '$divide', + meta: META_EXPR_ARITH, + description: 'The $divide operator divides two numbers and returns the quotient.', + snippet: '{ $divide: ["${1:\\$field1}", "${2:\\$field2}"] }', + link: getDocLink('$divide', META_EXPR_ARITH), + }, + { + value: '$exp', + meta: META_EXPR_ARITH, + description: 'The $exp operator raises e to the specified exponent and returns the result', + snippet: '{ $exp: "${1:\\$field}" }', + link: getDocLink('$exp', META_EXPR_ARITH), + }, + { + value: '$floor', + meta: META_EXPR_ARITH, + description: 'The $floor operator returns the largest integer less than or equal to the specified number', + snippet: '{ $floor: "${1:\\$field}" }', + link: getDocLink('$floor', META_EXPR_ARITH), + }, + { + value: '$ln', + meta: META_EXPR_ARITH, + description: 'The $ln operator calculates the natural logarithm of the input', + snippet: '{ $ln: "${1:\\$field}" }', + link: getDocLink('$ln', META_EXPR_ARITH), + }, + { + value: '$log', + meta: META_EXPR_ARITH, + description: 'The $log operator calculates the logarithm of a number in the specified base', + snippet: '{ $log: ["${1:\\$number}", ${2:base}] }', + link: getDocLink('$log', META_EXPR_ARITH), + }, + { + value: '$log10', + meta: META_EXPR_ARITH, + description: 'The $log10 operator calculates the log of a specified number in base 10', + snippet: '{ $log10: "${1:\\$field}" }', + link: getDocLink('$log10', META_EXPR_ARITH), + }, + { + value: '$mod', + meta: META_EXPR_ARITH, + description: + 'The $mod operator performs a modulo operation on the value of a field and selects documents with a specified result.', + snippet: '{ $mod: ["${1:\\$field1}", "${2:\\$field2}"] }', + link: getDocLink('$mod', META_EXPR_ARITH), + }, + { + value: '$multiply', + meta: META_EXPR_ARITH, + description: 'The $multiply operator multiplies the input numerical values', + snippet: '{ $multiply: ["${1:\\$field1}", "${2:\\$field2}"] }', + link: getDocLink('$multiply', META_EXPR_ARITH), + }, + { + value: '$pow', + meta: META_EXPR_ARITH, + description: + 'The `$pow` operator calculates the value of a numerical value raised to the power of a specified exponent.', + snippet: '{ $pow: ["${1:\\$field1}", "${2:\\$field2}"] }', + link: getDocLink('$pow', META_EXPR_ARITH), + }, + { + value: '$round', + meta: META_EXPR_ARITH, + description: 'The $round operator rounds a number to a specified decimal place.', + snippet: '{ $round: ["${1:\\$field}", ${2:place}] }', + link: getDocLink('$round', META_EXPR_ARITH), + }, + { + value: '$sqrt', + meta: META_EXPR_ARITH, + description: 'The $sqrt operator calculates and returns the square root of an input number', + snippet: '{ $sqrt: "${1:\\$field}" }', + link: getDocLink('$sqrt', META_EXPR_ARITH), + }, + { + value: '$subtract', + meta: META_EXPR_ARITH, + description: 'The $subtract operator subtracts two numbers and returns the result.', + snippet: '{ $subtract: ["${1:\\$field1}", "${2:\\$field2}"] }', + link: getDocLink('$subtract', META_EXPR_ARITH), + }, + { + value: '$trunc', + meta: META_EXPR_ARITH, + description: 'The $trunc operator truncates a number to a specified decimal place.', + snippet: '{ $trunc: "${1:\\$field}" }', + link: getDocLink('$trunc', META_EXPR_ARITH), + }, +]; + +// --------------------------------------------------------------------------- +// Array Expression Operators +// --------------------------------------------------------------------------- + +const arrayExpressionOperators: readonly OperatorEntry[] = [ + { + value: '$arrayElemAt', + meta: META_EXPR_ARRAY, + description: 'The $arrayElemAt returns the element at the specified array index.', + snippet: '{ $arrayElemAt: ["${1:\\$array}", ${2:index}] }', + link: getDocLink('$arrayElemAt', META_EXPR_ARRAY), + }, + { + value: '$arrayToObject', + meta: META_EXPR_ARRAY, + description: 'The $arrayToObject allows converting an array into a single document.', + snippet: '{ $arrayToObject: "${1:\\$array}" }', + link: getDocLink('$arrayToObject', META_EXPR_ARRAY), + }, + { + value: '$concatArrays', + meta: META_EXPR_ARRAY, + description: 'The $concatArrays is used to combine multiple arrays into a single array.', + snippet: '{ $concatArrays: ["${1:\\$array1}", "${2:\\$array2}"] }', + link: getDocLink('$concatArrays', META_EXPR_ARRAY), + }, + { + value: '$filter', + meta: META_EXPR_ARRAY, + description: 'The $filter operator filters for elements from an array based on a specified condition.', + snippet: '{ $filter: { input: "${1:\\$array}", as: "${2:item}", cond: { ${3:expression} } } }', + link: getDocLink('$filter', META_EXPR_ARRAY), + }, + { + value: '$firstN', + meta: META_EXPR_ARRAY, + description: + 'The $firstN operator sorts documents on one or more fields specified by the query and returns the first N document matching the filtering criteria', + snippet: '{ $firstN: { input: "${1:\\$array}", n: ${2:number} } }', + link: getDocLink('$firstN', META_EXPR_ARRAY), + }, + { + value: '$in', + meta: META_EXPR_ARRAY, + description: 'The $in operator matches value of a field against an array of specified values', + snippet: '{ $in: ["${1:\\$field}", "${2:\\$array}"] }', + link: getDocLink('$in', META_EXPR_ARRAY), + }, + { + value: '$indexOfArray', + meta: META_EXPR_ARRAY, + description: + 'The $indexOfArray operator is used to search for an element in an array and return the index of the first occurrence of the element.', + snippet: '{ $indexOfArray: ["${1:\\$array}", "${2:value}"] }', + link: getDocLink('$indexOfArray', META_EXPR_ARRAY), + }, + { + value: '$isArray', + meta: META_EXPR_ARRAY, + description: 'The $isArray operator is used to determine if a specified value is an array.', + snippet: '{ $isArray: "${1:\\$field}" }', + link: getDocLink('$isArray', META_EXPR_ARRAY), + }, + { + value: '$lastN', + meta: META_EXPR_ARRAY, + description: 'The $lastN accumulator operator returns the last N values in a group of documents.', + snippet: '{ $lastN: { input: "${1:\\$array}", n: ${2:number} } }', + link: getDocLink('$lastN', META_EXPR_ARRAY), + }, + { + value: '$map', + meta: META_EXPR_ARRAY, + description: 'The $map operator allows applying an expression to each element in an array.', + snippet: '{ $map: { input: "${1:\\$array}", as: "${2:item}", in: { ${3:expression} } } }', + link: getDocLink('$map', META_EXPR_ARRAY), + }, + { + value: '$maxN', + meta: META_EXPR_ARRAY, + description: 'Retrieves the top N values based on a specified filtering criteria', + snippet: '{ $maxN: { input: "${1:\\$array}", n: ${2:number} } }', + link: getDocLink('$maxN', META_EXPR_ARRAY), + }, + { + value: '$minN', + meta: META_EXPR_ARRAY, + description: 'Retrieves the bottom N values based on a specified filtering criteria', + snippet: '{ $minN: { input: "${1:\\$array}", n: ${2:number} } }', + link: getDocLink('$minN', META_EXPR_ARRAY), + }, + { + value: '$objectToArray', + meta: META_EXPR_ARRAY, + description: 'Converts an object into an array of key-value pair documents.', + snippet: '{ $objectToArray: "${1:\\$object}" }', + link: getDocLink('$objectToArray', META_EXPR_ARRAY), + }, + { + value: '$range', + meta: META_EXPR_ARRAY, + description: 'The $range operator allows generating an array of sequential integers.', + snippet: '{ $range: [${1:start}, ${2:end}, ${3:step}] }', + link: getDocLink('$range', META_EXPR_ARRAY), + }, + { + value: '$reduce', + meta: META_EXPR_ARRAY, + description: + 'The $reduce operator applies an expression to each element in an array & accumulate result as single value.', + snippet: '{ $reduce: { input: "${1:\\$array}", initialValue: ${2:0}, in: { ${3:expression} } } }', + link: getDocLink('$reduce', META_EXPR_ARRAY), + }, + { + value: '$reverseArray', + meta: META_EXPR_ARRAY, + description: 'The $reverseArray operator is used to reverse the order of elements in an array.', + snippet: '{ $reverseArray: "${1:\\$array}" }', + link: getDocLink('$reverseArray', META_EXPR_ARRAY), + }, + { + value: '$size', + meta: META_EXPR_ARRAY, + description: + 'The $size operator is used to query documents where an array field has a specified number of elements.', + snippet: '{ $size: "${1:\\$array}" }', + link: getDocLink('$size', META_EXPR_ARRAY), + }, + { + value: '$slice', + meta: META_EXPR_ARRAY, + description: 'The $slice operator returns a subset of an array from any element onwards in the array.', + snippet: '{ $slice: ["${1:\\$array}", ${2:n}] }', + link: getDocLink('$slice', META_EXPR_ARRAY), + }, + { + value: '$sortArray', + meta: META_EXPR_ARRAY, + description: 'The $sortArray operator helps in sorting the elements in an array.', + snippet: '{ $sortArray: { input: "${1:\\$array}", sortBy: { ${2:field}: ${3:1} } } }', + link: getDocLink('$sortArray', META_EXPR_ARRAY), + }, + { + value: '$zip', + meta: META_EXPR_ARRAY, + description: 'The $zip operator allows merging two or more arrays element-wise into a single array or arrays.', + snippet: '{ $zip: { inputs: ["${1:\\$array1}", "${2:\\$array2}"] } }', + link: getDocLink('$zip', META_EXPR_ARRAY), + }, +]; + +// --------------------------------------------------------------------------- +// Bitwise Operators +// --------------------------------------------------------------------------- + +const bitwiseOperators: readonly OperatorEntry[] = [ + { + value: '$bitAnd', + meta: META_EXPR_BITWISE, + description: + 'The $bitAnd operator performs a bitwise AND operation on integer values and returns the result as an integer.', + snippet: '{ $bitAnd: [${1:value1}, ${2:value2}] }', + link: getDocLink('$bitAnd', META_EXPR_BITWISE), + }, + { + value: '$bitNot', + meta: META_EXPR_BITWISE, + description: + 'The $bitNot operator performs a bitwise NOT operation on integer values and returns the result as an integer.', + snippet: '{ $bitNot: "${1:\\$field}" }', + link: getDocLink('$bitNot', META_EXPR_BITWISE), + }, + { + value: '$bitOr', + meta: META_EXPR_BITWISE, + description: + 'The $bitOr operator performs a bitwise OR operation on integer values and returns the result as an integer.', + snippet: '{ $bitOr: [${1:value1}, ${2:value2}] }', + link: getDocLink('$bitOr', META_EXPR_BITWISE), + }, + { + value: '$bitXor', + meta: META_EXPR_BITWISE, + description: 'The $bitXor operator performs a bitwise XOR operation on integer values.', + snippet: '{ $bitXor: [${1:value1}, ${2:value2}] }', + link: getDocLink('$bitXor', META_EXPR_BITWISE), + }, +]; + +// --------------------------------------------------------------------------- +// Boolean Expression Operators +// --------------------------------------------------------------------------- + +const booleanExpressionOperators: readonly OperatorEntry[] = [ + { + value: '$and', + meta: META_EXPR_BOOL, + description: + 'The $and operator joins multiple query clauses and returns documents that match all specified conditions.', + snippet: '{ $and: ["${1:expression1}", "${2:expression2}"] }', + link: getDocLink('$and', META_EXPR_BOOL), + }, + { + value: '$not', + meta: META_EXPR_BOOL, + description: + "The $not operator performs a logical NOT operation on a specified expression, selecting documents that don't match the expression.", + snippet: '{ $not: ["${1:expression}"] }', + link: getDocLink('$not', META_EXPR_BOOL), + }, + { + value: '$or', + meta: META_EXPR_BOOL, + description: + 'The $or operator joins query clauses with a logical OR and returns documents that match at least one of the specified conditions.', + snippet: '{ $or: ["${1:expression1}", "${2:expression2}"] }', + link: getDocLink('$or', META_EXPR_BOOL), + }, +]; + +// --------------------------------------------------------------------------- +// Comparison Expression Operators +// --------------------------------------------------------------------------- + +const comparisonExpressionOperators: readonly OperatorEntry[] = [ + { + value: '$cmp', + meta: META_EXPR_COMPARISON, + description: 'The $cmp operator compares two values', + snippet: '{ $cmp: ["${1:\\$field1}", "${2:\\$field2}"] }', + link: getDocLink('$cmp', META_EXPR_COMPARISON), + }, + { + value: '$eq', + meta: META_EXPR_COMPARISON, + description: 'The $eq query operator compares the value of a field to a specified value', + snippet: '{ $eq: ["${1:\\$field1}", "${2:\\$field2}"] }', + link: getDocLink('$eq', META_EXPR_COMPARISON), + }, + { + value: '$gt', + meta: META_EXPR_COMPARISON, + description: + 'The $gt query operator retrieves documents where the value of a field is greater than a specified value', + snippet: '{ $gt: ["${1:\\$field1}", "${2:\\$field2}"] }', + link: getDocLink('$gt', META_EXPR_COMPARISON), + }, + { + value: '$gte', + meta: META_EXPR_COMPARISON, + description: + 'The $gte operator retrieves documents where the value of a field is greater than or equal to a specified value', + snippet: '{ $gte: ["${1:\\$field1}", "${2:\\$field2}"] }', + link: getDocLink('$gte', META_EXPR_COMPARISON), + }, + { + value: '$lt', + meta: META_EXPR_COMPARISON, + description: 'The $lt operator retrieves documents where the value of field is less than a specified value', + snippet: '{ $lt: ["${1:\\$field1}", "${2:\\$field2}"] }', + link: getDocLink('$lt', META_EXPR_COMPARISON), + }, + { + value: '$lte', + meta: META_EXPR_COMPARISON, + description: + 'The $lte operator retrieves documents where the value of a field is less than or equal to a specified value', + snippet: '{ $lte: ["${1:\\$field1}", "${2:\\$field2}"] }', + link: getDocLink('$lte', META_EXPR_COMPARISON), + }, + { + value: '$ne', + meta: META_EXPR_COMPARISON, + description: "The $ne operator retrieves documents where the value of a field doesn't equal a specified value", + snippet: '{ $ne: ["${1:\\$field1}", "${2:\\$field2}"] }', + link: getDocLink('$ne', META_EXPR_COMPARISON), + }, +]; + +// --------------------------------------------------------------------------- +// Data Size Operators +// --------------------------------------------------------------------------- + +const dataSizeOperators: readonly OperatorEntry[] = [ + { + value: '$bsonSize', + meta: META_EXPR_DATASIZE, + description: 'The $bsonSize operator returns the size of a document in bytes when encoded as BSON.', + snippet: '{ $bsonSize: "${1:\\$field}" }', + link: getDocLink('$bsonSize', META_EXPR_DATASIZE), + }, + { + value: '$binarySize', + meta: META_EXPR_DATASIZE, + description: 'The $binarySize operator is used to return the size of a binary data field.', + snippet: '{ $binarySize: "${1:\\$field}" }', + link: getDocLink('$binarySize', META_EXPR_DATASIZE), + }, +]; + +// --------------------------------------------------------------------------- +// Date Expression Operators +// --------------------------------------------------------------------------- + +const dateExpressionOperators: readonly OperatorEntry[] = [ + { + value: '$dateAdd', + meta: META_EXPR_DATE, + description: 'The $dateAdd operator adds a specified number of time units (day, hour, month etc) to a date.', + snippet: '{ $dateAdd: { startDate: "${1:\\$dateField}", unit: "${2:day}", amount: ${3:1} } }', + link: getDocLink('$dateAdd', META_EXPR_DATE), + }, + { + value: '$dateDiff', + meta: META_EXPR_DATE, + description: + 'The $dateDiff operator calculates the difference between two dates in various units such as years, months, days, etc.', + snippet: '{ $dateDiff: { startDate: "${1:\\$startDate}", endDate: "${2:\\$endDate}", unit: "${3:day}" } }', + link: getDocLink('$dateDiff', META_EXPR_DATE), + }, + { + value: '$dateFromParts', + meta: META_EXPR_DATE, + description: 'The $dateFromParts operator constructs a date from individual components.', + snippet: '{ $dateFromParts: { year: ${1:2024}, month: ${2:1}, day: ${3:1} } }', + link: getDocLink('$dateFromParts', META_EXPR_DATE), + }, + { + value: '$dateFromString', + meta: META_EXPR_DATE, + description: 'The $dateDiff operator converts a date/time string to a date object.', + snippet: '{ $dateFromString: { dateString: "${1:dateString}" } }', + link: getDocLink('$dateFromString', META_EXPR_DATE), + }, + { + value: '$dateSubtract', + meta: META_EXPR_DATE, + description: 'The $dateSubtract operator subtracts a specified amount of time from a date.', + snippet: '{ $dateSubtract: { startDate: "${1:\\$dateField}", unit: "${2:day}", amount: ${3:1} } }', + link: getDocLink('$dateSubtract', META_EXPR_DATE), + }, + { + value: '$dateToParts', + meta: META_EXPR_DATE, + description: + 'The $dateToParts operator decomposes a date into its individual parts such as year, month, day, and more.', + snippet: '{ $dateToParts: { date: "${1:\\$dateField}" } }', + link: getDocLink('$dateToParts', META_EXPR_DATE), + }, + { + value: '$dateToString', + meta: META_EXPR_DATE, + description: 'The $dateToString operator converts a date object into a formatted string.', + snippet: '{ $dateToString: { format: "${1:%Y-%m-%d}", date: "${2:\\$dateField}" } }', + link: getDocLink('$dateToString', META_EXPR_DATE), + }, + { + value: '$dateTrunc', + meta: META_EXPR_DATE, + description: 'The $dateTrunc operator truncates a date to a specified unit.', + snippet: '{ $dateTrunc: { date: "${1:\\$dateField}", unit: "${2:day}" } }', + link: getDocLink('$dateTrunc', META_EXPR_DATE), + }, + { + value: '$dayOfMonth', + meta: META_EXPR_DATE, + description: 'The $dayOfMonth operator extracts the day of the month from a date.', + snippet: '{ $dayOfMonth: "${1:\\$dateField}" }', + link: getDocLink('$dayOfMonth', META_EXPR_DATE), + }, + { + value: '$dayOfWeek', + meta: META_EXPR_DATE, + description: 'The $dayOfWeek operator extracts the day of the week from a date.', + snippet: '{ $dayOfWeek: "${1:\\$dateField}" }', + link: getDocLink('$dayOfWeek', META_EXPR_DATE), + }, + { + value: '$dayOfYear', + meta: META_EXPR_DATE, + description: 'The $dayOfYear operator extracts the day of the year from a date.', + snippet: '{ $dayOfYear: "${1:\\$dateField}" }', + link: getDocLink('$dayOfYear', META_EXPR_DATE), + }, + { + value: '$hour', + meta: META_EXPR_DATE, + description: 'The $hour operator returns the hour portion of a date as a number between 0 and 23.', + snippet: '{ $hour: "${1:\\$dateField}" }', + link: getDocLink('$hour', META_EXPR_DATE), + }, + { + value: '$isoDayOfWeek', + meta: META_EXPR_DATE, + description: + 'The $isoDayOfWeek operator returns the weekday number in ISO 8601 format, ranging from 1 (Monday) to 7 (Sunday).', + snippet: '{ $isoDayOfWeek: "${1:\\$dateField}" }', + link: getDocLink('$isoDayOfWeek', META_EXPR_DATE), + }, + { + value: '$isoWeek', + meta: META_EXPR_DATE, + description: + 'The $isoWeek operator returns the week number of the year in ISO 8601 format, ranging from 1 to 53.', + snippet: '{ $isoWeek: "${1:\\$dateField}" }', + link: getDocLink('$isoWeek', META_EXPR_DATE), + }, + { + value: '$isoWeekYear', + meta: META_EXPR_DATE, + description: + 'The $isoWeekYear operator returns the year number in ISO 8601 format, which can differ from the calendar year for dates at the beginning or end of the year.', + snippet: '{ $isoWeekYear: "${1:\\$dateField}" }', + link: getDocLink('$isoWeekYear', META_EXPR_DATE), + }, + { + value: '$millisecond', + meta: META_EXPR_DATE, + description: 'The $millisecond operator extracts the milliseconds portion from a date value.', + snippet: '{ $millisecond: "${1:\\$dateField}" }', + link: getDocLink('$millisecond', META_EXPR_DATE), + }, + { + value: '$minute', + meta: META_EXPR_DATE, + description: 'The $minute operator extracts the minute portion from a date value.', + snippet: '{ $minute: "${1:\\$dateField}" }', + link: getDocLink('$minute', META_EXPR_DATE), + }, + { + value: '$month', + meta: META_EXPR_DATE, + description: 'The $month operator extracts the month portion from a date value.', + snippet: '{ $month: "${1:\\$dateField}" }', + link: getDocLink('$month', META_EXPR_DATE), + }, + { + value: '$second', + meta: META_EXPR_DATE, + description: 'The $second operator extracts the seconds portion from a date value.', + snippet: '{ $second: "${1:\\$dateField}" }', + link: getDocLink('$second', META_EXPR_DATE), + }, + { + value: '$toDate', + meta: META_EXPR_DATE, + description: 'The $toDate operator converts supported types to a proper Date object.', + snippet: '{ $toDate: "${1:\\$field}" }', + link: getDocLink('$toDate', META_EXPR_DATE), + }, + { + value: '$week', + meta: META_EXPR_DATE, + description: 'The $week operator returns the week number for a date as a value between 0 and 53.', + snippet: '{ $week: "${1:\\$dateField}" }', + link: getDocLink('$week', META_EXPR_DATE), + }, + { + value: '$year', + meta: META_EXPR_DATE, + description: 'The $year operator returns the year for a date as a four-digit number.', + snippet: '{ $year: "${1:\\$dateField}" }', + link: getDocLink('$year', META_EXPR_DATE), + }, +]; + +// --------------------------------------------------------------------------- +// Literal Expression Operator +// --------------------------------------------------------------------------- + +const literalExpressionOperator: readonly OperatorEntry[] = [ + { + value: '$literal', + meta: META_EXPR_LITERAL, + description: + 'The $literal operator returns the specified value without parsing it as an expression, allowing literal values to be used in aggregation pipelines.', + snippet: '{ $literal: ${1:value} }', + link: getDocLink('$literal', META_EXPR_LITERAL), + }, +]; + +// --------------------------------------------------------------------------- +// Miscellaneous Operators +// --------------------------------------------------------------------------- + +const miscellaneousOperators: readonly OperatorEntry[] = [ + { + value: '$getField', + meta: META_EXPR_MISC, + description: 'The $getField operator allows retrieving the value of a specified field from a document.', + snippet: '{ $getField: { field: "${1:fieldName}", input: "${2:\\$object}" } }', + link: getDocLink('$getField', META_EXPR_MISC), + }, + { + value: '$rand', + meta: META_EXPR_MISC, + description: 'The $rand operator generates a random float value between 0 and 1.', + snippet: '{ $rand: {} }', + link: getDocLink('$rand', META_EXPR_MISC), + }, + { + value: '$sampleRate', + meta: META_EXPR_MISC, + description: + 'The $sampleRate operator randomly samples documents from a collection based on a specified probability rate, useful for statistical analysis and testing.', + snippet: '{ $sampleRate: ${1:0.5} }', + link: getDocLink('$sampleRate', META_EXPR_MISC), + }, +]; + +// --------------------------------------------------------------------------- +// Object Expression Operators +// --------------------------------------------------------------------------- + +const objectExpressionOperators: readonly OperatorEntry[] = [ + { + value: '$mergeObjects', + meta: META_EXPR_OBJECT, + description: 'The $mergeObjects operator merges multiple documents into a single document', + snippet: '{ $mergeObjects: ["${1:\\$object1}", "${2:\\$object2}"] }', + link: getDocLink('$mergeObjects', META_EXPR_OBJECT), + }, + { + value: '$objectToArray', + meta: META_EXPR_OBJECT, + description: + 'The objectToArray command is used to transform a document (object) into an array of key-value pairs.', + snippet: '{ $objectToArray: "${1:\\$object}" }', + link: getDocLink('$objectToArray', META_EXPR_OBJECT), + }, + { + value: '$setField', + meta: META_EXPR_OBJECT, + description: 'The setField command is used to add, update, or remove fields in embedded documents.', + snippet: '{ $setField: { field: "${1:fieldName}", input: "${2:\\$object}", value: ${3:value} } }', + link: getDocLink('$setField', META_EXPR_OBJECT), + }, +]; + +// --------------------------------------------------------------------------- +// Set Expression Operators +// --------------------------------------------------------------------------- + +const setExpressionOperators: readonly OperatorEntry[] = [ + { + value: '$allElementsTrue', + meta: META_EXPR_SET, + description: 'The $allElementsTrue operator returns true if all elements in an array evaluate to true.', + snippet: '{ $allElementsTrue: ["${1:\\$array}"] }', + link: getDocLink('$allElementsTrue', META_EXPR_SET), + }, + { + value: '$anyElementTrue', + meta: META_EXPR_SET, + description: + 'The $anyElementTrue operator returns true if any element in an array evaluates to a value of true.', + snippet: '{ $anyElementTrue: ["${1:\\$array}"] }', + link: getDocLink('$anyElementTrue', META_EXPR_SET), + }, + { + value: '$setDifference', + meta: META_EXPR_SET, + description: + 'The $setDifference operator returns a set with elements that exist in one set but not in a second set.', + snippet: '{ $setDifference: ["${1:\\$set1}", "${2:\\$set2}"] }', + link: getDocLink('$setDifference', META_EXPR_SET), + }, + { + value: '$setEquals', + meta: META_EXPR_SET, + description: 'The $setEquals operator returns true if two sets have the same distinct elements.', + snippet: '{ $setEquals: ["${1:\\$set1}", "${2:\\$set2}"] }', + link: getDocLink('$setEquals', META_EXPR_SET), + }, + { + value: '$setIntersection', + meta: META_EXPR_SET, + description: 'The $setIntersection operator returns the common elements that appear in all input arrays.', + snippet: '{ $setIntersection: ["${1:\\$set1}", "${2:\\$set2}"] }', + link: getDocLink('$setIntersection', META_EXPR_SET), + }, + { + value: '$setIsSubset', + meta: META_EXPR_SET, + description: 'The $setIsSubset operator determines if one array is a subset of a second array.', + snippet: '{ $setIsSubset: ["${1:\\$set1}", "${2:\\$set2}"] }', + link: getDocLink('$setIsSubset', META_EXPR_SET), + }, + { + value: '$setUnion', + meta: META_EXPR_SET, + description: + 'The $setUnion operator returns an array that contains all the unique elements from the input arrays.', + snippet: '{ $setUnion: ["${1:\\$set1}", "${2:\\$set2}"] }', + link: getDocLink('$setUnion', META_EXPR_SET), + }, +]; + +// --------------------------------------------------------------------------- +// String Expression Operators +// --------------------------------------------------------------------------- + +const stringExpressionOperators: readonly OperatorEntry[] = [ + { + value: '$concat', + meta: META_EXPR_STRING, + description: 'Concatenates two or more strings and returns the resulting string.', + snippet: '{ $concat: ["${1:\\$string1}", "${2:\\$string2}"] }', + link: getDocLink('$concat', META_EXPR_STRING), + }, + { + value: '$dateFromString', + meta: META_EXPR_STRING, + description: 'The $dateDiff operator converts a date/time string to a date object.', + snippet: '{ $dateFromString: "${1:\\$string}" }', + link: getDocLink('$dateFromString', META_EXPR_STRING), + }, + { + value: '$dateToString', + meta: META_EXPR_STRING, + description: 'The $dateToString operator converts a date object into a formatted string.', + snippet: '{ $dateToString: "${1:\\$string}" }', + link: getDocLink('$dateToString', META_EXPR_STRING), + }, + { + value: '$indexOfBytes', + meta: META_EXPR_STRING, + description: 'Returns the byte index of the first occurrence of a substring within a string.', + snippet: '{ $indexOfBytes: ["${1:\\$string}", "${2:substring}"] }', + link: getDocLink('$indexOfBytes', META_EXPR_STRING), + }, + { + value: '$indexOfCP', + meta: META_EXPR_STRING, + description: 'Returns the code point index of the first occurrence of a substring within a string.', + snippet: '{ $indexOfCP: ["${1:\\$string}", "${2:substring}"] }', + link: getDocLink('$indexOfCP', META_EXPR_STRING), + }, + { + value: '$ltrim', + meta: META_EXPR_STRING, + description: 'Removes whitespace or specified characters from the beginning of a string.', + snippet: '{ $ltrim: { input: "${1:\\$string}" } }', + link: getDocLink('$ltrim', META_EXPR_STRING), + }, + { + value: '$regexFind', + meta: META_EXPR_STRING, + description: 'Applies a regular expression to a string and returns the first match.', + snippet: '{ $regexFind: { input: "${1:\\$string}", regex: "${2:pattern}" } }', + link: getDocLink('$regexFind', META_EXPR_STRING), + }, + { + value: '$regexFindAll', + meta: META_EXPR_STRING, + description: 'Applies a regular expression to a string and returns all matches as an array.', + snippet: '{ $regexFindAll: { input: "${1:\\$string}", regex: "${2:pattern}" } }', + link: getDocLink('$regexFindAll', META_EXPR_STRING), + }, + { + value: '$regexMatch', + meta: META_EXPR_STRING, + description: 'Applies a regular expression to a string and returns a boolean indicating if a match was found.', + snippet: '{ $regexMatch: { input: "${1:\\$string}", regex: "${2:pattern}" } }', + link: getDocLink('$regexMatch', META_EXPR_STRING), + }, + { + value: '$replaceOne', + meta: META_EXPR_STRING, + description: 'Replaces the first occurrence of a search string with a replacement string.', + snippet: '{ $replaceOne: { input: "${1:\\$string}", find: "${2:find}", replacement: "${3:replacement}" } }', + link: getDocLink('$replaceOne', META_EXPR_STRING), + }, + { + value: '$replaceAll', + meta: META_EXPR_STRING, + description: 'Replaces all occurrences of a search string with a replacement string.', + snippet: '{ $replaceAll: { input: "${1:\\$string}", find: "${2:find}", replacement: "${3:replacement}" } }', + link: getDocLink('$replaceAll', META_EXPR_STRING), + }, + { + value: '$rtrim', + meta: META_EXPR_STRING, + description: 'Removes whitespace or specified characters from the end of a string.', + snippet: '{ $rtrim: { input: "${1:\\$string}" } }', + link: getDocLink('$rtrim', META_EXPR_STRING), + }, + { + value: '$split', + meta: META_EXPR_STRING, + description: 'Splits a string by a delimiter and returns an array of substrings.', + snippet: '{ $split: ["${1:\\$string}", "${2:delimiter}"] }', + link: getDocLink('$split', META_EXPR_STRING), + }, + { + value: '$strLenBytes', + meta: META_EXPR_STRING, + description: 'Returns the number of UTF-8 encoded bytes in the specified string.', + snippet: '{ $strLenBytes: "${1:\\$string}" }', + link: getDocLink('$strLenBytes', META_EXPR_STRING), + }, + { + value: '$strLenCP', + meta: META_EXPR_STRING, + description: 'Returns the number of UTF-8 code points in the specified string.', + snippet: '{ $strLenCP: "${1:\\$string}" }', + link: getDocLink('$strLenCP', META_EXPR_STRING), + }, + { + value: '$strcasecmp', + meta: META_EXPR_STRING, + description: 'Performs a case-insensitive comparison of two strings and returns an integer.', + snippet: '{ $strcasecmp: ["${1:\\$string1}", "${2:\\$string2}"] }', + link: getDocLink('$strcasecmp', META_EXPR_STRING), + }, + { + value: '$substr', + meta: META_EXPR_STRING, + description: + 'Returns a substring of a string, starting at a specified index for a specified length. Deprecated — use $substrBytes or $substrCP.', + snippet: '{ $substr: ["${1:\\$string}", ${2:start}, ${3:length}] }', + link: getDocLink('$substr', META_EXPR_STRING), + }, + { + value: '$substrBytes', + meta: META_EXPR_STRING, + description: + 'Returns a substring of a string by byte index, starting at a specified index for a specified number of bytes.', + snippet: '{ $substrBytes: ["${1:\\$string}", ${2:start}, ${3:length}] }', + link: getDocLink('$substrBytes', META_EXPR_STRING), + }, + { + value: '$substrCP', + meta: META_EXPR_STRING, + description: + 'Returns a substring of a string by code point index, starting at a specified index for a specified number of code points.', + snippet: '{ $substrCP: ["${1:\\$string}", ${2:start}, ${3:length}] }', + link: getDocLink('$substrCP', META_EXPR_STRING), + }, + { + value: '$toLower', + meta: META_EXPR_STRING, + description: 'Converts a string to lowercase and returns the result.', + snippet: '{ $toLower: "${1:\\$string}" }', + link: getDocLink('$toLower', META_EXPR_STRING), + }, + { + value: '$toString', + meta: META_EXPR_STRING, + description: 'The $toString operator converts an expression into a String', + snippet: '{ $toString: "${1:\\$string}" }', + link: getDocLink('$toString', META_EXPR_STRING), + }, + { + value: '$trim', + meta: META_EXPR_STRING, + description: 'Removes whitespace or specified characters from both ends of a string.', + snippet: '{ $trim: { input: "${1:\\$string}" } }', + link: getDocLink('$trim', META_EXPR_STRING), + }, + { + value: '$toUpper', + meta: META_EXPR_STRING, + description: 'Converts a string to uppercase and returns the result.', + snippet: '{ $toUpper: "${1:\\$string}" }', + link: getDocLink('$toUpper', META_EXPR_STRING), + }, +]; + +// --------------------------------------------------------------------------- +// Timestamp Expression Operators +// --------------------------------------------------------------------------- + +const timestampExpressionOperators: readonly OperatorEntry[] = [ + { + value: '$tsIncrement', + meta: META_EXPR_TIMESTAMP, + description: 'The $tsIncrement operator extracts the increment portion from a timestamp value.', + snippet: '{ $tsIncrement: "${1:\\$timestampField}" }', + link: getDocLink('$tsIncrement', META_EXPR_TIMESTAMP), + }, + { + value: '$tsSecond', + meta: META_EXPR_TIMESTAMP, + description: 'The $tsSecond operator extracts the seconds portion from a timestamp value.', + snippet: '{ $tsSecond: "${1:\\$timestampField}" }', + link: getDocLink('$tsSecond', META_EXPR_TIMESTAMP), + }, +]; + +// --------------------------------------------------------------------------- +// Trigonometry Expression Operators +// --------------------------------------------------------------------------- + +const trigonometryExpressionOperators: readonly OperatorEntry[] = [ + { + value: '$sin', + meta: META_EXPR_TRIG, + description: 'Returns the sine of a value measured in radians.', + snippet: '{ $sin: "${1:\\$value}" }', + link: getDocLink('$sin', META_EXPR_TRIG), + }, + { + value: '$cos', + meta: META_EXPR_TRIG, + description: 'Returns the cosine of a value measured in radians.', + snippet: '{ $cos: "${1:\\$value}" }', + link: getDocLink('$cos', META_EXPR_TRIG), + }, + { + value: '$tan', + meta: META_EXPR_TRIG, + description: 'Returns the tangent of a value measured in radians.', + snippet: '{ $tan: "${1:\\$value}" }', + link: getDocLink('$tan', META_EXPR_TRIG), + }, + { + value: '$asin', + meta: META_EXPR_TRIG, + description: 'Returns the arcsine (inverse sine) of a value in radians.', + snippet: '{ $asin: "${1:\\$value}" }', + link: getDocLink('$asin', META_EXPR_TRIG), + }, + { + value: '$acos', + meta: META_EXPR_TRIG, + description: 'Returns the arccosine (inverse cosine) of a value in radians.', + snippet: '{ $acos: "${1:\\$value}" }', + link: getDocLink('$acos', META_EXPR_TRIG), + }, + { + value: '$atan', + meta: META_EXPR_TRIG, + description: 'Returns the arctangent (inverse tangent) of a value in radians.', + snippet: '{ $atan: "${1:\\$value}" }', + link: getDocLink('$atan', META_EXPR_TRIG), + }, + { + value: '$atan2', + meta: META_EXPR_TRIG, + description: 'Returns the arctangent of the quotient of two values, using the signs to determine the quadrant.', + snippet: '{ $atan2: "${1:\\$value}" }', + link: getDocLink('$atan2', META_EXPR_TRIG), + }, + { + value: '$asinh', + meta: META_EXPR_TRIG, + description: 'Returns the inverse hyperbolic sine of a value.', + snippet: '{ $asinh: "${1:\\$value}" }', + link: getDocLink('$asinh', META_EXPR_TRIG), + }, + { + value: '$acosh', + meta: META_EXPR_TRIG, + description: 'Returns the inverse hyperbolic cosine of a value.', + snippet: '{ $acosh: "${1:\\$value}" }', + link: getDocLink('$acosh', META_EXPR_TRIG), + }, + { + value: '$atanh', + meta: META_EXPR_TRIG, + description: 'Returns the inverse hyperbolic tangent of a value.', + snippet: '{ $atanh: "${1:\\$value}" }', + link: getDocLink('$atanh', META_EXPR_TRIG), + }, + { + value: '$sinh', + meta: META_EXPR_TRIG, + description: 'Returns the hyperbolic sine of a value.', + snippet: '{ $sinh: "${1:\\$value}" }', + link: getDocLink('$sinh', META_EXPR_TRIG), + }, + { + value: '$cosh', + meta: META_EXPR_TRIG, + description: 'Returns the hyperbolic cosine of a value.', + snippet: '{ $cosh: "${1:\\$value}" }', + link: getDocLink('$cosh', META_EXPR_TRIG), + }, + { + value: '$tanh', + meta: META_EXPR_TRIG, + description: 'Returns the hyperbolic tangent of a value.', + snippet: '{ $tanh: "${1:\\$value}" }', + link: getDocLink('$tanh', META_EXPR_TRIG), + }, + { + value: '$degreesToRadians', + meta: META_EXPR_TRIG, + description: 'Converts a value from degrees to radians.', + snippet: '{ $degreesToRadians: "${1:\\$angle}" }', + link: getDocLink('$degreesToRadians', META_EXPR_TRIG), + }, + { + value: '$radiansToDegrees', + meta: META_EXPR_TRIG, + description: 'Converts a value from radians to degrees.', + snippet: '{ $radiansToDegrees: "${1:\\$angle}" }', + link: getDocLink('$radiansToDegrees', META_EXPR_TRIG), + }, +]; + +// --------------------------------------------------------------------------- +// Type Expression Operators +// --------------------------------------------------------------------------- + +const typeExpressionOperators: readonly OperatorEntry[] = [ + { + value: '$convert', + meta: META_EXPR_TYPE, + description: 'The $convert operator converts an expression into the specified type', + snippet: '{ $convert: { input: "${1:\\$field}", to: "${2:type}" } }', + link: getDocLink('$convert', META_EXPR_TYPE), + }, + { + value: '$isNumber', + meta: META_EXPR_TYPE, + description: 'The $isNumber operator checks if a specified expression is a numerical type', + snippet: '{ $isNumber: "${1:\\$field}" }', + link: getDocLink('$isNumber', META_EXPR_TYPE), + }, + { + value: '$toBool', + meta: META_EXPR_TYPE, + description: 'The $toBool operator converts an expression into a Boolean type', + snippet: '{ $toBool: "${1:\\$field}" }', + link: getDocLink('$toBool', META_EXPR_TYPE), + }, + { + value: '$toDate', + meta: META_EXPR_TYPE, + description: 'The $toDate operator converts supported types to a proper Date object.', + snippet: '{ $toDate: "${1:\\$field}" }', + link: getDocLink('$toDate', META_EXPR_TYPE), + }, + { + value: '$toDecimal', + meta: META_EXPR_TYPE, + description: 'The $toDecimal operator converts an expression into a Decimal type', + snippet: '{ $toDecimal: "${1:\\$field}" }', + link: getDocLink('$toDecimal', META_EXPR_TYPE), + }, + { + value: '$toDouble', + meta: META_EXPR_TYPE, + description: 'The $toDouble operator converts an expression into a Double value', + snippet: '{ $toDouble: "${1:\\$field}" }', + link: getDocLink('$toDouble', META_EXPR_TYPE), + }, + { + value: '$toInt', + meta: META_EXPR_TYPE, + description: 'The $toInt operator converts an expression into an Integer', + snippet: '{ $toInt: "${1:\\$field}" }', + link: getDocLink('$toInt', META_EXPR_TYPE), + }, + { + value: '$toLong', + meta: META_EXPR_TYPE, + description: 'The $toLong operator converts an expression into a Long value', + snippet: '{ $toLong: "${1:\\$field}" }', + link: getDocLink('$toLong', META_EXPR_TYPE), + }, + { + value: '$toObjectId', + meta: META_EXPR_TYPE, + description: 'The $toObjectId operator converts an expression into an ObjectId', + snippet: '{ $toObjectId: "${1:\\$field}" }', + link: getDocLink('$toObjectId', META_EXPR_TYPE), + }, + { + value: '$toString', + meta: META_EXPR_TYPE, + description: 'The $toString operator converts an expression into a String', + snippet: '{ $toString: "${1:\\$field}" }', + link: getDocLink('$toString', META_EXPR_TYPE), + }, + { + value: '$type', + meta: META_EXPR_TYPE, + description: 'The $type operator retrieves documents if the chosen field is of the specified type.', + snippet: '{ $type: "${1:\\$field}" }', + link: getDocLink('$type', META_EXPR_TYPE), + }, +]; + +// --------------------------------------------------------------------------- +// Variable Expression Operators +// --------------------------------------------------------------------------- + +const variableExpressionOperators: readonly OperatorEntry[] = [ + { + value: '$let', + meta: META_EXPR_VARIABLE, + description: + 'The $let operator allows defining variables for use in a specified expression, enabling complex calculations and reducing code repetition.', + snippet: '{ $let: { vars: { ${1:var}: ${2:expression} }, in: ${3:expression} } }', + link: getDocLink('$let', META_EXPR_VARIABLE), + }, +]; + +// --------------------------------------------------------------------------- +// Conditional Expression Operators +// --------------------------------------------------------------------------- + +const conditionalExpressionOperators: readonly OperatorEntry[] = [ + { + value: '$cond', + meta: META_EXPR_CONDITIONAL, + description: + 'The $cond operator is used to evaluate a condition and return one of two expressions based on the result.', + snippet: '{ $cond: { if: { ${1:expression} }, then: ${2:trueValue}, else: ${3:falseValue} } }', + link: getDocLink('$cond', META_EXPR_CONDITIONAL), + }, + { + value: '$ifNull', + meta: META_EXPR_CONDITIONAL, + description: + 'The $ifNull operator is used to evaluate an expression and return a specified value if the expression resolves to null.', + snippet: '{ $ifNull: ["${1:\\$field}", ${2:replacement}] }', + link: getDocLink('$ifNull', META_EXPR_CONDITIONAL), + }, + { + value: '$switch', + meta: META_EXPR_CONDITIONAL, + description: + 'The $switch operator is used to evaluate a series of conditions and return a value based on the first condition that evaluates to true.', + snippet: + '{ $switch: { branches: [{ case: { ${1:expression} }, then: ${2:value} }], default: ${3:defaultValue} } }', + link: getDocLink('$switch', META_EXPR_CONDITIONAL), + }, +]; + +// --------------------------------------------------------------------------- +// Registration +// --------------------------------------------------------------------------- + +registerOperators([ + ...arithmeticExpressionOperators, + ...arrayExpressionOperators, + ...bitwiseOperators, + ...booleanExpressionOperators, + ...comparisonExpressionOperators, + ...dataSizeOperators, + ...dateExpressionOperators, + ...literalExpressionOperator, + ...miscellaneousOperators, + ...objectExpressionOperators, + ...setExpressionOperators, + ...stringExpressionOperators, + ...timestampExpressionOperators, + ...trigonometryExpressionOperators, + ...typeExpressionOperators, + ...variableExpressionOperators, + ...conditionalExpressionOperators, +]); diff --git a/packages/documentdb-constants/src/index.ts b/packages/documentdb-constants/src/index.ts index 7b5debffb..ba442cc13 100644 --- a/packages/documentdb-constants/src/index.ts +++ b/packages/documentdb-constants/src/index.ts @@ -69,3 +69,13 @@ export { getAllCompletions, getFilteredCompletions, registerOperators } from './ // -- Documentation URL helpers -- export { getDocBase, getDocLink } from './docLinks'; + +// -- Operator data modules (self-register on import) -- +import './accumulators'; +import './bsonConstructors'; +import './expressionOperators'; +import './queryOperators'; +import './stages'; +import './systemVariables'; +import './updateOperators'; +import './windowOperators'; diff --git a/packages/documentdb-constants/src/queryOperators.ts b/packages/documentdb-constants/src/queryOperators.ts new file mode 100644 index 000000000..5c18a5973 --- /dev/null +++ b/packages/documentdb-constants/src/queryOperators.ts @@ -0,0 +1,446 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// AUTO-GENERATED — DO NOT EDIT BY HAND +// +// Generated by: npm run generate (scripts/generate-from-reference.ts) +// Sources: resources/operator-reference-scraped.md +// resources/operator-reference-overrides.md +// +// To change operator data, edit the overrides file and re-run the generator. + +import { getDocLink } from './docLinks'; +import { registerOperators } from './getFilteredCompletions'; +import { + META_QUERY_ARRAY, + META_QUERY_BITWISE, + META_QUERY_COMPARISON, + META_QUERY_ELEMENT, + META_QUERY_EVALUATION, + META_QUERY_GEOSPATIAL, + META_QUERY_LOGICAL, + META_QUERY_MISC, + META_QUERY_PROJECTION, +} from './metaTags'; +import { type OperatorEntry } from './types'; + +// --------------------------------------------------------------------------- +// Comparison Query Operators +// --------------------------------------------------------------------------- + +const comparisonQueryOperators: readonly OperatorEntry[] = [ + { + value: '$eq', + meta: META_QUERY_COMPARISON, + description: 'The $eq query operator compares the value of a field to a specified value', + snippet: '{ $eq: ${1:value} }', + link: getDocLink('$eq', META_QUERY_COMPARISON), + }, + { + value: '$gt', + meta: META_QUERY_COMPARISON, + description: + 'The $gt query operator retrieves documents where the value of a field is greater than a specified value', + snippet: '{ $gt: ${1:value} }', + link: getDocLink('$gt', META_QUERY_COMPARISON), + }, + { + value: '$gte', + meta: META_QUERY_COMPARISON, + description: + 'The $gte operator retrieves documents where the value of a field is greater than or equal to a specified value', + snippet: '{ $gte: ${1:value} }', + link: getDocLink('$gte', META_QUERY_COMPARISON), + }, + { + value: '$in', + meta: META_QUERY_COMPARISON, + description: 'The $in operator matches value of a field against an array of specified values', + snippet: '{ $in: [${1:value}] }', + link: getDocLink('$in', META_QUERY_COMPARISON), + }, + { + value: '$lt', + meta: META_QUERY_COMPARISON, + description: 'The $lt operator retrieves documents where the value of field is less than a specified value', + snippet: '{ $lt: ${1:value} }', + link: getDocLink('$lt', META_QUERY_COMPARISON), + }, + { + value: '$lte', + meta: META_QUERY_COMPARISON, + description: + 'The $lte operator retrieves documents where the value of a field is less than or equal to a specified value', + snippet: '{ $lte: ${1:value} }', + link: getDocLink('$lte', META_QUERY_COMPARISON), + }, + { + value: '$ne', + meta: META_QUERY_COMPARISON, + description: "The $ne operator retrieves documents where the value of a field doesn't equal a specified value", + snippet: '{ $ne: ${1:value} }', + link: getDocLink('$ne', META_QUERY_COMPARISON), + }, + { + value: '$nin', + meta: META_QUERY_COMPARISON, + description: "The $nin operator retrieves documents where the value of a field doesn't match a list of values", + snippet: '{ $nin: [${1:value}] }', + link: getDocLink('$nin', META_QUERY_COMPARISON), + }, +]; + +// --------------------------------------------------------------------------- +// Logical Query Operators +// --------------------------------------------------------------------------- + +const logicalQueryOperators: readonly OperatorEntry[] = [ + { + value: '$and', + meta: META_QUERY_LOGICAL, + description: + 'The $and operator joins multiple query clauses and returns documents that match all specified conditions.', + snippet: '{ $and: [{ ${1:expression} }] }', + link: getDocLink('$and', META_QUERY_LOGICAL), + }, + { + value: '$not', + meta: META_QUERY_LOGICAL, + description: + "The $not operator performs a logical NOT operation on a specified expression, selecting documents that don't match the expression.", + snippet: '{ $not: { ${1:expression} } }', + link: getDocLink('$not', META_QUERY_LOGICAL), + }, + { + value: '$nor', + meta: META_QUERY_LOGICAL, + description: + 'The $nor operator performs a logical NOR on an array of expressions and retrieves documents that fail all the conditions.', + snippet: '{ $nor: [{ ${1:expression} }] }', + link: getDocLink('$nor', META_QUERY_LOGICAL), + }, + { + value: '$or', + meta: META_QUERY_LOGICAL, + description: + 'The $or operator joins query clauses with a logical OR and returns documents that match at least one of the specified conditions.', + snippet: '{ $or: [{ ${1:expression} }] }', + link: getDocLink('$or', META_QUERY_LOGICAL), + }, +]; + +// --------------------------------------------------------------------------- +// Element Query Operators +// --------------------------------------------------------------------------- + +const elementQueryOperators: readonly OperatorEntry[] = [ + { + value: '$exists', + meta: META_QUERY_ELEMENT, + description: + 'The $exists operator retrieves documents that contain the specified field in their document structure.', + snippet: '{ $exists: ${1:true} }', + link: getDocLink('$exists', META_QUERY_ELEMENT), + }, + { + value: '$type', + meta: META_QUERY_ELEMENT, + description: 'The $type operator retrieves documents if the chosen field is of the specified type.', + snippet: '{ $type: "${1:type}" }', + link: getDocLink('$type', META_QUERY_ELEMENT), + }, +]; + +// --------------------------------------------------------------------------- +// Evaluation Query Operators +// --------------------------------------------------------------------------- + +const evaluationQueryOperators: readonly OperatorEntry[] = [ + { + value: '$expr', + meta: META_QUERY_EVALUATION, + description: + 'The $expr operator allows the use of aggregation expressions within the query language, enabling complex field comparisons and calculations.', + snippet: '{ $expr: { ${1:expression} } }', + link: getDocLink('$expr', META_QUERY_EVALUATION), + }, + { + value: '$jsonSchema', + meta: META_QUERY_EVALUATION, + description: + 'The $jsonSchema operator validates documents against a JSON Schema definition for data validation and structure enforcement. Discover supported features and limitations.', + snippet: '{ $jsonSchema: { bsonType: "${1:object}" } }', + link: getDocLink('$jsonSchema', META_QUERY_EVALUATION), + }, + { + value: '$mod', + meta: META_QUERY_EVALUATION, + description: + 'The $mod operator performs a modulo operation on the value of a field and selects documents with a specified result.', + snippet: '{ $mod: [${1:divisor}, ${2:remainder}] }', + link: getDocLink('$mod', META_QUERY_EVALUATION), + }, + { + value: '$regex', + meta: META_QUERY_EVALUATION, + description: + 'The $regex operator provides regular expression capabilities for pattern matching in queries, allowing flexible string matching and searching.', + snippet: '{ $regex: /${1:pattern}/ }', + link: getDocLink('$regex', META_QUERY_EVALUATION), + applicableBsonTypes: ['string'], + }, + { + value: '$text', + meta: META_QUERY_EVALUATION, + description: + 'The $text operator performs text search on the content of indexed string fields, enabling full-text search capabilities.', + snippet: '{ $text: { \\$search: "${1:text}" } }', + link: getDocLink('$text', META_QUERY_EVALUATION), + applicableBsonTypes: ['string'], + }, +]; + +// --------------------------------------------------------------------------- +// Geospatial Operators +// --------------------------------------------------------------------------- + +const geospatialOperators: readonly OperatorEntry[] = [ + { + value: '$geoIntersects', + meta: META_QUERY_GEOSPATIAL, + description: + 'The $geoIntersects operator selects documents whose location field intersects with a specified GeoJSON object.', + snippet: '{ $geoIntersects: { \\$geometry: { type: "${1:GeoJSON type}", coordinates: ${2:coordinates} } } }', + link: getDocLink('$geoIntersects', META_QUERY_GEOSPATIAL), + }, + { + value: '$geoWithin', + meta: META_QUERY_GEOSPATIAL, + description: + 'The $geoWithin operator selects documents whose location field is completely within a specified geometry.', + snippet: '{ $geoWithin: { \\$geometry: { type: "${1:GeoJSON type}", coordinates: ${2:coordinates} } } }', + link: getDocLink('$geoWithin', META_QUERY_GEOSPATIAL), + }, + { + value: '$box', + meta: META_QUERY_GEOSPATIAL, + description: 'The $box operator defines a rectangular area for geospatial queries using coordinate pairs.', + snippet: '[[${1:bottomLeftX}, ${2:bottomLeftY}], [${3:upperRightX}, ${4:upperRightY}]]', + link: getDocLink('$box', META_QUERY_GEOSPATIAL), + }, + { + value: '$center', + meta: META_QUERY_GEOSPATIAL, + description: 'The $center operator specifies a circle using legacy coordinate pairs for $geoWithin queries.', + snippet: '[[${1:x}, ${2:y}], ${3:radius}]', + link: getDocLink('$center', META_QUERY_GEOSPATIAL), + }, + { + value: '$centerSphere', + meta: META_QUERY_GEOSPATIAL, + description: 'The $centerSphere operator specifies a circle using spherical geometry for $geoWithin queries.', + snippet: '[[${1:x}, ${2:y}], ${3:radiusInRadians}]', + link: getDocLink('$centerSphere', META_QUERY_GEOSPATIAL), + }, + { + value: '$geometry', + meta: META_QUERY_GEOSPATIAL, + description: 'The $geometry operator specifies a GeoJSON geometry for geospatial queries.', + snippet: '{ type: "${1:Point}", coordinates: [${2:coordinates}] }', + link: getDocLink('$geometry', META_QUERY_GEOSPATIAL), + }, + { + value: '$maxDistance', + meta: META_QUERY_GEOSPATIAL, + description: + 'The $maxDistance operator specifies the maximum distance that can exist between two points in a geospatial query.', + snippet: '${1:distance}', + link: getDocLink('$maxDistance', META_QUERY_GEOSPATIAL), + }, + { + value: '$minDistance', + meta: META_QUERY_GEOSPATIAL, + description: + 'The $minDistance operator specifies the minimum distance that must exist between two points in a geospatial query.', + snippet: '${1:distance}', + link: getDocLink('$minDistance', META_QUERY_GEOSPATIAL), + }, + { + value: '$polygon', + meta: META_QUERY_GEOSPATIAL, + description: + 'The $polygon operator defines a polygon for geospatial queries, allowing you to find locations within an irregular shape.', + snippet: '[[${1:x1}, ${2:y1}], [${3:x2}, ${4:y2}], [${5:x3}, ${6:y3}]]', + link: getDocLink('$polygon', META_QUERY_GEOSPATIAL), + }, + { + value: '$near', + meta: META_QUERY_GEOSPATIAL, + description: + 'The $near operator returns documents with location fields that are near a specified point, sorted by distance.', + snippet: + '{ $near: { \\$geometry: { type: "Point", coordinates: [${1:lng}, ${2:lat}] }, \\$maxDistance: ${3:distance} } }', + link: getDocLink('$near', META_QUERY_GEOSPATIAL), + }, + { + value: '$nearSphere', + meta: META_QUERY_GEOSPATIAL, + description: + 'The $nearSphere operator returns documents whose location fields are near a specified point on a sphere, sorted by distance on a spherical surface.', + snippet: + '{ $nearSphere: { \\$geometry: { type: "Point", coordinates: [${1:lng}, ${2:lat}] }, \\$maxDistance: ${3:distance} } }', + link: getDocLink('$nearSphere', META_QUERY_GEOSPATIAL), + }, +]; + +// --------------------------------------------------------------------------- +// Array Query Operators +// --------------------------------------------------------------------------- + +const arrayQueryOperators: readonly OperatorEntry[] = [ + { + value: '$all', + meta: META_QUERY_ARRAY, + description: 'The $all operator helps finding array documents matching all the elements.', + snippet: '{ $all: [${1:value}] }', + link: getDocLink('$all', META_QUERY_ARRAY), + applicableBsonTypes: ['array'], + }, + { + value: '$elemMatch', + meta: META_QUERY_ARRAY, + description: + 'The $elemmatch operator returns complete array, qualifying criteria with at least one matching array element.', + snippet: '{ $elemMatch: { ${1:query} } }', + link: getDocLink('$elemMatch', META_QUERY_ARRAY), + applicableBsonTypes: ['array'], + }, + { + value: '$size', + meta: META_QUERY_ARRAY, + description: + 'The $size operator is used to query documents where an array field has a specified number of elements.', + snippet: '{ $size: ${1:number} }', + link: getDocLink('$size', META_QUERY_ARRAY), + applicableBsonTypes: ['array'], + }, +]; + +// --------------------------------------------------------------------------- +// Bitwise Query Operators +// --------------------------------------------------------------------------- + +const bitwiseQueryOperators: readonly OperatorEntry[] = [ + { + value: '$bitsAllClear', + meta: META_QUERY_BITWISE, + description: + 'The $bitsAllClear operator is used to match documents where all the bit positions specified in a bitmask are clear.', + snippet: '{ $bitsAllClear: ${1:bitmask} }', + link: getDocLink('$bitsAllClear', META_QUERY_BITWISE), + applicableBsonTypes: ['int', 'long'], + }, + { + value: '$bitsAllSet', + meta: META_QUERY_BITWISE, + description: 'The bitsAllSet command is used to match documents where all the specified bit positions are set.', + snippet: '{ $bitsAllSet: ${1:bitmask} }', + link: getDocLink('$bitsAllSet', META_QUERY_BITWISE), + applicableBsonTypes: ['int', 'long'], + }, + { + value: '$bitsAnyClear', + meta: META_QUERY_BITWISE, + description: + 'The $bitsAnyClear operator matches documents where any of the specified bit positions in a bitmask are clear.', + snippet: '{ $bitsAnyClear: ${1:bitmask} }', + link: getDocLink('$bitsAnyClear', META_QUERY_BITWISE), + applicableBsonTypes: ['int', 'long'], + }, + { + value: '$bitsAnySet', + meta: META_QUERY_BITWISE, + description: + 'The $bitsAnySet operator returns documents where any of the specified bit positions are set to 1.', + snippet: '{ $bitsAnySet: ${1:bitmask} }', + link: getDocLink('$bitsAnySet', META_QUERY_BITWISE), + applicableBsonTypes: ['int', 'long'], + }, +]; + +// --------------------------------------------------------------------------- +// Projection Operators +// --------------------------------------------------------------------------- + +const projectionOperators: readonly OperatorEntry[] = [ + { + value: '$', + meta: META_QUERY_PROJECTION, + description: + 'The $ positional operator identifies an element in an array to update without explicitly specifying the position of the element in the array.', + link: getDocLink('$', META_QUERY_PROJECTION), + }, + { + value: '$elemMatch', + meta: META_QUERY_PROJECTION, + description: + 'The $elemmatch operator returns complete array, qualifying criteria with at least one matching array element.', + snippet: '{ $elemMatch: { ${1:query} } }', + link: getDocLink('$elemMatch', META_QUERY_PROJECTION), + }, + { + value: '$slice', + meta: META_QUERY_PROJECTION, + description: 'The $slice operator returns a subset of an array from any element onwards in the array.', + snippet: '{ $slice: ${1:number} }', + link: getDocLink('$slice', META_QUERY_PROJECTION), + }, +]; + +// --------------------------------------------------------------------------- +// Miscellaneous Query Operators +// --------------------------------------------------------------------------- + +const miscellaneousQueryOperators: readonly OperatorEntry[] = [ + { + value: '$comment', + meta: META_QUERY_MISC, + description: + 'The $comment operator adds a comment to a query to help identify the query in logs and profiler output.', + snippet: '{ $comment: "${1:comment}" }', + link: getDocLink('$comment', META_QUERY_MISC), + }, + { + value: '$rand', + meta: META_QUERY_MISC, + description: 'The $rand operator generates a random float value between 0 and 1.', + snippet: '{ $rand: {} }', + link: getDocLink('$rand', META_QUERY_MISC), + }, + { + value: '$natural', + meta: META_QUERY_MISC, + description: + 'The $natural operator forces the query to use the natural order of documents in a collection, providing control over document ordering and retrieval.', + snippet: '{ $natural: ${1:1} }', + link: getDocLink('$natural', META_QUERY_MISC), + }, +]; + +// --------------------------------------------------------------------------- +// Registration +// --------------------------------------------------------------------------- + +registerOperators([ + ...comparisonQueryOperators, + ...logicalQueryOperators, + ...elementQueryOperators, + ...evaluationQueryOperators, + ...geospatialOperators, + ...arrayQueryOperators, + ...bitwiseQueryOperators, + ...projectionOperators, + ...miscellaneousQueryOperators, +]); diff --git a/packages/documentdb-constants/src/stages.ts b/packages/documentdb-constants/src/stages.ts new file mode 100644 index 000000000..cbe1d9fd0 --- /dev/null +++ b/packages/documentdb-constants/src/stages.ts @@ -0,0 +1,298 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// AUTO-GENERATED — DO NOT EDIT BY HAND +// +// Generated by: npm run generate (scripts/generate-from-reference.ts) +// Sources: resources/operator-reference-scraped.md +// resources/operator-reference-overrides.md +// +// To change operator data, edit the overrides file and re-run the generator. + +import { getDocLink } from './docLinks'; +import { registerOperators } from './getFilteredCompletions'; +import { META_STAGE } from './metaTags'; +import { type OperatorEntry } from './types'; + +// --------------------------------------------------------------------------- +// Aggregation Pipeline Stages +// --------------------------------------------------------------------------- + +const aggregationPipelineStages: readonly OperatorEntry[] = [ + { + value: '$addFields', + meta: META_STAGE, + description: 'The $addFields stage in the aggregation pipeline is used to add new fields to documents.', + snippet: '{ $addFields: { ${1:newField}: ${2:expression} } }', + link: getDocLink('$addFields', META_STAGE), + }, + { + value: '$bucket', + meta: META_STAGE, + description: 'Groups input documents into buckets based on specified boundaries.', + snippet: '{ $bucket: { groupBy: "${1:\\$field}", boundaries: [${2:values}], default: "${3:Other}" } }', + link: getDocLink('$bucket', META_STAGE), + }, + { + value: '$bucketAuto', + meta: META_STAGE, + description: + 'Categorizes documents into a specified number of groups based on a given expression, automatically determining bucket boundaries.', + snippet: '{ $bucketAuto: { groupBy: "${1:\\$field}", buckets: ${2:number} } }', + link: getDocLink('$bucketAuto', META_STAGE), + }, + { + value: '$changeStream', + meta: META_STAGE, + description: 'The $changeStream stage opens a change stream cursor to track data changes in real-time.', + snippet: '{ $changeStream: {} }', + link: getDocLink('$changeStream', META_STAGE), + }, + { + value: '$collStats', + meta: META_STAGE, + description: + 'The $collStats stage in the aggregation pipeline is used to return statistics about a collection.', + snippet: '{ $collStats: { storageStats: {} } }', + link: getDocLink('$collStats', META_STAGE), + }, + { + value: '$count', + meta: META_STAGE, + description: + 'The `$count` operator is used to count the number of documents that match a query filtering criteria.', + snippet: '{ $count: "${1:countField}" }', + link: getDocLink('$count', META_STAGE), + }, + { + value: '$densify', + meta: META_STAGE, + description: 'Adds missing data points in a sequence of values within an array or collection.', + snippet: '{ $densify: { field: "${1:field}", range: { step: ${2:1}, bounds: "full" } } }', + link: getDocLink('$densify', META_STAGE), + }, + { + value: '$documents', + meta: META_STAGE, + description: 'The $documents stage creates a pipeline from a set of provided documents.', + snippet: '{ $documents: [${1:documents}] }', + link: getDocLink('$documents', META_STAGE), + }, + { + value: '$facet', + meta: META_STAGE, + description: + 'The $facet allows for multiple parallel aggregations to be executed within a single pipeline stage.', + snippet: '{ $facet: { ${1:outputField}: [{ ${2:stage} }] } }', + link: getDocLink('$facet', META_STAGE), + }, + { + value: '$fill', + meta: META_STAGE, + description: + 'The $fill stage allows filling missing values in documents based on specified methods and criteria.', + snippet: '{ $fill: { output: { ${1:field}: { method: "${2:linear}" } } } }', + link: getDocLink('$fill', META_STAGE), + }, + { + value: '$geoNear', + meta: META_STAGE, + description: + 'The $geoNear operator finds and sorts documents by their proximity to a geospatial point, returning distance information for each document.', + snippet: + '{ $geoNear: { near: { type: "Point", coordinates: [${1:lng}, ${2:lat}] }, distanceField: "${3:distance}" } }', + link: getDocLink('$geoNear', META_STAGE), + }, + { + value: '$graphLookup', + meta: META_STAGE, + description: + 'Performs a recursive search on a collection to return documents connected by a specified field relationship.', + snippet: + '{ $graphLookup: { from: "${1:collection}", startWith: "${2:\\$field}", connectFromField: "${3:field}", connectToField: "${4:field}", as: "${5:result}" } }', + link: getDocLink('$graphLookup', META_STAGE), + }, + { + value: '$group', + meta: META_STAGE, + description: + 'The $group stage groups documents by specified identifier expressions and applies accumulator expressions.', + snippet: '{ $group: { _id: "${1:\\$field}", ${2:accumulator}: { ${3:\\$sum}: 1 } } }', + link: getDocLink('$group', META_STAGE), + }, + { + value: '$indexStats', + meta: META_STAGE, + description: 'The $indexStats stage returns usage statistics for each index in the collection.', + snippet: '{ $indexStats: {} }', + link: getDocLink('$indexStats', META_STAGE), + }, + { + value: '$limit', + meta: META_STAGE, + description: 'Restricts the number of documents passed to the next stage in the pipeline.', + snippet: '{ $limit: ${1:number} }', + link: getDocLink('$limit', META_STAGE), + }, + { + value: '$lookup', + meta: META_STAGE, + description: + 'The $lookup stage in the Aggregation Framework is used to perform left outer joins with other collections.', + snippet: + '{ $lookup: { from: "${1:collection}", localField: "${2:field}", foreignField: "${3:field}", as: "${4:result}" } }', + link: getDocLink('$lookup', META_STAGE), + }, + { + value: '$match', + meta: META_STAGE, + description: + 'The $match stage in the aggregation pipeline is used to filter documents that match a specified condition.', + snippet: '{ $match: { ${1:query} } }', + link: getDocLink('$match', META_STAGE), + }, + { + value: '$merge', + meta: META_STAGE, + description: + 'The $merge stage in an aggregation pipeline writes the results of the aggregation to a specified collection.', + snippet: '{ $merge: { into: "${1:collection}" } }', + link: getDocLink('$merge', META_STAGE), + }, + { + value: '$out', + meta: META_STAGE, + description: + 'The `$out` stage in an aggregation pipeline writes the resulting documents to a specified collection.', + snippet: '{ $out: "${1:collection}" }', + link: getDocLink('$out', META_STAGE), + }, + { + value: '$project', + meta: META_STAGE, + description: 'Reshapes documents by including, excluding, or computing new fields.', + snippet: '{ $project: { ${1:field}: 1 } }', + link: getDocLink('$project', META_STAGE), + }, + { + value: '$redact', + meta: META_STAGE, + description: 'Filters the content of the documents based on access rights.', + snippet: + '{ $redact: { \\$cond: { if: { ${1:expression} }, then: "${2:\\$\\$DESCEND}", else: "${3:\\$\\$PRUNE}" } } }', + link: getDocLink('$redact', META_STAGE), + }, + { + value: '$replaceRoot', + meta: META_STAGE, + description: 'Replaces the input document with a specified embedded document, promoting it to the top level.', + snippet: '{ $replaceRoot: { newRoot: "${1:\\$field}" } }', + link: getDocLink('$replaceRoot', META_STAGE), + }, + { + value: '$replaceWith', + meta: META_STAGE, + description: + 'The $replaceWith operator in Azure DocumentDB returns a document after replacing a document with the specified document', + snippet: '{ $replaceWith: "${1:\\$field}" }', + link: getDocLink('$replaceWith', META_STAGE), + }, + { + value: '$sample', + meta: META_STAGE, + description: 'The $sample operator in Azure DocumentDB returns a randomly selected number of documents', + snippet: '{ $sample: { size: ${1:number} } }', + link: getDocLink('$sample', META_STAGE), + }, + { + value: '$search', + meta: META_STAGE, + description: 'Performs full-text search on string fields using Atlas Search or compatible search indexes.', + snippet: '{ $search: { ${1} } }', + link: getDocLink('$search', META_STAGE), + }, + { + value: '$searchMeta', + meta: META_STAGE, + description: 'Returns metadata about an Atlas Search query without returning the matching documents.', + snippet: '{ $searchMeta: { ${1} } }', + link: getDocLink('$searchMeta', META_STAGE), + }, + { + value: '$set', + meta: META_STAGE, + description: 'The $set operator in Azure DocumentDB updates or creates a new field with a specified value', + snippet: '{ $set: { ${1:field}: ${2:expression} } }', + link: getDocLink('$set', META_STAGE), + }, + { + value: '$setWindowFields', + meta: META_STAGE, + description: + 'Adds computed fields to documents using window functions over a specified partition and sort order.', + snippet: + '{ $setWindowFields: { partitionBy: "${1:\\$field}", sortBy: { ${2:field}: ${3:1} }, output: { ${4:newField}: { ${5:windowFunc} } } } }', + link: getDocLink('$setWindowFields', META_STAGE), + }, + { + value: '$skip', + meta: META_STAGE, + description: + 'The $skip stage in the aggregation pipeline is used to skip a specified number of documents from the input and pass the remaining documents to the next stage in the pipeline.', + snippet: '{ $skip: ${1:number} }', + link: getDocLink('$skip', META_STAGE), + }, + { + value: '$sort', + meta: META_STAGE, + description: + 'The $sort stage in the aggregation pipeline is used to order the documents in the pipeline by a specified field or fields.', + snippet: '{ $sort: { ${1:field}: ${2:1} } }', + link: getDocLink('$sort', META_STAGE), + }, + { + value: '$sortByCount', + meta: META_STAGE, + description: + 'The $sortByCount stage in the aggregation pipeline is used to group documents by a specified expression and then sort the count of documents in each group in descending order.', + snippet: '{ $sortByCount: "${1:\\$field}" }', + link: getDocLink('$sortByCount', META_STAGE), + }, + { + value: '$unionWith', + meta: META_STAGE, + description: 'Combines the results of two collections into a single result set, similar to SQL UNION ALL.', + snippet: '{ $unionWith: { coll: "${1:collection}", pipeline: [${2}] } }', + link: getDocLink('$unionWith', META_STAGE), + }, + { + value: '$unset', + meta: META_STAGE, + description: 'The $unset stage in the aggregation pipeline is used to remove specified fields from documents.', + snippet: '{ $unset: "${1:field}" }', + link: getDocLink('$unset', META_STAGE), + }, + { + value: '$unwind', + meta: META_STAGE, + description: + 'The $unwind stage in the aggregation framework is used to deconstruct an array field from the input documents to output a document for each element.', + snippet: '{ $unwind: "${1:\\$arrayField}" }', + link: getDocLink('$unwind', META_STAGE), + }, + { + value: '$currentOp', + meta: META_STAGE, + description: 'Returns information on active and queued operations for the database instance.', + snippet: '{ $currentOp: { allUsers: true } }', + link: getDocLink('$currentOp', META_STAGE), + }, +]; + +// --------------------------------------------------------------------------- +// Registration +// --------------------------------------------------------------------------- + +registerOperators([...aggregationPipelineStages]); diff --git a/packages/documentdb-constants/src/systemVariables.ts b/packages/documentdb-constants/src/systemVariables.ts new file mode 100644 index 000000000..e8c9d3546 --- /dev/null +++ b/packages/documentdb-constants/src/systemVariables.ts @@ -0,0 +1,79 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// AUTO-GENERATED — DO NOT EDIT BY HAND +// +// Generated by: npm run generate (scripts/generate-from-reference.ts) +// Sources: resources/operator-reference-scraped.md +// resources/operator-reference-overrides.md +// +// To change operator data, edit the overrides file and re-run the generator. + +import { getDocLink } from './docLinks'; +import { registerOperators } from './getFilteredCompletions'; +import { META_VARIABLE } from './metaTags'; +import { type OperatorEntry } from './types'; + +// --------------------------------------------------------------------------- +// Variables in Aggregation Expressions +// --------------------------------------------------------------------------- + +const systemVariables: readonly OperatorEntry[] = [ + { + value: '$$NOW', + meta: META_VARIABLE, + description: + 'Returns the current datetime as a Date object. Constant throughout a single aggregation pipeline.', + link: getDocLink('$$NOW', META_VARIABLE), + }, + { + value: '$$ROOT', + meta: META_VARIABLE, + description: + 'References the root document — the top-level document currently being processed in the pipeline stage.', + link: getDocLink('$$ROOT', META_VARIABLE), + }, + { + value: '$$REMOVE', + meta: META_VARIABLE, + description: + 'Removes a field from the output document. Used with $project or $addFields to conditionally exclude fields.', + link: getDocLink('$$REMOVE', META_VARIABLE), + }, + { + value: '$$CURRENT', + meta: META_VARIABLE, + description: + 'References the current document in the pipeline stage. Equivalent to $$ROOT at the start of the pipeline.', + link: getDocLink('$$CURRENT', META_VARIABLE), + }, + { + value: '$$DESCEND', + meta: META_VARIABLE, + description: + 'Used with $redact. Returns the document fields at the current level and continues descending into subdocuments.', + link: getDocLink('$$DESCEND', META_VARIABLE), + }, + { + value: '$$PRUNE', + meta: META_VARIABLE, + description: + 'Used with $redact. Excludes all fields at the current document level and stops descending into subdocuments.', + link: getDocLink('$$PRUNE', META_VARIABLE), + }, + { + value: '$$KEEP', + meta: META_VARIABLE, + description: + 'Used with $redact. Keeps all fields at the current document level without further descending into subdocuments.', + link: getDocLink('$$KEEP', META_VARIABLE), + }, +]; + +// --------------------------------------------------------------------------- +// Registration +// --------------------------------------------------------------------------- + +registerOperators([...systemVariables]); diff --git a/packages/documentdb-constants/src/updateOperators.ts b/packages/documentdb-constants/src/updateOperators.ts new file mode 100644 index 000000000..2f504de59 --- /dev/null +++ b/packages/documentdb-constants/src/updateOperators.ts @@ -0,0 +1,203 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// AUTO-GENERATED — DO NOT EDIT BY HAND +// +// Generated by: npm run generate (scripts/generate-from-reference.ts) +// Sources: resources/operator-reference-scraped.md +// resources/operator-reference-overrides.md +// +// To change operator data, edit the overrides file and re-run the generator. + +import { getDocLink } from './docLinks'; +import { registerOperators } from './getFilteredCompletions'; +import { META_UPDATE_ARRAY, META_UPDATE_BITWISE, META_UPDATE_FIELD } from './metaTags'; +import { type OperatorEntry } from './types'; + +// --------------------------------------------------------------------------- +// Field Update Operators +// --------------------------------------------------------------------------- + +const fieldUpdateOperators: readonly OperatorEntry[] = [ + { + value: '$currentDate', + meta: META_UPDATE_FIELD, + description: + 'The $currentDate operator sets the value of a field to the current date, either as a Date or a timestamp.', + snippet: '{ $currentDate: { "${1:field}": true } }', + link: getDocLink('$currentDate', META_UPDATE_FIELD), + }, + { + value: '$inc', + meta: META_UPDATE_FIELD, + description: 'The $inc operator increments the value of a field by a specified amount.', + snippet: '{ $inc: { "${1:field}": ${2:value} } }', + link: getDocLink('$inc', META_UPDATE_FIELD), + }, + { + value: '$min', + meta: META_UPDATE_FIELD, + description: 'Retrieves the minimum value for a specified field', + snippet: '{ $min: { "${1:field}": ${2:value} } }', + link: getDocLink('$min', META_UPDATE_FIELD), + }, + { + value: '$max', + meta: META_UPDATE_FIELD, + description: 'The $max operator returns the maximum value from a set of input values.', + snippet: '{ $max: { "${1:field}": ${2:value} } }', + link: getDocLink('$max', META_UPDATE_FIELD), + }, + { + value: '$mul', + meta: META_UPDATE_FIELD, + description: 'The $mul operator multiplies the value of a field by a specified number.', + snippet: '{ $mul: { "${1:field}": ${2:value} } }', + link: getDocLink('$mul', META_UPDATE_FIELD), + }, + { + value: '$rename', + meta: META_UPDATE_FIELD, + description: 'The $rename operator allows renaming fields in documents during update operations.', + snippet: '{ $rename: { "${1:oldField}": "${2:newField}" } }', + link: getDocLink('$rename', META_UPDATE_FIELD), + }, + { + value: '$set', + meta: META_UPDATE_FIELD, + description: 'The $set operator in Azure DocumentDB updates or creates a new field with a specified value', + snippet: '{ $set: { "${1:field}": ${2:value} } }', + link: getDocLink('$set', META_UPDATE_FIELD), + }, + { + value: '$setOnInsert', + meta: META_UPDATE_FIELD, + description: + 'The $setOnInsert operator sets field values only when an upsert operation results in an insert of a new document.', + snippet: '{ $setOnInsert: { "${1:field}": ${2:value} } }', + link: getDocLink('$setOnInsert', META_UPDATE_FIELD), + }, + { + value: '$unset', + meta: META_UPDATE_FIELD, + description: 'The $unset stage in the aggregation pipeline is used to remove specified fields from documents.', + snippet: '{ $unset: { "${1:field}": ${2:value} } }', + link: getDocLink('$unset', META_UPDATE_FIELD), + }, +]; + +// --------------------------------------------------------------------------- +// Array Update Operators +// --------------------------------------------------------------------------- + +const arrayUpdateOperators: readonly OperatorEntry[] = [ + { + value: '$', + meta: META_UPDATE_ARRAY, + description: + 'The $ positional operator identifies an element in an array to update without explicitly specifying the position of the element in the array.', + link: getDocLink('$', META_UPDATE_ARRAY), + }, + { + value: '$[]', + meta: META_UPDATE_ARRAY, + description: 'Positional all operator. Acts as a placeholder to update all elements in an array field.', + link: getDocLink('$[]', META_UPDATE_ARRAY), + }, + { + value: '$[identifier]', + meta: META_UPDATE_ARRAY, + description: + 'Filtered positional operator. Acts as a placeholder to update elements that match an arrayFilters condition.', + link: getDocLink('$[identifier]', META_UPDATE_ARRAY), + }, + { + value: '$addToSet', + meta: META_UPDATE_ARRAY, + description: + "The addToSet operator adds elements to an array if they don't already exist, while ensuring uniqueness of elements within the set.", + snippet: '{ $addToSet: { "${1:field}": ${2:value} } }', + link: getDocLink('$addToSet', META_UPDATE_ARRAY), + }, + { + value: '$pop', + meta: META_UPDATE_ARRAY, + description: 'Removes the first or last element of an array.', + snippet: '{ $pop: { "${1:field}": ${2:1} } }', + link: getDocLink('$pop', META_UPDATE_ARRAY), + }, + { + value: '$pull', + meta: META_UPDATE_ARRAY, + description: 'Removes all instances of a value from an array.', + snippet: '{ $pull: { "${1:field}": ${2:condition} } }', + link: getDocLink('$pull', META_UPDATE_ARRAY), + }, + { + value: '$push', + meta: META_UPDATE_ARRAY, + description: 'The $push operator adds a specified value to an array within a document.', + snippet: '{ $push: { "${1:field}": ${2:value} } }', + link: getDocLink('$push', META_UPDATE_ARRAY), + }, + { + value: '$pullAll', + meta: META_UPDATE_ARRAY, + description: 'The $pullAll operator is used to remove all instances of the specified values from an array.', + snippet: '{ $pullAll: { "${1:field}": [${2:values}] } }', + link: getDocLink('$pullAll', META_UPDATE_ARRAY), + }, + { + value: '$each', + meta: META_UPDATE_ARRAY, + description: + 'The $each operator is used within an `$addToSet`or`$push` operation to add multiple elements to an array field in a single update operation.', + snippet: '{ $each: [${1:values}] }', + link: getDocLink('$each', META_UPDATE_ARRAY), + }, + { + value: '$position', + meta: META_UPDATE_ARRAY, + description: + 'Specifies the position in the array at which the $push operator inserts elements. Used with $each.', + snippet: '{ $position: ${1:index} }', + link: getDocLink('$position', META_UPDATE_ARRAY), + }, + { + value: '$slice', + meta: META_UPDATE_ARRAY, + description: 'The $slice operator returns a subset of an array from any element onwards in the array.', + snippet: '{ $slice: ${1:number} }', + link: getDocLink('$slice', META_UPDATE_ARRAY), + }, + { + value: '$sort', + meta: META_UPDATE_ARRAY, + description: + 'The $sort stage in the aggregation pipeline is used to order the documents in the pipeline by a specified field or fields.', + snippet: '{ $sort: { "${1:field}": ${2:1} } }', + link: getDocLink('$sort', META_UPDATE_ARRAY), + }, +]; + +// --------------------------------------------------------------------------- +// Bitwise Update Operators +// --------------------------------------------------------------------------- + +const bitwiseUpdateOperators: readonly OperatorEntry[] = [ + { + value: '$bit', + meta: META_UPDATE_BITWISE, + description: 'The `$bit` operator is used to perform bitwise operations on integer values.', + snippet: '{ $bit: { "${1:field}": { "${2:and|or|xor}": ${3:value} } } }', + link: getDocLink('$bit', META_UPDATE_BITWISE), + }, +]; + +// --------------------------------------------------------------------------- +// Registration +// --------------------------------------------------------------------------- + +registerOperators([...fieldUpdateOperators, ...arrayUpdateOperators, ...bitwiseUpdateOperators]); diff --git a/packages/documentdb-constants/src/windowOperators.ts b/packages/documentdb-constants/src/windowOperators.ts new file mode 100644 index 000000000..aafb8e465 --- /dev/null +++ b/packages/documentdb-constants/src/windowOperators.ts @@ -0,0 +1,230 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// AUTO-GENERATED — DO NOT EDIT BY HAND +// +// Generated by: npm run generate (scripts/generate-from-reference.ts) +// Sources: resources/operator-reference-scraped.md +// resources/operator-reference-overrides.md +// +// To change operator data, edit the overrides file and re-run the generator. + +import { getDocLink } from './docLinks'; +import { registerOperators } from './getFilteredCompletions'; +import { META_WINDOW } from './metaTags'; +import { type OperatorEntry } from './types'; + +// --------------------------------------------------------------------------- +// Window Operators +// --------------------------------------------------------------------------- + +const windowOperators: readonly OperatorEntry[] = [ + { + value: '$sum', + meta: META_WINDOW, + description: 'The $sum operator calculates the sum of the values of a field based on a filtering criteria', + snippet: '{ $sum: "${1:\\$field}" }', + link: getDocLink('$sum', META_WINDOW), + }, + { + value: '$push', + meta: META_WINDOW, + description: 'The $push operator adds a specified value to an array within a document.', + snippet: '{ $push: "${1:\\$field}" }', + link: getDocLink('$push', META_WINDOW), + }, + { + value: '$addToSet', + meta: META_WINDOW, + description: + "The addToSet operator adds elements to an array if they don't already exist, while ensuring uniqueness of elements within the set.", + snippet: '{ $addToSet: "${1:\\$field}" }', + link: getDocLink('$addToSet', META_WINDOW), + }, + { + value: '$count', + meta: META_WINDOW, + description: + 'The `$count` operator is used to count the number of documents that match a query filtering criteria.', + snippet: '{ $count: "${1:\\$field}" }', + link: getDocLink('$count', META_WINDOW), + }, + { + value: '$max', + meta: META_WINDOW, + description: 'The $max operator returns the maximum value from a set of input values.', + snippet: '{ $max: "${1:\\$field}" }', + link: getDocLink('$max', META_WINDOW), + }, + { + value: '$min', + meta: META_WINDOW, + description: 'Retrieves the minimum value for a specified field', + snippet: '{ $min: "${1:\\$field}" }', + link: getDocLink('$min', META_WINDOW), + }, + { + value: '$avg', + meta: META_WINDOW, + description: 'Computes the average of numeric values for documents in a group, bucket, or window.', + snippet: '{ $avg: "${1:\\$field}" }', + link: getDocLink('$avg', META_WINDOW), + }, + { + value: '$stdDevPop', + meta: META_WINDOW, + description: 'The $stddevpop operator calculates the standard deviation of the specified values', + snippet: '{ $stdDevPop: "${1:\\$field}" }', + link: getDocLink('$stdDevPop', META_WINDOW), + }, + { + value: '$bottom', + meta: META_WINDOW, + description: + "The $bottom operator returns the last document from the query's result set sorted by one or more fields", + snippet: '{ $bottom: "${1:\\$field}" }', + link: getDocLink('$bottom', META_WINDOW), + }, + { + value: '$bottomN', + meta: META_WINDOW, + description: 'The $bottomN operator returns the last N documents from the result sorted by one or more fields', + snippet: '{ $bottomN: "${1:\\$field}" }', + link: getDocLink('$bottomN', META_WINDOW), + }, + { + value: '$covariancePop', + meta: META_WINDOW, + description: 'The $covariancePop operator returns the covariance of two numerical expressions', + snippet: '{ $covariancePop: "${1:\\$field}" }', + link: getDocLink('$covariancePop', META_WINDOW), + }, + { + value: '$covarianceSamp', + meta: META_WINDOW, + description: 'The $covarianceSamp operator returns the covariance of a sample of two numerical expressions', + snippet: '{ $covarianceSamp: "${1:\\$field}" }', + link: getDocLink('$covarianceSamp', META_WINDOW), + }, + { + value: '$denseRank', + meta: META_WINDOW, + description: + 'The $denseRank operator assigns and returns a positional ranking for each document within a partition based on a specified sort order', + snippet: '{ $denseRank: {} }', + link: getDocLink('$denseRank', META_WINDOW), + }, + { + value: '$derivative', + meta: META_WINDOW, + description: + 'The $derivative operator calculates the average rate of change of the value of a field within a specified window.', + snippet: '{ $derivative: { input: "${1:\\$field}", unit: "${2:hour}" } }', + link: getDocLink('$derivative', META_WINDOW), + }, + { + value: '$documentNumber', + meta: META_WINDOW, + description: + 'The $documentNumber operator assigns and returns a position for each document within a partition based on a specified sort order', + snippet: '{ $documentNumber: {} }', + link: getDocLink('$documentNumber', META_WINDOW), + }, + { + value: '$expMovingAvg', + meta: META_WINDOW, + description: + 'The $expMovingAvg operator calculates the moving average of a field based on the specified number of documents to hold the highest weight', + snippet: '{ $expMovingAvg: { input: "${1:\\$field}", N: ${2:number} } }', + link: getDocLink('$expMovingAvg', META_WINDOW), + }, + { + value: '$first', + meta: META_WINDOW, + description: "The $first operator returns the first value in a group according to the group's sorting order.", + snippet: '{ $first: "${1:\\$field}" }', + link: getDocLink('$first', META_WINDOW), + }, + { + value: '$integral', + meta: META_WINDOW, + description: + 'The $integral operator calculates the area under a curve with the specified range of documents forming the adjacent documents for the calculation.', + snippet: '{ $integral: { input: "${1:\\$field}", unit: "${2:hour}" } }', + link: getDocLink('$integral', META_WINDOW), + }, + { + value: '$last', + meta: META_WINDOW, + description: 'The $last operator returns the last document from the result sorted by one or more fields', + snippet: '{ $last: "${1:\\$field}" }', + link: getDocLink('$last', META_WINDOW), + }, + { + value: '$linearFill', + meta: META_WINDOW, + description: + 'The $linearFill operator interpolates missing values in a sequence of documents using linear interpolation.', + snippet: '{ $linearFill: "${1:\\$field}" }', + link: getDocLink('$linearFill', META_WINDOW), + }, + { + value: '$locf', + meta: META_WINDOW, + description: + 'The $locf operator propagates the last observed non-null value forward within a partition in a windowed query.', + snippet: '{ $locf: "${1:\\$field}" }', + link: getDocLink('$locf', META_WINDOW), + }, + { + value: '$minN', + meta: META_WINDOW, + description: 'Retrieves the bottom N values based on a specified filtering criteria', + snippet: '{ $minN: "${1:\\$field}" }', + link: getDocLink('$minN', META_WINDOW), + }, + { + value: '$rank', + meta: META_WINDOW, + description: 'The $rank operator ranks documents within a partition based on a specified sort order.', + snippet: '{ $rank: {} }', + link: getDocLink('$rank', META_WINDOW), + }, + { + value: '$shift', + meta: META_WINDOW, + description: 'A window operator that shifts values within a partition and returns the shifted value.', + snippet: '{ $shift: { output: "${1:\\$field}", by: ${2:1}, default: ${3:null} } }', + link: getDocLink('$shift', META_WINDOW), + }, + { + value: '$stdDevSamp', + meta: META_WINDOW, + description: + 'The $stddevsamp operator calculates the standard deviation of a specified sample of values and not the entire population', + snippet: '{ $stdDevSamp: "${1:\\$field}" }', + link: getDocLink('$stdDevSamp', META_WINDOW), + }, + { + value: '$top', + meta: META_WINDOW, + description: 'The $top operator returns the first document from the result set sorted by one or more fields', + snippet: '{ $top: "${1:\\$field}" }', + link: getDocLink('$top', META_WINDOW), + }, + { + value: '$topN', + meta: META_WINDOW, + description: 'The $topN operator returns the first N documents from the result sorted by one or more fields', + snippet: '{ $topN: "${1:\\$field}" }', + link: getDocLink('$topN', META_WINDOW), + }, +]; + +// --------------------------------------------------------------------------- +// Registration +// --------------------------------------------------------------------------- + +registerOperators([...windowOperators]); From 45625d20f8f0ef5c1b1031e2657602f3bc9c6c27 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Fri, 20 Feb 2026 12:07:16 +0000 Subject: [PATCH 030/128] feat: add evaluate-overrides script to assess scraped data and manual overrides --- packages/documentdb-constants/package.json | 3 +- .../documentdb-constants/scripts/README.md | 22 ++ .../scripts/evaluate-overrides.ts | 367 ++++++++++++++++++ 3 files changed, 391 insertions(+), 1 deletion(-) create mode 100644 packages/documentdb-constants/scripts/evaluate-overrides.ts diff --git a/packages/documentdb-constants/package.json b/packages/documentdb-constants/package.json index bdcd8420a..cb612d748 100644 --- a/packages/documentdb-constants/package.json +++ b/packages/documentdb-constants/package.json @@ -13,7 +13,8 @@ "test": "jest --config jest.config.js", "prettier-fix": "prettier -w \"(scripts|src)/**/*.@(js|ts|jsx|tsx|json|md)\" \"./*.@(js|ts|jsx|tsx|json|md)\"", "scrape": "ts-node scripts/scrape-operator-docs.ts && prettier --write resources/operator-reference-scraped.md", - "generate": "ts-node scripts/generate-from-reference.ts && prettier --write \"src/queryOperators.ts\" \"src/updateOperators.ts\" \"src/expressionOperators.ts\" \"src/accumulators.ts\" \"src/windowOperators.ts\" \"src/stages.ts\" \"src/systemVariables.ts\"" + "generate": "ts-node scripts/generate-from-reference.ts && prettier --write \"src/queryOperators.ts\" \"src/updateOperators.ts\" \"src/expressionOperators.ts\" \"src/accumulators.ts\" \"src/windowOperators.ts\" \"src/stages.ts\" \"src/systemVariables.ts\"", + "evaluate": "ts-node scripts/evaluate-overrides.ts" }, "repository": { "type": "git", diff --git a/packages/documentdb-constants/scripts/README.md b/packages/documentdb-constants/scripts/README.md index 1938af370..fb30afbe8 100644 --- a/packages/documentdb-constants/scripts/README.md +++ b/packages/documentdb-constants/scripts/README.md @@ -46,6 +46,26 @@ npm run generate > **Do not edit the generated `src/` files by hand.** Put corrections in `resources/operator-reference-overrides.md` instead. The generated files contain a header warning to this effect. +## evaluate-overrides.ts + +Evaluates the relationship between scraped data and manual overrides. Produces a color-coded report. + +```bash +npm run evaluate +``` + +**When to run:** + +- After re-scraping (`npm run scrape`) to see if previously-missing descriptions are now available +- Periodically, to check coverage and detect redundant overrides + +**Report sections:** + +1. **GAPS** — operators with empty scraped descriptions and no override (need attention) +2. **POTENTIALLY REDUNDANT** — operators that have **both** a scraped description and an override description; the override may no longer be needed +3. **ACTIVE OVERRIDES** — overrides filling real gaps, with both override and scraped values shown +4. **SUMMARY** — total counts and coverage percentage + ## Workflow ``` @@ -57,6 +77,8 @@ npm run generate │ ▼ operator-reference-scraped.md + │ + ├──── npm run evaluate (check gaps & redundant overrides) │ ├──── operator-reference-overrides.md (manual) │ diff --git a/packages/documentdb-constants/scripts/evaluate-overrides.ts b/packages/documentdb-constants/scripts/evaluate-overrides.ts new file mode 100644 index 000000000..81337ccd9 --- /dev/null +++ b/packages/documentdb-constants/scripts/evaluate-overrides.ts @@ -0,0 +1,367 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * evaluate-overrides.ts + * + * Evaluates the relationship between scraped operator data and manual overrides. + * Produces a report showing: + * + * 1. Operators with empty descriptions in the scrape AND no override + * (gaps that still need attention) + * 2. Operators that have overrides — shows both the override value and the + * original scraped value so you can detect when an override is no longer + * needed (e.g. the upstream docs now have a description) + * 3. Summary statistics + * + * Usage: npm run evaluate + */ + +import * as fs from 'fs'; +import * as path from 'path'; + +// --------------------------------------------------------------------------- +// Types (lightweight — reuses the same Markdown format as the generator) +// --------------------------------------------------------------------------- + +interface ParsedEntry { + value: string; + description: string; + category: string; +} + +interface OverrideEntry { + description?: string; + syntax?: string; + docLink?: string; + snippet?: string; +} + +// --------------------------------------------------------------------------- +// Parsers (simplified versions of the generator's parsers) +// --------------------------------------------------------------------------- + +function parseDump(content: string): ParsedEntry[] { + const lines = content.split('\n'); + const entries: ParsedEntry[] = []; + + let currentCategory = ''; + let currentOp: Partial | null = null; + let inCodeBlock = false; + + for (const line of lines) { + if (line.startsWith('```')) { + inCodeBlock = !inCodeBlock; + continue; + } + if (inCodeBlock) continue; + + const h2 = line.match(/^## (.+)$/); + if (h2) { + if (currentOp && currentCategory) { + entries.push({ + value: currentOp.value!, + description: currentOp.description || '', + category: currentCategory, + }); + } + currentOp = null; + const cat = h2[1].trim(); + if (cat === 'Summary' || cat === 'Not Listed') { + currentCategory = ''; + continue; + } + currentCategory = cat; + continue; + } + + const h3 = line.match(/^### (.+)$/); + if (h3 && currentCategory) { + if (currentOp) { + entries.push({ + value: currentOp.value!, + description: currentOp.description || '', + category: currentCategory, + }); + } + currentOp = { value: h3[1].trim(), description: '', category: currentCategory }; + continue; + } + + if (currentOp && line.startsWith('- **Description:**')) { + currentOp.description = line.replace('- **Description:**', '').trim(); + } + } + + if (currentOp && currentCategory) { + entries.push({ value: currentOp.value!, description: currentOp.description || '', category: currentCategory }); + } + + return entries; +} + +function parseOverrides(content: string): Map> { + const lines = content.split('\n'); + const result = new Map>(); + + let currentCategory = ''; + let currentOp: { value: string; entry: OverrideEntry } | null = null; + let inCodeBlock = false; + let syntaxLines: string[] = []; + + for (const line of lines) { + if (line.startsWith('```')) { + if (inCodeBlock) { + inCodeBlock = false; + if (currentOp) { + currentOp.entry.syntax = syntaxLines.join('\n').trim(); + } + syntaxLines = []; + continue; + } else { + inCodeBlock = true; + continue; + } + } + if (inCodeBlock) { + syntaxLines.push(line); + continue; + } + + const h2 = line.match(/^## (.+)$/); + if (h2) { + if (currentOp && currentCategory) { + saveOverride(result, currentCategory, currentOp); + } + currentOp = null; + currentCategory = h2[1].trim(); + continue; + } + + const h3 = line.match(/^### (.+)$/); + if (h3 && currentCategory) { + if (currentOp) { + saveOverride(result, currentCategory, currentOp); + } + currentOp = { value: h3[1].trim(), entry: {} }; + continue; + } + + if (currentOp) { + if (line.startsWith('- **Description:**')) { + currentOp.entry.description = line.replace('- **Description:**', '').trim(); + } + if (line.startsWith('- **Doc Link:**')) { + currentOp.entry.docLink = line.replace('- **Doc Link:**', '').trim(); + } + if (line.startsWith('- **Snippet:**')) { + currentOp.entry.snippet = line.replace('- **Snippet:**', '').trim(); + } + } + } + + if (currentOp && currentCategory) { + saveOverride(result, currentCategory, currentOp); + } + + return result; +} + +function saveOverride( + map: Map>, + category: string, + op: { value: string; entry: OverrideEntry }, +): void { + if (!map.has(category)) map.set(category, new Map()); + map.get(category)!.set(op.value, op.entry); +} + +// --------------------------------------------------------------------------- +// Lookup helpers +// --------------------------------------------------------------------------- + +/** Find an override for an operator, checking both exact category match and cross-category fallback. */ +function findOverride( + overrides: Map>, + operatorValue: string, + category: string, +): { override: OverrideEntry; overrideCategory: string } | undefined { + // Exact category match first + const catOverrides = overrides.get(category); + if (catOverrides) { + const entry = catOverrides.get(operatorValue); + if (entry) return { override: entry, overrideCategory: category }; + } + + // Cross-category fallback + for (const [overrideCat, opMap] of overrides) { + if (overrideCat === category) continue; + const entry = opMap.get(operatorValue); + if (entry) return { override: entry, overrideCategory: overrideCat }; + } + + return undefined; +} + +// --------------------------------------------------------------------------- +// ANSI colors for terminal output +// --------------------------------------------------------------------------- + +const RED = '\x1b[31m'; +const GREEN = '\x1b[32m'; +const YELLOW = '\x1b[33m'; +const CYAN = '\x1b[36m'; +const DIM = '\x1b[2m'; +const BOLD = '\x1b[1m'; +const RESET = '\x1b[0m'; + +// --------------------------------------------------------------------------- +// Main +// --------------------------------------------------------------------------- + +function main(): void { + const dumpPath = path.join(__dirname, '..', 'resources', 'operator-reference-scraped.md'); + const overridePath = path.join(__dirname, '..', 'resources', 'operator-reference-overrides.md'); + + if (!fs.existsSync(dumpPath)) { + console.error(`❌ Scraped dump not found: ${dumpPath}`); + process.exit(1); + } + + console.log(`${BOLD}📊 Evaluating operator overrides${RESET}\n`); + + // Parse both files + const dumpContent = fs.readFileSync(dumpPath, 'utf-8'); + const dumpEntries = parseDump(dumpContent); + + let overrides = new Map>(); + let totalOverrideCount = 0; + if (fs.existsSync(overridePath)) { + const overrideContent = fs.readFileSync(overridePath, 'utf-8'); + overrides = parseOverrides(overrideContent); + for (const [, catMap] of overrides) { + totalOverrideCount += catMap.size; + } + } + + // Categorize every scraped entry + const gaps: ParsedEntry[] = []; // empty description, no override + const overridden: { entry: ParsedEntry; override: OverrideEntry; overrideCategory: string }[] = []; + const redundantOverrides: { entry: ParsedEntry; override: OverrideEntry; overrideCategory: string }[] = []; + const descriptionsOk: ParsedEntry[] = []; + + for (const entry of dumpEntries) { + const match = findOverride(overrides, entry.value, entry.category); + const hasScrapedDescription = entry.description.trim().length > 0; + + if (match) { + if (hasScrapedDescription && match.override.description) { + // Has both scraped description AND an override description + redundantOverrides.push({ entry, override: match.override, overrideCategory: match.overrideCategory }); + } else { + // Override is filling a gap (or overriding something else) + overridden.push({ entry, override: match.override, overrideCategory: match.overrideCategory }); + } + } else if (!hasScrapedDescription) { + gaps.push(entry); + } else { + descriptionsOk.push(entry); + } + } + + // ----------------------------------------------------------------------- + // Section 1: Gaps — empty description, no override + // ----------------------------------------------------------------------- + console.log(`${BOLD}${RED}═══ GAPS: Empty description, no override (${gaps.length}) ═══${RESET}`); + if (gaps.length === 0) { + console.log(` ${GREEN}✅ No gaps — all operators have descriptions or overrides.${RESET}\n`); + } else { + const byCategory = groupByCategory(gaps); + for (const [cat, ops] of byCategory) { + console.log(` ${CYAN}${cat}${RESET}`); + for (const op of ops) { + console.log(` ${RED}⚠${RESET} ${op.value}`); + } + } + console.log(''); + } + + // ----------------------------------------------------------------------- + // Section 2: Potentially redundant overrides + // (scraped dump NOW has a description, but override also provides one) + // ----------------------------------------------------------------------- + console.log(`${BOLD}${YELLOW}═══ POTENTIALLY REDUNDANT OVERRIDES (${redundantOverrides.length}) ═══${RESET}`); + if (redundantOverrides.length === 0) { + console.log(` ${GREEN}✅ No redundant overrides — all overrides are filling gaps.${RESET}\n`); + } else { + console.log( + ` ${DIM}These operators now have scraped descriptions. The override may no longer be needed.${RESET}`, + ); + console.log( + ` ${DIM}Compare the values below — if the scraped one is good enough, remove the override.${RESET}\n`, + ); + for (const { entry, override, overrideCategory } of redundantOverrides) { + console.log(` ${CYAN}${entry.value}${RESET} ${DIM}(${entry.category})${RESET}`); + console.log(` ${DIM}Override (${overrideCategory}):${RESET} ${override.description}`); + console.log(` ${DIM}Scraped:${RESET} ${entry.description}`); + console.log(''); + } + } + + // ----------------------------------------------------------------------- + // Section 3: Active overrides filling gaps + // ----------------------------------------------------------------------- + console.log(`${BOLD}${GREEN}═══ ACTIVE OVERRIDES FILLING GAPS (${overridden.length}) ═══${RESET}`); + if (overridden.length === 0) { + console.log(` ${DIM}No active overrides.${RESET}\n`); + } else { + const byCategory = new Map(); + for (const item of overridden) { + const cat = item.overrideCategory; + if (!byCategory.has(cat)) byCategory.set(cat, []); + byCategory.get(cat)!.push(item); + } + for (const [cat, items] of byCategory) { + console.log(` ${CYAN}${cat}${RESET} (${items.length} overrides)`); + for (const { entry, override } of items) { + const overrideDesc = override.description || '(no description override)'; + const scrapedDesc = entry.description || '(empty)'; + console.log(` ${GREEN}✓${RESET} ${entry.value}`); + console.log(` ${DIM}Override:${RESET} ${overrideDesc}`); + if (scrapedDesc !== '(empty)') { + console.log(` ${DIM}Scraped:${RESET} ${scrapedDesc}`); + } + } + } + console.log(''); + } + + // ----------------------------------------------------------------------- + // Section 4: Summary + // ----------------------------------------------------------------------- + console.log(`${BOLD}═══ SUMMARY ═══${RESET}`); + console.log(` Total scraped operators: ${dumpEntries.length}`); + console.log(` With scraped description: ${descriptionsOk.length + redundantOverrides.length}`); + console.log(` Filled by override: ${overridden.length}`); + console.log(` Potentially redundant: ${YELLOW}${redundantOverrides.length}${RESET}`); + console.log(` ${RED}Gaps remaining:${RESET} ${gaps.length}`); + console.log(` Total overrides in file: ${totalOverrideCount}`); + console.log(` Coverage: ${((1 - gaps.length / dumpEntries.length) * 100).toFixed(1)}%`); +} + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + +function groupByCategory(entries: ParsedEntry[]): Map { + const map = new Map(); + for (const e of entries) { + if (!map.has(e.category)) map.set(e.category, []); + map.get(e.category)!.push(e); + } + return map; +} + +main(); From eaf0a9b6286540edc7fac98b478541bc8468856b Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Fri, 20 Feb 2026 12:33:41 +0000 Subject: [PATCH 031/128] refactor: enhance findOverride function to support cross-category fallback logic --- .../scripts/evaluate-overrides.ts | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/packages/documentdb-constants/scripts/evaluate-overrides.ts b/packages/documentdb-constants/scripts/evaluate-overrides.ts index 81337ccd9..671a9ddae 100644 --- a/packages/documentdb-constants/scripts/evaluate-overrides.ts +++ b/packages/documentdb-constants/scripts/evaluate-overrides.ts @@ -182,22 +182,41 @@ function saveOverride( // Lookup helpers // --------------------------------------------------------------------------- -/** Find an override for an operator, checking both exact category match and cross-category fallback. */ +/** + * Find an override for a dump entry, mirroring how the generator resolves overrides. + * + * The generator's `applyOverrides` iterates override categories: + * 1. If the override category exists in the dump, it looks for the operator in that exact category. + * 2. If the override category does NOT exist in the dump, it falls back to cross-category search. + * + * So for a dump entry (operatorValue, category), an override matches only if: + * (a) The override is in the same category as the dump entry (exact match), OR + * (b) The override is in a category that doesn't exist in the dump at all, and no + * earlier dump category already claimed this operator via cross-category fallback. + * + * We pass `dumpCategories` (all category names in the dump) to distinguish (a) from (b). + */ function findOverride( overrides: Map>, operatorValue: string, category: string, + dumpCategories: Set, ): { override: OverrideEntry; overrideCategory: string } | undefined { - // Exact category match first + // Exact category match: override category === dump entry category const catOverrides = overrides.get(category); if (catOverrides) { const entry = catOverrides.get(operatorValue); if (entry) return { override: entry, overrideCategory: category }; } - // Cross-category fallback + // Cross-category fallback: only if override category doesn't exist in the dump. + // This mirrors the generator, which only enters the cross-category path when + // `categorizedOps.get(category)` returns undefined. for (const [overrideCat, opMap] of overrides) { if (overrideCat === category) continue; + // If this override category exists in the dump, the generator would do an + // exact-category-only lookup there — it would NOT spill into other categories. + if (dumpCategories.has(overrideCat)) continue; const entry = opMap.get(operatorValue); if (entry) return { override: entry, overrideCategory: overrideCat }; } @@ -252,8 +271,11 @@ function main(): void { const redundantOverrides: { entry: ParsedEntry; override: OverrideEntry; overrideCategory: string }[] = []; const descriptionsOk: ParsedEntry[] = []; + // Collect all dump category names so findOverride can distinguish exact vs cross-category + const dumpCategories = new Set(dumpEntries.map((e) => e.category)); + for (const entry of dumpEntries) { - const match = findOverride(overrides, entry.value, entry.category); + const match = findOverride(overrides, entry.value, entry.category, dumpCategories); const hasScrapedDescription = entry.description.trim().length > 0; if (match) { From 6642026386a57252586751fc4d791eab53c17156 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Fri, 20 Feb 2026 12:47:00 +0000 Subject: [PATCH 032/128] feat: add comprehensive unit tests for DocumentDB operator references and completions - Introduced new test files for operator reference verification, parsing, and structural invariants. - Implemented tests for `getFilteredCompletions` and `docLinks` to ensure correct URL generation. - Enhanced Jest configuration to limit workers and updated test match patterns. - Added `parseOperatorReference` utility to structure operator data from markdown dumps. - Verified that all operators in the implementation match the documented reference and that no unsupported operators are present. - Ensured all entries have required fields, valid meta tags, and non-empty descriptions. --- jest.config.js | 1 + package-lock.json | 19144 +++++++++------- packages/documentdb-constants/jest.config.js | 5 +- packages/documentdb-constants/package.json | 7 +- .../documentdb-constants/src/docLinks.test.ts | 72 + .../src/getFilteredCompletions.test.ts | 222 + .../src/operatorReference.test.ts | 164 + .../src/parseOperatorReference.test.ts | 156 + .../src/parseOperatorReference.ts | 159 + .../src/structuralInvariants.test.ts | 242 + 10 files changed, 11711 insertions(+), 8461 deletions(-) create mode 100644 packages/documentdb-constants/src/docLinks.test.ts create mode 100644 packages/documentdb-constants/src/getFilteredCompletions.test.ts create mode 100644 packages/documentdb-constants/src/operatorReference.test.ts create mode 100644 packages/documentdb-constants/src/parseOperatorReference.test.ts create mode 100644 packages/documentdb-constants/src/parseOperatorReference.ts create mode 100644 packages/documentdb-constants/src/structuralInvariants.test.ts diff --git a/jest.config.js b/jest.config.js index 6db24cd52..ca22ee433 100644 --- a/jest.config.js +++ b/jest.config.js @@ -13,5 +13,6 @@ module.exports = { }, }, '/packages/schema-analyzer', + '/packages/documentdb-constants', ], }; diff --git a/package-lock.json b/package-lock.json index 25a846b9b..cf28dcd8b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6055,6 +6055,16 @@ "@types/send": "*" } }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/hast": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", @@ -9788,272 +9798,334 @@ "dev": true, "license": "MIT" }, - "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-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", "dev": true, "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.1" + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" }, "bin": { - "cross-env": "src/bin/cross-env.js", - "cross-env-shell": "src/bin/cross-env-shell.js" + "create-jest": "bin/create-jest.js" }, "engines": { - "node": ">=10.14", - "npm": ">=6", - "yarn": ">=1" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "node_modules/create-jest/node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "license": "MIT", "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" }, "engines": { - "node": ">= 8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", + "node_modules/create-jest/node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, "engines": { - "node": "*" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/css-loader": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz", - "integrity": "sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA==", + "node_modules/create-jest/node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, "license": "MIT", "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" }, "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.27.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/css-select": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", - "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "node_modules/create-jest/node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" + "jest-get-type": "^29.6.3" }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/css-what": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", - "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "node_modules/create-jest/node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">= 6" + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "node_modules/create-jest/node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" }, "engines": { - "node": ">=4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "license": "MIT" - }, - "node_modules/data-view-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", - "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "node_modules/create-jest/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/data-view-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", - "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "node_modules/create-jest/node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" }, - "funding": { - "url": "https://github.com/sponsors/inspect-js" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/data-view-byte-offset": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", - "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "node_modules/create-jest/node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/dayjs": { - "version": "1.11.19", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", - "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", + "node_modules/create-jest/node_modules/@sinclair/typebox": { + "version": "0.27.10", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", + "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==", + "dev": true, "license": "MIT" }, - "node_modules/debounce": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", - "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", + "node_modules/create-jest/node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dev": true, - "license": "MIT" + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "node_modules/create-jest/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, "engines": { - "node": ">=6.0" + "node": ">=10" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "node_modules/create-jest/node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, "license": "MIT", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@babel/core": "^7.8.0" } }, - "node_modules/decode-named-character-reference": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", - "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", + "node_modules/create-jest/node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/create-jest/node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, "license": "MIT", "dependencies": { - "character-entities": "^2.0.0" + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "node_modules/create-jest/node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, "license": "MIT", "dependencies": { - "mimic-response": "^3.1.0" + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "node_modules/create-jest/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "license": "MIT", "engines": { @@ -10063,632 +10135,737 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/dedent": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", - "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==", + "node_modules/create-jest/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, - "license": "MIT", - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" } - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, + ], "license": "MIT", - "optional": true, "engines": { - "node": ">=4.0.0" + "node": ">=8" } }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "node_modules/create-jest/node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", "dev": true, "license": "MIT" }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "node_modules/create-jest/node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/deepmerge-json": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/deepmerge-json/-/deepmerge-json-1.5.0.tgz", - "integrity": "sha512-jZRrDmBKjmGcqMFEUJ14FjMJwm05Qaked+1vxaALRtF0UAl7lPU8OLWXFxvoeg3jbQM249VPFVn8g2znaQkEtA==", + "node_modules/create-jest/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, "engines": { - "node": ">=4.0.0" + "node": ">=8" } }, - "node_modules/default-browser": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.4.0.tgz", - "integrity": "sha512-XDuvSq38Hr1MdN47EDvYtx3U0MTqpCEn+F6ft8z2vYDzMrvQhVp0ui9oQdqW3MvK3vqUETglt1tVGgjLuJ5izg==", + "node_modules/create-jest/node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, "license": "MIT", "dependencies": { - "bundle-name": "^4.1.0", - "default-browser-id": "^5.0.0" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/default-browser-id": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", - "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "node_modules/create-jest/node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, "engines": { - "node": ">=18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } } }, - "node_modules/defaults": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-2.0.2.tgz", - "integrity": "sha512-cuIw0PImdp76AOfgkjbW4VhQODRmNNcKR73vdCH5cLd/ifj7aamfoXvYgfGkEAjNJZ3ozMIy9Gu2LutUkGEPbA==", + "node_modules/create-jest/node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=16" + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "node_modules/create-jest/node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dev": true, "license": "MIT", + "dependencies": { + "detect-newline": "^3.0.0" + }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "node_modules/create-jest/node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dev": true, "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "node_modules/create-jest/node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "node_modules/create-jest/node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, "license": "MIT", "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "node_modules/create-jest/node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", "dev": true, "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "node_modules/create-jest/node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dev": true, "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, "engines": { - "node": ">= 0.8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "node_modules/create-jest/node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, "engines": { - "node": ">=6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "node_modules/create-jest/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "node_modules/create-jest/node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, - "license": "Apache-2.0", - "optional": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "node_modules/create-jest/node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "node_modules/create-jest/node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, - "license": "MIT" - }, - "node_modules/devlop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", "license": "MIT", "dependencies": { - "dequal": "^2.0.0" + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/diff": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", - "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "node_modules/create-jest/node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, "engines": { - "node": ">=0.3.1" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==", - "license": "MIT" - }, - "node_modules/dns-packet": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", - "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "node_modules/create-jest/node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "dev": true, "license": "MIT", "dependencies": { - "@leichtgewicht/ip-codec": "^2.0.1" + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" }, "engines": { - "node": ">=6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "node_modules/create-jest/node_modules/jest-snapshot/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "node_modules/create-jest/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, "license": "MIT", "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "node_modules/create-jest/node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "domelementtype": "^2.3.0" + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" }, "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/domutils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", - "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "node_modules/create-jest/node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "node_modules/create-jest/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": ">= 0.4" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT" - }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/editions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/editions/-/editions-6.22.0.tgz", - "integrity": "sha512-UgGlf8IW75je7HZjNDpJdCv4cGJWIi6yumFdZ0R7A8/CIhQiWUjyGLCxdHpd8bmyD1gnkfUNK0oeOXqUS2cpfQ==", + "node_modules/create-jest/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, - "license": "Artistic-2.0", + "license": "MIT", "dependencies": { - "version-range": "^4.15.0" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "ecmascript": ">= es5", - "node": ">=4" - }, - "funding": { - "url": "https://bevry.me/fund" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "node_modules/create-jest/node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], "license": "MIT" }, - "node_modules/electron-to-chromium": { - "version": "1.5.286", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", - "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", + "node_modules/create-jest/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, - "license": "ISC" - }, - "node_modules/embla-carousel": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz", - "integrity": "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==", "license": "MIT" }, - "node_modules/embla-carousel-autoplay": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/embla-carousel-autoplay/-/embla-carousel-autoplay-8.6.0.tgz", - "integrity": "sha512-OBu5G3nwaSXkZCo1A6LTaFMZ8EpkYbwIaH+bPqdBnDGQ2fh4+NbzjXjs2SktoPNKCtflfVMc75njaDHOYXcrsA==", - "license": "MIT", - "peerDependencies": { - "embla-carousel": "8.6.0" - } - }, - "node_modules/embla-carousel-fade": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/embla-carousel-fade/-/embla-carousel-fade-8.6.0.tgz", - "integrity": "sha512-qaYsx5mwCz72ZrjlsXgs1nKejSrW+UhkbOMwLgfRT7w2LtdEB03nPRI06GHuHv5ac2USvbEiX2/nAHctcDwvpg==", - "license": "MIT", - "peerDependencies": { - "embla-carousel": "8.6.0" + "node_modules/create-jest/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "node_modules/create-jest/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "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/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "node_modules/create-jest/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, "engines": { - "node": ">= 4" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "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", - "engines": { - "node": ">= 0.8" - } + "license": "MIT" }, - "node_modules/encoding-sniffer": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", - "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==", + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", "dev": true, "license": "MIT", "dependencies": { - "iconv-lite": "^0.6.3", - "whatwg-encoding": "^3.1.1" + "cross-spawn": "^7.0.1" }, - "funding": { - "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", - "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "once": "^1.4.0" + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" } }, - "node_modules/enhanced-resolve": { - "version": "5.19.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz", - "integrity": "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==", + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.3.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": ">=10.13.0" + "node": ">= 8" } }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", "dev": true, - "license": "BSD-2-Clause", + "license": "BSD-3-Clause", "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "node": "*" } }, - "node_modules/envinfo": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.20.0.tgz", - "integrity": "sha512-+zUomDcLXsVkQ37vUqWBvQwLaLlj8eZPSi61llaEFAVBY5mhcXdaSw1pSJVl4yTYD5g/gEfpNl28YYk4IPvrrg==", + "node_modules/css-loader": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz", + "integrity": "sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA==", "dev": true, "license": "MIT", - "bin": { - "envinfo": "dist/cli.js" + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" }, "engines": { - "node": ">=4" + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.27.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } } }, - "node_modules/environment": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", - "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/error-ex": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", - "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/error-stack-parser": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", - "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, "license": "MIT", - "dependencies": { - "stackframe": "^1.3.4" + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" } }, - "node_modules/es-abstract": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", - "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "dev": true, "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -10697,2055 +10874,2136 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" } }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-module-lexer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", - "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", - "dev": true, + "node_modules/dayjs": { + "version": "1.11.19", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", + "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", "license": "MIT" }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { - "es-errors": "^1.3.0" + "ms": "^2.1.3" }, "engines": { - "node": ">= 0.4" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, "engines": { - "node": ">= 0.4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/es-shim-unscopables": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", - "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", - "dev": true, + "node_modules/decode-named-character-reference": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", + "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", "license": "MIT", "dependencies": { - "hasown": "^2.0.2" + "character-entities": "^2.0.0" }, - "engines": { - "node": ">= 0.4" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/es-to-primitive": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", - "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "dev": true, "license": "MIT", "dependencies": { - "is-callable": "^1.2.7", - "is-date-object": "^1.0.5", - "is-symbol": "^1.0.4" + "mimic-response": "^3.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/es-toolkit": { - "version": "1.42.0", - "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.42.0.tgz", - "integrity": "sha512-SLHIyY7VfDJBM8clz4+T2oquwTQxEzu263AyhVK4jREOAwJ+8eebaa4wM3nlvnAqhDrMm2EsA6hWHaQsMPQ1nA==", + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, "license": "MIT", - "workspaces": [ - "docs", - "benchmarks" - ] + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "node_modules/dedent": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", + "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, "license": "MIT", + "optional": true, "engines": { - "node": ">=6" + "node": ">=4.0.0" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, "license": "MIT" }, - "node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/eslint": { - "version": "9.39.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", - "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", + "node_modules/deepmerge-json": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/deepmerge-json/-/deepmerge-json-1.5.0.tgz", + "integrity": "sha512-jZRrDmBKjmGcqMFEUJ14FjMJwm05Qaked+1vxaALRtF0UAl7lPU8OLWXFxvoeg3jbQM249VPFVn8g2znaQkEtA==", "dev": true, "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/default-browser": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.4.0.tgz", + "integrity": "sha512-XDuvSq38Hr1MdN47EDvYtx3U0MTqpCEn+F6ft8z2vYDzMrvQhVp0ui9oQdqW3MvK3vqUETglt1tVGgjLuJ5izg==", + "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.8.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.1", - "@eslint/config-helpers": "^0.4.2", - "@eslint/core": "^0.17.0", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.39.1", - "@eslint/plugin-kit": "^0.4.1", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@types/estree": "^1.0.6", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.4.0", - "eslint-visitor-keys": "^4.2.1", - "espree": "^10.4.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" }, "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "license": "MIT", + "engines": { + "node": ">=18" }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "node_modules/defaults": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-2.0.2.tgz", + "integrity": "sha512-cuIw0PImdp76AOfgkjbW4VhQODRmNNcKR73vdCH5cLd/ifj7aamfoXvYgfGkEAjNJZ3ozMIy9Gu2LutUkGEPbA==", "dev": true, "license": "MIT", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", "dev": true, "license": "MIT", - "dependencies": { - "ms": "^2.1.1" + "engines": { + "node": ">=10" } }, - "node_modules/eslint-module-utils": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", - "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, "license": "MIT", "dependencies": { - "debug": "^3.2.7" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { - "node": ">=4" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "license": "MIT", - "dependencies": { - "ms": "^2.1.1" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-plugin-import": { - "version": "2.32.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", - "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "license": "MIT", "dependencies": { - "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.9", - "array.prototype.findlastindex": "^1.2.6", - "array.prototype.flat": "^1.3.3", - "array.prototype.flatmap": "^1.3.3", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.1", - "hasown": "^2.0.2", - "is-core-module": "^2.16.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "object.groupby": "^1.0.3", - "object.values": "^1.2.1", - "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.9", - "tsconfig-paths": "^3.15.0" + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { - "node": ">=4" + "node": ">= 0.4" }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": ">=0.4.0" } }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, "license": "MIT", - "dependencies": { - "ms": "^2.1.1" + "engines": { + "node": ">= 0.8" } }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", "engines": { - "node": "*" + "node": ">=6" } }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/eslint-plugin-jest": { - "version": "29.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.1.0.tgz", - "integrity": "sha512-LabxXbASXVjguqL+kBHTPMf3gUeSqwH4fsrEyHTY/MCs42I/p9+ctg09SJpYiD8eGaIsP6GwYr5xW6xWS9XgZg==", + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/utils": "^8.0.0" - }, + "license": "Apache-2.0", + "optional": true, "engines": { - "node": "^20.12.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^8.0.0", - "eslint": "^8.57.0 || ^9.0.0", - "jest": "*" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - }, - "jest": { - "optional": true - } + "node": ">=8" } }, - "node_modules/eslint-plugin-license-header": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-license-header/-/eslint-plugin-license-header-0.8.0.tgz", - "integrity": "sha512-khTCz6G3JdoQfwrtY4XKl98KW4PpnWUKuFx8v+twIRhJADEyYglMDC0td8It75C1MZ88gcvMusWuUlJsos7gYg==", + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true, "license": "MIT", - "dependencies": { - "requireindex": "^1.2.0" + "engines": { + "node": ">=8" } }, - "node_modules/eslint-plugin-mocha": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-11.2.0.tgz", - "integrity": "sha512-nMdy3tEXZac8AH5Z/9hwUkSfWu8xHf4XqwB5UEQzyTQGKcNlgFeciRAjLjliIKC3dR1Ex/a2/5sqgQzvYRkkkA==", + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", "dev": true, + "license": "MIT" + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.1", - "globals": "^15.14.0" + "dequal": "^2.0.0" }, - "peerDependencies": { - "eslint": ">=9.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/eslint-plugin-mocha/node_modules/globals": { - "version": "15.15.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", - "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", + "node_modules/diff": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "node_modules/discontinuous-range": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", + "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==", + "license": "MIT" + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "@leichtgewicht/ip-codec": "^2.0.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=6" } }, - "node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "dependencies": { + "esutils": "^2.0.2" }, - "funding": { - "url": "https://opencollective.com/eslint" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, "engines": { - "node": ">=10" + "node": ">= 4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", "dev": true, - "license": "ISC", + "license": "BSD-2-Clause", "dependencies": { - "is-glob": "^4.0.3" + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" }, - "engines": { - "node": ">=10.13.0" + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/eslint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" }, "engines": { - "node": "*" + "node": ">= 0.4" } }, - "node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT" + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", "dependencies": { - "acorn": "^8.15.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "safe-buffer": "^5.0.1" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/editions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/editions/-/editions-6.22.0.tgz", + "integrity": "sha512-UgGlf8IW75je7HZjNDpJdCv4cGJWIi6yumFdZ0R7A8/CIhQiWUjyGLCxdHpd8bmyD1gnkfUNK0oeOXqUS2cpfQ==", "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "license": "Artistic-2.0", + "dependencies": { + "version-range": "^4.15.0" }, "engines": { + "ecmascript": ">= es5", "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" } }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } + "license": "MIT" }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "node_modules/electron-to-chromium": { + "version": "1.5.286", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", + "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" + "license": "ISC" + }, + "node_modules/embla-carousel": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz", + "integrity": "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==", + "license": "MIT" + }, + "node_modules/embla-carousel-autoplay": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel-autoplay/-/embla-carousel-autoplay-8.6.0.tgz", + "integrity": "sha512-OBu5G3nwaSXkZCo1A6LTaFMZ8EpkYbwIaH+bPqdBnDGQ2fh4+NbzjXjs2SktoPNKCtflfVMc75njaDHOYXcrsA==", + "license": "MIT", + "peerDependencies": { + "embla-carousel": "8.6.0" } }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" + "node_modules/embla-carousel-fade": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel-fade/-/embla-carousel-fade-8.6.0.tgz", + "integrity": "sha512-qaYsx5mwCz72ZrjlsXgs1nKejSrW+UhkbOMwLgfRT7w2LtdEB03nPRI06GHuHv5ac2USvbEiX2/nAHctcDwvpg==", + "license": "MIT", + "peerDependencies": { + "embla-carousel": "8.6.0" } }, - "node_modules/estree-util-is-identifier-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", - "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, "license": "MIT", + "engines": { + "node": ">=12" + }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "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": "BSD-2-Clause", + "license": "MIT" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 4" } }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "node_modules/encoding-sniffer": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", + "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.8.x" + "dependencies": { + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" + }, + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" } }, - "node_modules/events-universal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", - "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "optional": true, "dependencies": { - "bare-events": "^2.7.0" + "once": "^1.4.0" } }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "node_modules/enhanced-resolve": { + "version": "5.19.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz", + "integrity": "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==", "dev": true, "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" + "graceful-fs": "^4.2.4", + "tapable": "^2.3.0" }, "engines": { - "node": ">=10" + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" }, "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/exit-x": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz", - "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==", + "node_modules/envinfo": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.20.0.tgz", + "integrity": "sha512-+zUomDcLXsVkQ37vUqWBvQwLaLlj8eZPSi61llaEFAVBY5mhcXdaSw1pSJVl4yTYD5g/gEfpNl28YYk4IPvrrg==", "dev": true, "license": "MIT", + "bin": { + "envinfo": "dist/cli.js" + }, "engines": { - "node": ">= 0.8.0" + "node": ">=4" } }, - "node_modules/expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", "dev": true, - "license": "(MIT OR WTFPL)", - "optional": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/expect": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", - "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/expect-utils": "30.2.0", - "@jest/get-type": "30.1.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", - "jest-util": "30.2.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "is-arrayish": "^0.2.1" } }, - "node_modules/express": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", "dev": true, "license": "MIT", "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "~1.20.3", - "content-disposition": "~0.5.4", - "content-type": "~1.0.4", - "cookie": "~0.7.1", - "cookie-signature": "~1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.3.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "~0.1.12", - "proxy-addr": "~2.0.7", - "qs": "~6.14.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "~0.19.0", - "serve-static": "~1.16.2", - "setprototypeof": "1.2.0", - "statuses": "~2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" + "stackframe": "^1.3.4" + } + }, + "node_modules/es-abstract": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" }, "engines": { - "node": ">= 0.10.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, "license": "MIT", - "dependencies": { - "ms": "2.0.0" + "engines": { + "node": ">= 0.4" } }, - "node_modules/express/node_modules/ms": { + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", "dev": true, "license": "MIT" }, - "node_modules/ext-list": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", - "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "dev": true, "license": "MIT", "dependencies": { - "mime-db": "^1.28.0" + "es-errors": "^1.3.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, - "node_modules/ext-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", - "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "dev": true, "license": "MIT", "dependencies": { - "ext-list": "^2.0.0", - "sort-keys-length": "^1.0.0" + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { - "node": ">=4" + "node": ">= 0.4" } }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "license": "MIT" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-fifo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", - "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dev": true, "license": "MIT", "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" }, "engines": { - "node": ">=8.6.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" + "node_modules/es-toolkit": { + "version": "1.42.0", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.42.0.tgz", + "integrity": "sha512-SLHIyY7VfDJBM8clz4+T2oquwTQxEzu263AyhVK4jREOAwJ+8eebaa4wM3nlvnAqhDrMm2EsA6hWHaQsMPQ1nA==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 4.9.1" + "node": ">=6" } }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } + "license": "MIT" }, - "node_modules/faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "websocket-driver": ">=0.5.1" - }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "license": "MIT", "engines": { - "node": ">=0.8.0" + "node": ">=8" } }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "node_modules/eslint": { + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", + "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "bser": "2.1.1" + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.1", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, "license": "MIT", "dependencies": { - "pend": "~1.2.0" + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, - "node_modules/fflate": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", - "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", - "license": "MIT" - }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" + "ms": "^2.1.1" } }, - "node_modules/file-type": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-20.5.0.tgz", - "integrity": "sha512-BfHZtG/l9iMm4Ecianu7P8HRD2tBHLtjXinm4X62XBOYzi7CYA7jyqfJzOvXHqzVrVPYqBo2/GvbARMaaJkKVg==", + "node_modules/eslint-module-utils": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", "dev": true, "license": "MIT", "dependencies": { - "@tokenizer/inflate": "^0.2.6", - "strtok3": "^10.2.0", - "token-types": "^6.0.0", - "uint8array-extras": "^1.4.0" + "debug": "^3.2.7" }, "engines": { - "node": ">=18" + "node": ">=4" }, - "funding": { - "url": "https://github.com/sindresorhus/file-type?sponsor=1" + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, - "node_modules/filename-reserved-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-3.0.0.tgz", - "integrity": "sha512-hn4cQfU6GOT/7cFHXBqeBg2TbrMBgdD0kcjLhvSQYYwm3s4B6cjvBfb7nBALJLAXqmU5xajSa7X2NnUud/VCdw==", + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "ms": "^2.1.1" } }, - "node_modules/filenamify": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-6.0.0.tgz", - "integrity": "sha512-vqIlNogKeyD3yzrm0yhRMQg8hOVwYcYRfjEoODd49iCprMn4HL85gK3HcykQE53EPIpX3HcAbGA5ELQv216dAQ==", + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", "dependencies": { - "filename-reserved-regex": "^3.0.0" + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" }, "engines": { - "node": ">=16" + "node": ">=4" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "license": "MIT", "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" + "ms": "^2.1.1" } }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "ms": "2.0.0" + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, - "license": "MIT" - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/find-versions": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-5.1.0.tgz", - "integrity": "sha512-+iwzCJ7C5v5KgcBuueqVoNiHVoQpwiUK5XFLjf0affFTep+Wcw93tPvmb8tqujDNmzhBDPddnWV/qgWSXgq+Hg==", + "node_modules/eslint-plugin-jest": { + "version": "29.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.1.0.tgz", + "integrity": "sha512-LabxXbASXVjguqL+kBHTPMf3gUeSqwH4fsrEyHTY/MCs42I/p9+ctg09SJpYiD8eGaIsP6GwYr5xW6xWS9XgZg==", "dev": true, "license": "MIT", "dependencies": { - "semver-regex": "^4.0.5" + "@typescript-eslint/utils": "^8.0.0" }, "engines": { - "node": ">=12" + "node": "^20.12.0 || ^22.0.0 || >=24.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "license": "BSD-3-Clause", - "bin": { - "flat": "cli.js" + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", + "jest": "*" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } } }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "node_modules/eslint-plugin-license-header": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-license-header/-/eslint-plugin-license-header-0.8.0.tgz", + "integrity": "sha512-khTCz6G3JdoQfwrtY4XKl98KW4PpnWUKuFx8v+twIRhJADEyYglMDC0td8It75C1MZ88gcvMusWuUlJsos7gYg==", "dev": true, "license": "MIT", "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" + "requireindex": "^1.2.0" } }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "dev": true, - "license": "ISC" - }, - "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "node_modules/eslint-plugin-mocha": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-11.2.0.tgz", + "integrity": "sha512-nMdy3tEXZac8AH5Z/9hwUkSfWu8xHf4XqwB5UEQzyTQGKcNlgFeciRAjLjliIKC3dR1Ex/a2/5sqgQzvYRkkkA==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], "license": "MIT", - "engines": { - "node": ">=4.0" + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.1", + "globals": "^15.14.0" }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } + "peerDependencies": { + "eslint": ">=9.0.0" } }, - "node_modules/for-each": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", - "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "node_modules/eslint-plugin-mocha/node_modules/globals": { + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", "dev": true, "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7" - }, "engines": { - "node": ">= 0.4" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, - "license": "ISC", + "license": "BSD-2-Clause", "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">=14" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://opencollective.com/eslint" } }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, - "license": "ISC", + "license": "Apache-2.0", "engines": { - "node": ">=14" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://opencollective.com/eslint" } }, - "node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "engines": { - "node": ">= 6" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/form-data-encoder": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", - "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 14.17" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, "engines": { - "node": ">= 0.6" + "node": ">=10.13.0" } }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, - "license": "MIT", - "optional": true + "license": "MIT" }, - "node_modules/fs-extra": { - "version": "11.3.2", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.2.tgz", - "integrity": "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==", + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=14.14" + "node": "*" } }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" } }, - "node_modules/function.prototype.name": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", - "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "functions-have-names": "^1.2.3", - "hasown": "^2.0.2", - "is-callable": "^1.2.7" + "estraverse": "^5.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=4.0" } }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", "license": "MIT", "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/generator-function": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", - "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "engines": { - "node": ">= 0.4" + "node": ">=0.10.0" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "dev": true, "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": ">= 0.6" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "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": "ISC", + "license": "MIT", "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">=0.8.x" } }, - "node_modules/get-east-asian-width": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", - "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.7.0" } }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", "dev": true, - "license": "MIT", "engines": { - "node": ">=8.0.0" + "node": ">= 0.8.0" } }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "node_modules/exit-x": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz", + "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==", "dev": true, "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, "engines": { - "node": ">= 0.4" + "node": ">= 0.8.0" } }, - "node_modules/get-stdin": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", - "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", "dev": true, - "license": "MIT", + "license": "(MIT OR WTFPL)", + "optional": true, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "node_modules/expect": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", + "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "@jest/expect-utils": "30.2.0", + "@jest/get-type": "30.1.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-util": "30.2.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/get-symbol-description": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", - "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", - "dev": true, - "license": "MIT", + "node_modules/express": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", + "dev": true, + "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6" + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.14.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" }, "engines": { - "node": ">= 0.4" + "node": ">= 0.10.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "license": "MIT", - "optional": true + "dependencies": { + "ms": "2.0.0" + } }, - "node_modules/glob": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-12.0.0.tgz", - "integrity": "sha512-5Qcll1z7IKgHr5g485ePDdHcNQY0k2dtv/bjYy0iuyGxQw2qSOiiXUXJ+AYQpg3HNoUMHqAruX478Jeev7UULw==", + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT" + }, + "node_modules/ext-list": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", + "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", + "dev": true, + "license": "MIT", "dependencies": { - "foreground-child": "^3.3.1", - "jackspeak": "^4.1.1", - "minimatch": "^10.1.1", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^2.0.0" - }, - "bin": { - "glob": "dist/esm/bin.mjs" + "mime-db": "^1.28.0" }, "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=0.10.0" } }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/ext-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", + "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "is-glob": "^4.0.1" + "ext-list": "^2.0.0", + "sort-keys-length": "^1.0.0" }, "engines": { - "node": ">= 6" + "node": ">=4" } }, - "node_modules/glob-to-regex.js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/glob-to-regex.js/-/glob-to-regex.js-1.2.0.tgz", - "integrity": "sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==", + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } + "license": "MIT" }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", "dev": true, - "license": "BSD-2-Clause" + "license": "MIT" }, - "node_modules/glob/node_modules/minimatch": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", - "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", "dependencies": { - "@isaacs/brace-expansion": "^5.0.0" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" }, "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=8.6.0" } }, - "node_modules/globals": { - "version": "16.5.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", - "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 4.9.1" } }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "reusify": "^1.0.4" } }, - "node_modules/globby": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", - "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.3", - "ignore": "^7.0.3", - "path-type": "^6.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.3.0" + "websocket-driver": ">=0.5.1" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.8.0" } }, - "node_modules/globby/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" } }, - "node_modules/globby/node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", "dev": true, "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "pend": "~1.2.0" } }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "license": "MIT" }, - "node_modules/got": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/got/-/got-13.0.0.tgz", - "integrity": "sha512-XfBk1CxOOScDcMr9O1yKkNaQyy865NbYs+F7dr4H0LZMVgCj2Le59k6PqbNHoL5ToeaEQUYh6c6yMfVcc6SJxA==", + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "license": "MIT", "dependencies": { - "@sindresorhus/is": "^5.2.0", - "@szmarczak/http-timer": "^5.0.1", - "cacheable-lookup": "^7.0.0", - "cacheable-request": "^10.2.8", - "decompress-response": "^6.0.0", - "form-data-encoder": "^2.1.2", - "get-stream": "^6.0.1", - "http2-wrapper": "^2.1.10", - "lowercase-keys": "^3.0.0", - "p-cancelable": "^3.0.0", - "responselike": "^3.0.0" + "flat-cache": "^4.0.0" }, "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" + "node": ">=16.0.0" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, - "node_modules/handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true, - "license": "MIT" - }, - "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "node_modules/file-type": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-20.5.0.tgz", + "integrity": "sha512-BfHZtG/l9iMm4Ecianu7P8HRD2tBHLtjXinm4X62XBOYzi7CYA7jyqfJzOvXHqzVrVPYqBo2/GvbARMaaJkKVg==", "dev": true, "license": "MIT", "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" + "@tokenizer/inflate": "^0.2.6", + "strtok3": "^10.2.0", + "token-types": "^6.0.0", + "uint8array-extras": "^1.4.0" }, "engines": { - "node": ">=0.4.7" + "node": ">=18" }, - "optionalDependencies": { - "uglify-js": "^3.1.4" + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" } }, - "node_modules/handlebars/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/filename-reserved-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-3.0.0.tgz", + "integrity": "sha512-hn4cQfU6GOT/7cFHXBqeBg2TbrMBgdD0kcjLhvSQYYwm3s4B6cjvBfb7nBALJLAXqmU5xajSa7X2NnUud/VCdw==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/has-bigints": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", - "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "node_modules/filenamify": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-6.0.0.tgz", + "integrity": "sha512-vqIlNogKeyD3yzrm0yhRMQg8hOVwYcYRfjEoODd49iCprMn4HL85gK3HcykQE53EPIpX3HcAbGA5ELQv216dAQ==", "dev": true, "license": "MIT", + "dependencies": { + "filename-reserved-regex": "^3.0.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=16" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, "engines": { "node": ">=8" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dev": true, "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0" + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.8" } }, - "node_modules/has-proto": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", - "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "license": "MIT", "dependencies": { - "dunder-proto": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "ms": "2.0.0" } }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "node_modules/find-versions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-5.1.0.tgz", + "integrity": "sha512-+iwzCJ7C5v5KgcBuueqVoNiHVoQpwiUK5XFLjf0affFTep+Wcw93tPvmb8tqujDNmzhBDPddnWV/qgWSXgq+Hg==", "dev": true, "license": "MIT", "dependencies": { - "has-symbols": "^1.0.3" + "semver-regex": "^4.0.5" }, "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", "dependencies": { - "function-bind": "^1.1.2" + "flatted": "^3.2.9", + "keyv": "^4.5.4" }, "engines": { - "node": ">= 0.4" + "node": ">=16" } }, - "node_modules/hast-util-to-jsx-runtime": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", - "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "hast-util-whitespace": "^3.0.0", - "mdast-util-mdx-expression": "^2.0.0", - "mdast-util-mdx-jsx": "^3.0.0", - "mdast-util-mdxjs-esm": "^2.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0", - "style-to-js": "^1.0.0", - "unist-util-position": "^5.0.0", - "vfile-message": "^4.0.0" + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "peerDependenciesMeta": { + "debug": { + "optional": true + } } }, - "node_modules/hast-util-whitespace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", - "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, "license": "MIT", "dependencies": { - "@types/hast": "^3.0.0" + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "license": "MIT", - "bin": { - "he": "bin/he" + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/hosted-git-info": { + "node_modules/foreground-child/node_modules/signal-exit": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, "engines": { - "node": ">=10" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "dev": true, "license": "MIT", "dependencies": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/html-entities": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", - "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", + "node_modules/form-data-encoder": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", + "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/mdevils" - }, - { - "type": "patreon", - "url": "https://patreon.com/mdevils" - } - ], - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">= 14.17" + } }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">= 0.6" + } }, - "node_modules/html-to-text": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-8.2.1.tgz", - "integrity": "sha512-aN/3JvAk8qFsWVeE9InWAWueLXrbkoVZy0TkzaGhoRBC2gCFEeRLDDJN3/ijIGHohy6H+SZzUQWN/hcYtaPK8w==", + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, "license": "MIT", - "dependencies": { - "@selderee/plugin-htmlparser2": "^0.6.0", - "deepmerge": "^4.2.2", - "he": "^1.2.0", - "htmlparser2": "^6.1.0", - "minimist": "^1.2.6", - "selderee": "^0.6.0" - }, - "bin": { - "html-to-text": "bin/cli.js" - }, "engines": { - "node": ">=10.23.2" + "node": ">= 0.6" } }, - "node_modules/html-to-text/node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/fs-extra": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.2.tgz", + "integrity": "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==", + "dev": true, "license": "MIT", "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + "engines": { + "node": ">=14.14" } }, - "node_modules/html-to-text/node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^2.2.0" - }, + "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", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">= 4" - }, + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/html-to-text/node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "license": "BSD-2-Clause", + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "license": "MIT", "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/html-to-text/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "license": "BSD-2-Clause", + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/html-to-text/node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, "license": "MIT", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" + "engines": { + "node": ">= 0.4" } }, - "node_modules/html-url-attributes": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz", - "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==", + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/htmlparser2": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz", - "integrity": "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==", + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "MIT", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.2.1", - "entities": "^6.0.0" + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/htmlparser2/node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "node_modules/get-east-asian-width": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", + "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "engines": { - "node": ">=0.12" + "node": ">=18" }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/http-cache-semantics": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", - "dev": true, - "license": "MIT" - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, "license": "MIT", "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/http-parser-js": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz", - "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==", - "dev": true, - "license": "MIT" - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, "license": "MIT", - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, "engines": { "node": ">=8.0.0" } }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">= 14" + "node": ">= 0.4" } }, - "node_modules/http-proxy-middleware": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz", - "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==", + "node_modules/get-stdin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", + "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", "dev": true, "license": "MIT", - "dependencies": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - }, "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@types/express": "^4.17.13" - }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } + "node": ">=8" } }, - "node_modules/http-proxy-middleware/node_modules/is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, "license": "MIT", "engines": { @@ -12755,335 +13013,281 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/http-proxy/node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true, - "license": "MIT" - }, - "node_modules/http2-wrapper": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", - "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, "license": "MIT", "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.2.0" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" }, "engines": { - "node": ">=10.19.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true, "license": "MIT", + "optional": true + }, + "node_modules/glob": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-12.0.0.tgz", + "integrity": "sha512-5Qcll1z7IKgHr5g485ePDdHcNQY0k2dtv/bjYy0iuyGxQw2qSOiiXUXJ+AYQpg3HNoUMHqAruX478Jeev7UULw==", + "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">= 14" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "license": "Apache-2.0", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, "engines": { - "node": ">=10.17.0" + "node": ">= 6" } }, - "node_modules/hyperdyperid": { + "node_modules/glob-to-regex.js": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", - "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", + "resolved": "https://registry.npmjs.org/glob-to-regex.js/-/glob-to-regex.js-1.2.0.tgz", + "integrity": "sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": ">=10.18" + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" } }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause" + }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "@isaacs/brace-expansion": "^5.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "node_modules/globals": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", "dev": true, - "license": "ISC", + "license": "MIT", "engines": { - "node": "^10 || ^12 || >= 14" + "node": ">=18" }, - "peerDependencies": { - "postcss": "^8.1.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, "engines": { - "node": ">= 4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/immutable": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz", - "integrity": "sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==", - "dev": true, - "license": "MIT" - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "node_modules/globby": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", + "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", "dev": true, "license": "MIT", "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.3", + "path-type": "^6.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.3.0" }, "engines": { - "node": ">=6" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/import-local": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "node_modules/globby/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, "license": "MIT", - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, "engines": { - "node": ">=8" + "node": ">= 4" + } + }, + "node_modules/globby/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.8.19" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/index-to-position": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.2.0.tgz", - "integrity": "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==", + "node_modules/got": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/got/-/got-13.0.0.tgz", + "integrity": "sha512-XfBk1CxOOScDcMr9O1yKkNaQyy865NbYs+F7dr4H0LZMVgCj2Le59k6PqbNHoL5ToeaEQUYh6c6yMfVcc6SJxA==", "dev": true, "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^5.2.0", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^10.2.8", + "decompress-response": "^6.0.0", + "form-data-encoder": "^2.1.2", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^3.0.0" + }, "engines": { - "node": ">=18" + "node": ">=16" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sindresorhus/got?sponsor=1" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true, "license": "ISC" }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true, - "license": "ISC", - "optional": true - }, - "node_modules/inline-style-parser": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", - "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", "license": "MIT" }, - "node_modules/inspect-with-kind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/inspect-with-kind/-/inspect-with-kind-1.0.5.tgz", - "integrity": "sha512-MAQUJuIo7Xqk8EVNP+6d3CKq9c80hi4tjIbIAT6lmGW9W6WzlHiu9PS8uSuUYU+Do+j1baiFp3H25XEVxDIG2g==", + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", "dev": true, - "license": "ISC", - "dependencies": { - "kind-of": "^6.0.2" - } + "license": "MIT" }, - "node_modules/internal-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", - "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/interpret": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", - "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/ipaddr.js": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", - "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/is-alphabetical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", - "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-alphanumerical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", - "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", - "license": "MIT", - "dependencies": { - "is-alphabetical": "^2.0.0", - "is-decimal": "^2.0.0" + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", - "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" + "bin": { + "handlebars": "bin/handlebars" }, "engines": { - "node": ">= 0.4" + "node": ">=0.4.7" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "optionalDependencies": { + "uglify-js": "^3.1.4" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-async-function": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", - "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "license": "MIT", - "dependencies": { - "async-function": "^1.0.0", - "call-bound": "^1.0.3", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, + "license": "BSD-3-Clause", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/is-bigint": { + "node_modules/has-bigints": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", - "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", "dev": true, "license": "MIT", - "dependencies": { - "has-bigints": "^1.0.2" - }, "engines": { "node": ">= 0.4" }, @@ -13091,49 +13295,38 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, "engines": { "node": ">=8" } }, - "node_modules/is-boolean-object": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", - "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", "dev": true, "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -13141,15 +13334,12 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, "engines": { "node": ">= 0.4" }, @@ -13157,16 +13347,14 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-data-view": { + "node_modules/has-tostringtag": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", - "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "is-typed-array": "^1.1.13" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -13175,2453 +13363,4123 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-date-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", - "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" + "function-bind": "^1.1.2" }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-decimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", - "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/is-docker": { + "node_modules/hast-util-whitespace": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", "license": "MIT", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "dependencies": { + "@types/hast": "^3.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "license": "MIT", - "engines": { - "node": ">=0.10.0" + "bin": { + "he": "bin/he" } }, - "node_modules/is-finalizationregistry": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", - "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "call-bound": "^1.0.3" + "lru-cache": "^6.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" } }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "node_modules/html-entities": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", + "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT" }, - "node_modules/is-generator-function": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", - "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true, + "license": "MIT" + }, + "node_modules/html-to-text": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-8.2.1.tgz", + "integrity": "sha512-aN/3JvAk8qFsWVeE9InWAWueLXrbkoVZy0TkzaGhoRBC2gCFEeRLDDJN3/ijIGHohy6H+SZzUQWN/hcYtaPK8w==", "license": "MIT", "dependencies": { - "call-bound": "^1.0.4", - "generator-function": "^2.0.0", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" + "@selderee/plugin-htmlparser2": "^0.6.0", + "deepmerge": "^4.2.2", + "he": "^1.2.0", + "htmlparser2": "^6.1.0", + "minimist": "^1.2.6", + "selderee": "^0.6.0" }, - "engines": { - "node": ">= 0.4" + "bin": { + "html-to-text": "bin/cli.js" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=10.23.2" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, + "node_modules/html-to-text/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", "license": "MIT", "dependencies": { - "is-extglob": "^2.1.1" + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-hexadecimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", - "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", - "license": "MIT", "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "license": "MIT", + "node_modules/html-to-text/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "license": "BSD-2-Clause", "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" + "domelementtype": "^2.2.0" }, "engines": { - "node": ">=14.16" + "node": ">= 4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/is-interactive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", - "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" + "node_modules/html-to-text/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, + "node_modules/html-to-text/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "license": "BSD-2-Clause", "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "dev": true, + "node_modules/html-to-text/node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" } }, - "node_modules/is-network-error": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.0.tgz", - "integrity": "sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==", - "dev": true, + "node_modules/html-url-attributes": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz", + "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==", "license": "MIT", - "engines": { - "node": ">=16" - }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/htmlparser2": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz", + "integrity": "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==", "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], "license": "MIT", - "engines": { - "node": ">=0.12.0" + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.1", + "entities": "^6.0.0" } }, - "node_modules/is-number-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", - "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "node_modules/htmlparser2/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, + "license": "BSD-2-Clause", "engines": { - "node": ">= 0.4" + "node": ">=0.12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } + "license": "BSD-2-Clause" }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dev": true, "license": "MIT", "dependencies": { - "isobject": "^3.0.1" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, - "node_modules/is-regex": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "node_modules/http-parser-js": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz", + "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8.0.0" } }, - "node_modules/is-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", - "dev": true, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "license": "MIT", - "engines": { - "node": ">= 0.4" + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 14" } }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", - "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "node_modules/http-proxy-middleware": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz", + "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3" + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" }, "engines": { - "node": ">= 0.4" + "node": ">=12.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/http-proxy-middleware/node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-string": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", - "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "node_modules/http-proxy/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "license": "MIT" }, - "node_modules/is-symbol": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", - "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "node_modules/http2-wrapper": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", + "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "has-symbols": "^1.1.0", - "safe-regex-test": "^1.1.0" + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.2.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10.19.0" } }, - "node_modules/is-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", - "dev": true, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "license": "MIT", "dependencies": { - "which-typed-array": "^1.1.16" + "agent-base": "^7.1.2", + "debug": "4" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 14" } }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10.17.0" } }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "node_modules/hyperdyperid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", + "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10.18" } }, - "node_modules/is-weakref": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", - "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/is-weakset": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", - "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, + "license": "ISC", "engines": { - "node": ">= 0.4" + "node": "^10 || ^12 || >= 14" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "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", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, "license": "MIT", - "dependencies": { - "is-inside-container": "^1.0.0" - }, "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 4" } }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", "dev": true, "license": "MIT" }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "node_modules/immutable": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz", + "integrity": "sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==", "dev": true, - "license": "ISC" + "license": "MIT" }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", - "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=0.8.19" } }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "node_modules/index-to-position": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.2.0.tgz", + "integrity": "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "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": "MIT", + "license": "ISC", "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/istanbul-lib-source-maps": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", - "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true, - "license": "BSD-3-Clause", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/inline-style-parser": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", + "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", + "license": "MIT" + }, + "node_modules/inspect-with-kind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/inspect-with-kind/-/inspect-with-kind-1.0.5.tgz", + "integrity": "sha512-MAQUJuIo7Xqk8EVNP+6d3CKq9c80hi4tjIbIAT6lmGW9W6WzlHiu9PS8uSuUYU+Do+j1baiFp3H25XEVxDIG2g==", + "dev": true, + "license": "ISC", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.23", - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0" - }, - "engines": { - "node": ">=10" + "kind-of": "^6.0.2" } }, - "node_modules/istanbul-reports": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", - "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/istextorbinary": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-9.5.0.tgz", - "integrity": "sha512-5mbUj3SiZXCuRf9fT3ibzbSSEWiy63gFfksmGfdOzujPjW3k+z8WvIBxcJHBoQNlaZaiyB25deviif2+osLmLw==", + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", "dev": true, - "license": "Artistic-2.0", - "dependencies": { - "binaryextensions": "^6.11.0", - "editions": "^6.21.0", - "textextensions": "^6.11.0" - }, + "license": "MIT", "engines": { - "node": ">=4" - }, - "funding": { - "url": "https://bevry.me/fund" + "node": ">=10.13.0" } }, - "node_modules/jackspeak": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", - "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", + "node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, + "license": "MIT", "engines": { - "node": "20 || >=22" - }, + "node": ">= 10" + } + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "license": "MIT", "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/jest": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-30.2.0.tgz", - "integrity": "sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==", - "dev": true, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", "license": "MIT", "dependencies": { - "@jest/core": "30.2.0", - "@jest/types": "30.2.0", - "import-local": "^3.2.0", - "jest-cli": "30.2.0" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/jest-changed-files": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.2.0.tgz", - "integrity": "sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ==", + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dev": true, "license": "MIT", "dependencies": { - "execa": "^5.1.1", - "jest-util": "30.2.0", - "p-limit": "^3.1.0" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-circus": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.2.0.tgz", - "integrity": "sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg==", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "30.2.0", - "@jest/expect": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/types": "30.2.0", - "@types/node": "*", - "chalk": "^4.1.2", - "co": "^4.6.0", - "dedent": "^1.6.0", - "is-generator-fn": "^2.1.0", - "jest-each": "30.2.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-runtime": "30.2.0", - "jest-snapshot": "30.2.0", - "jest-util": "30.2.0", - "p-limit": "^3.1.0", - "pretty-format": "30.2.0", - "pure-rand": "^7.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.6" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } + "license": "MIT" }, - "node_modules/jest-cli": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.2.0.tgz", - "integrity": "sha512-Os9ukIvADX/A9sLt6Zse3+nmHtHaE6hqOsjQtNiugFTbKRHYIYtZXNGNK9NChseXy7djFPjndX1tL0sCTlfpAA==", + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/core": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/types": "30.2.0", - "chalk": "^4.1.2", - "exit-x": "^0.2.2", - "import-local": "^3.2.0", - "jest-config": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", - "yargs": "^17.7.2" - }, - "bin": { - "jest": "bin/jest.js" + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-config": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.2.0.tgz", - "integrity": "sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA==", + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.27.4", - "@jest/get-type": "30.1.0", - "@jest/pattern": "30.0.1", - "@jest/test-sequencer": "30.2.0", - "@jest/types": "30.2.0", - "babel-jest": "30.2.0", - "chalk": "^4.1.2", - "ci-info": "^4.2.0", - "deepmerge": "^4.3.1", - "glob": "^10.3.10", - "graceful-fs": "^4.2.11", - "jest-circus": "30.2.0", - "jest-docblock": "30.2.0", - "jest-environment-node": "30.2.0", - "jest-regex-util": "30.0.1", - "jest-resolve": "30.2.0", - "jest-runner": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", - "micromatch": "^4.0.8", - "parse-json": "^5.2.0", - "pretty-format": "30.2.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" + "has-bigints": "^1.0.2" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "esbuild-register": ">=3.4.0", - "ts-node": ">=9.0.0" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "esbuild-register": { - "optional": true - }, - "ts-node": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-diff": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", - "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/diff-sequences": "30.0.1", - "@jest/get-type": "30.1.0", - "chalk": "^4.1.2", - "pretty-format": "30.2.0" + "binary-extensions": "^2.0.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=8" } }, - "node_modules/jest-docblock": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.2.0.tgz", - "integrity": "sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==", + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", "dev": true, "license": "MIT", "dependencies": { - "detect-newline": "^3.1.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-each": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.2.0.tgz", - "integrity": "sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ==", + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/get-type": "30.1.0", - "@jest/types": "30.2.0", - "chalk": "^4.1.2", - "jest-util": "30.2.0", - "pretty-format": "30.2.0" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-environment-node": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.2.0.tgz", - "integrity": "sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA==", + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/fake-timers": "30.2.0", - "@jest/types": "30.2.0", - "@types/node": "*", - "jest-mock": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0" + "hasown": "^2.0.2" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-haste-map": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.2.0.tgz", - "integrity": "sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==", + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", - "@types/node": "*", - "anymatch": "^3.1.3", - "fb-watchman": "^2.0.2", - "graceful-fs": "^4.2.11", - "jest-regex-util": "30.0.1", - "jest-util": "30.2.0", - "jest-worker": "30.2.0", - "micromatch": "^4.0.8", - "walker": "^1.0.8" + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" }, - "optionalDependencies": { - "fsevents": "^2.3.3" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-leak-detector": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.2.0.tgz", - "integrity": "sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ==", + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/get-type": "30.1.0", - "pretty-format": "30.2.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-matcher-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", - "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", - "dev": true, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", "license": "MIT", - "dependencies": { - "@jest/get-type": "30.1.0", - "chalk": "^4.1.2", - "jest-diff": "30.2.0", - "pretty-format": "30.2.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", - "dev": true, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", - "@types/stack-utils": "^2.0.3", - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.6" + "bin": { + "is-docker": "cli.js" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-mock": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", - "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/types": "30.2.0", - "@types/node": "*", - "jest-util": "30.2.0" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-mock-vscode": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/jest-mock-vscode/-/jest-mock-vscode-4.0.5.tgz", - "integrity": "sha512-XLK3mZjKLAUpERm9p5j0nbDlTTYGUxvZLOFFCv5iM2dmi8LUszhlKGzYYnR9rvvbx3UYRRj+yuzK3Q0jK6s1jg==", + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", "dev": true, "license": "MIT", "dependencies": { - "vscode-uri": "^3.0.8" + "call-bound": "^1.0.3" }, "engines": { - "node": ">20.0.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@types/vscode": "^1.90.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } + "node": ">=8" } }, - "node_modules/jest-regex-util": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", - "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true, "license": "MIT", "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=6" } }, - "node_modules/jest-resolve": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.2.0.tgz", - "integrity": "sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A==", + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "jest-haste-map": "30.2.0", - "jest-pnp-resolver": "^1.2.3", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", - "slash": "^3.0.0", - "unrs-resolver": "^1.7.11" + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-resolve-dependencies": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.2.0.tgz", - "integrity": "sha512-xTOIGug/0RmIe3mmCqCT95yO0vj6JURrn1TKWlNbhiAefJRWINNPgwVkrVgt/YaerPzY3iItufd80v3lOrFJ2w==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "license": "MIT", "dependencies": { - "jest-regex-util": "30.0.1", - "jest-snapshot": "30.2.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-runner": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.2.0.tgz", - "integrity": "sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ==", - "dev": true, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", "license": "MIT", - "dependencies": { - "@jest/console": "30.2.0", - "@jest/environment": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", - "@types/node": "*", - "chalk": "^4.1.2", - "emittery": "^0.13.1", - "exit-x": "^0.2.2", - "graceful-fs": "^4.2.11", - "jest-docblock": "30.2.0", - "jest-environment-node": "30.2.0", - "jest-haste-map": "30.2.0", - "jest-leak-detector": "30.2.0", - "jest-message-util": "30.2.0", - "jest-resolve": "30.2.0", - "jest-runtime": "30.2.0", - "jest-util": "30.2.0", - "jest-watcher": "30.2.0", - "jest-worker": "30.2.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/jest-runtime": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.2.0.tgz", - "integrity": "sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg==", - "dev": true, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", "license": "MIT", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/fake-timers": "30.2.0", - "@jest/globals": "30.2.0", - "@jest/source-map": "30.0.1", - "@jest/test-result": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", - "@types/node": "*", - "chalk": "^4.1.2", - "cjs-module-lexer": "^2.1.0", - "collect-v8-coverage": "^1.0.2", - "glob": "^10.3.10", - "graceful-fs": "^4.2.11", - "jest-haste-map": "30.2.0", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", - "jest-regex-util": "30.0.1", - "jest-resolve": "30.2.0", - "jest-snapshot": "30.2.0", - "jest-util": "30.2.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-snapshot": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.2.0.tgz", - "integrity": "sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA==", + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/core": "^7.27.4", - "@babel/generator": "^7.27.5", - "@babel/plugin-syntax-jsx": "^7.27.1", - "@babel/plugin-syntax-typescript": "^7.27.1", - "@babel/types": "^7.27.3", - "@jest/expect-utils": "30.2.0", - "@jest/get-type": "30.1.0", - "@jest/snapshot-utils": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", - "babel-preset-current-node-syntax": "^1.2.0", - "chalk": "^4.1.2", - "expect": "30.2.0", - "graceful-fs": "^4.2.11", - "jest-diff": "30.2.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-util": "30.2.0", - "pretty-format": "30.2.0", - "semver": "^7.7.2", - "synckit": "^0.11.8" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "30.2.0", - "@types/node": "*", - "chalk": "^4.1.2", - "ci-info": "^4.2.0", - "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-util/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true, "license": "MIT", "engines": { - "node": ">=12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-validate": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.2.0.tgz", - "integrity": "sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw==", + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/get-type": "30.1.0", - "@jest/types": "30.2.0", - "camelcase": "^6.3.0", - "chalk": "^4.1.2", - "leven": "^3.1.0", - "pretty-format": "30.2.0" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "node_modules/is-network-error": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.0.tgz", + "integrity": "sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-watcher": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.2.0.tgz", - "integrity": "sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/test-result": "30.2.0", - "@jest/types": "30.2.0", - "@types/node": "*", - "ansi-escapes": "^4.3.2", - "chalk": "^4.1.2", - "emittery": "^0.13.1", - "jest-util": "30.2.0", - "string-length": "^4.0.2" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=0.12.0" } }, - "node_modules/jest-worker": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.2.0.tgz", - "integrity": "sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g==", + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*", - "@ungap/structured-clone": "^1.3.0", - "jest-util": "30.2.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.1.1" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=8" } }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "license": "MIT", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "isobject": "^3.0.1" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, "license": "MIT", - "bin": { - "json5": "lib/cli.js" + "dependencies": { + "call-bound": "^1.0.3" }, "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "license": "MIT" - }, - "node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" + "engines": { + "node": ">=8" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, "license": "MIT", "dependencies": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^7.5.4" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": ">=12", - "npm": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jszip": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", - "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "dev": true, - "license": "(MIT OR GPL-3.0-or-later)", - "dependencies": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "setimmediate": "^1.0.5" - } - }, - "node_modules/jwa": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", - "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", - "license": "MIT", - "dependencies": { - "buffer-equal-constant-time": "^1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.3.tgz", - "integrity": "sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g==", "license": "MIT", "dependencies": { - "jwa": "^1.4.2", - "safe-buffer": "^5.0.1" + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/keyborg": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/keyborg/-/keyborg-2.6.0.tgz", - "integrity": "sha512-o5kvLbuTF+o326CMVYpjlaykxqYP9DphFQZ2ZpgrvBouyvOxyEB7oqe8nOLFpiV5VCtz0D3pt8gXQYWpLpBnmA==", - "license": "MIT" - }, - "node_modules/keytar": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz", - "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==", + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, - "hasInstallScript": true, "license": "MIT", - "optional": true, "dependencies": { - "node-addon-api": "^4.3.0", - "prebuild-install": "^7.0.1" + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/launch-editor": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.12.0.tgz", - "integrity": "sha512-giOHXoOtifjdHqUamwKq6c49GzBdLjvxrd2D+Q4V6uOHopJv7p9VJxikDsQ/CBXZbEITgUqSVHXLTG3VhPP1Dg==", + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", "dev": true, "license": "MIT", "dependencies": { - "picocolors": "^1.1.1", - "shell-quote": "^1.8.3" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "license": "MIT", + "call-bound": "^1.0.3" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", "dev": true, "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/lie": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", - "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", - "dev": true, + "node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", "license": "MIT", "dependencies": { - "immediate": "~3.0.5" + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true, "license": "MIT" }, - "node_modules/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "dev": true, "license": "MIT", - "dependencies": { - "uc.micro": "^2.0.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/loader-runner": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", - "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "engines": { - "node": ">=6.11.5" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=8" } }, - "node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" }, "engines": { - "node": ">=8.9.0" + "node": ">=10" } }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "p-locate": "^5.0.0" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", - "license": "MIT" - }, - "node_modules/lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", - "license": "MIT" - }, - "node_modules/lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", - "license": "MIT" - }, - "node_modules/lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", - "license": "MIT" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "license": "MIT" - }, - "node_modules/lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", - "license": "MIT" - }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "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", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", - "license": "MIT" - }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", - "dev": true, - "license": "MIT" - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/longest-streak": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", - "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/lowercase-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", - "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=8" } }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/istextorbinary": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-9.5.0.tgz", + "integrity": "sha512-5mbUj3SiZXCuRf9fT3ibzbSSEWiy63gFfksmGfdOzujPjW3k+z8WvIBxcJHBoQNlaZaiyB25deviif2+osLmLw==", "dev": true, - "license": "ISC", + "license": "Artistic-2.0", "dependencies": { - "yallist": "^4.0.0" + "binaryextensions": "^6.11.0", + "editions": "^6.21.0", + "textextensions": "^6.11.0" }, "engines": { - "node": ">=10" + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" } }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "node_modules/jackspeak": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", + "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "semver": "^7.5.3" + "@isaacs/cliui": "^8.0.2" }, "engines": { - "node": ">=10" + "node": "20 || >=22" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "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/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "node_modules/jest": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-30.2.0.tgz", + "integrity": "sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "tmpl": "1.0.5" + "@jest/core": "30.2.0", + "@jest/types": "30.2.0", + "import-local": "^3.2.0", + "jest-cli": "30.2.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/markdown-it": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", - "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "node_modules/jest-changed-files": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.2.0.tgz", + "integrity": "sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ==", "dev": true, "license": "MIT", "dependencies": { - "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.0", - "mdurl": "^2.0.0", - "punycode.js": "^2.3.1", - "uc.micro": "^2.1.0" + "execa": "^5.1.1", + "jest-util": "30.2.0", + "p-limit": "^3.1.0" }, - "bin": { - "markdown-it": "bin/markdown-it.mjs" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/markdown-it/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, - "license": "Python-2.0" - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "node_modules/jest-circus": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.2.0.tgz", + "integrity": "sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg==", "dev": true, "license": "MIT", + "dependencies": { + "@jest/environment": "30.2.0", + "@jest/expect": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "co": "^4.6.0", + "dedent": "^1.6.0", + "is-generator-fn": "^2.1.0", + "jest-each": "30.2.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-runtime": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", + "p-limit": "^3.1.0", + "pretty-format": "30.2.0", + "pure-rand": "^7.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, "engines": { - "node": ">= 0.4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/md5": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", - "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "node_modules/jest-cli": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.2.0.tgz", + "integrity": "sha512-Os9ukIvADX/A9sLt6Zse3+nmHtHaE6hqOsjQtNiugFTbKRHYIYtZXNGNK9NChseXy7djFPjndX1tL0sCTlfpAA==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "charenc": "0.0.2", - "crypt": "0.0.2", - "is-buffer": "~1.1.6" - } - }, - "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", - "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark": "^4.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-stringify-position": "^4.0.0" + "@jest/core": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", + "chalk": "^4.1.2", + "exit-x": "^0.2.2", + "import-local": "^3.2.0", + "jest-config": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "yargs": "^17.7.2" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-expression": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", - "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" + "bin": { + "jest": "bin/jest.js" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-jsx": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", - "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "devlop": "^1.1.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "parse-entities": "^4.0.0", - "stringify-entities": "^4.0.0", - "unist-util-stringify-position": "^4.0.0", - "vfile-message": "^4.0.0" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/mdast-util-mdxjs-esm": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", - "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "node_modules/jest-config": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.2.0.tgz", + "integrity": "sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA==", + "dev": true, "license": "MIT", "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" + "@babel/core": "^7.27.4", + "@jest/get-type": "30.1.0", + "@jest/pattern": "30.0.1", + "@jest/test-sequencer": "30.2.0", + "@jest/types": "30.2.0", + "babel-jest": "30.2.0", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "deepmerge": "^4.3.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-circus": "30.2.0", + "jest-docblock": "30.2.0", + "jest-environment-node": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.2.0", + "jest-runner": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "micromatch": "^4.0.8", + "parse-json": "^5.2.0", + "pretty-format": "30.2.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "esbuild-register": ">=3.4.0", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "esbuild-register": { + "optional": true + }, + "ts-node": { + "optional": true + } } }, - "node_modules/mdast-util-phrasing": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", - "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "node_modules/jest-diff": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", + "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "dev": true, "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "unist-util-is": "^6.0.0" + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "pretty-format": "30.2.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/mdast-util-to-hast": { - "version": "13.2.1", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", - "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "node_modules/jest-docblock": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.2.0.tgz", + "integrity": "sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==", + "dev": true, "license": "MIT", "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", - "devlop": "^1.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "trim-lines": "^3.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" + "detect-newline": "^3.1.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/mdast-util-to-markdown": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", - "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "node_modules/jest-each": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.2.0.tgz", + "integrity": "sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ==", + "dev": true, "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" + "@jest/get-type": "30.1.0", + "@jest/types": "30.2.0", + "chalk": "^4.1.2", + "jest-util": "30.2.0", + "pretty-format": "30.2.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/mdast-util-to-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", - "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "node_modules/jest-environment-node": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.2.0.tgz", + "integrity": "sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA==", + "dev": true, "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0" + "@jest/environment": "30.2.0", + "@jest/fake-timers": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-mock": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "dev": true, - "license": "MIT" - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/memfs": { - "version": "4.51.0", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.51.0.tgz", - "integrity": "sha512-4zngfkVM/GpIhC8YazOsM6E8hoB33NP0BCESPOA6z7qaL6umPJNqkO8CNYaLV2FB2MV6H1O3x2luHHOSqppv+A==", + "node_modules/jest-haste-map": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.2.0.tgz", + "integrity": "sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@jsonjoy.com/json-pack": "^1.11.0", - "@jsonjoy.com/util": "^1.9.0", - "glob-to-regex.js": "^1.0.1", - "thingies": "^2.5.0", - "tree-dump": "^1.0.3", - "tslib": "^2.0.0" + "@jest/types": "30.2.0", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.1", + "jest-util": "30.2.0", + "jest-worker": "30.2.0", + "micromatch": "^4.0.8", + "walker": "^1.0.8" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.3" } }, - "node_modules/memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "license": "MIT" - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "node_modules/jest-leak-detector": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.2.0.tgz", + "integrity": "sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ==", "dev": true, "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "@jest/get-type": "30.1.0", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "license": "MIT" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "node_modules/jest-matcher-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", + "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", "dev": true, "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "jest-diff": "30.2.0", + "pretty-format": "30.2.0" + }, "engines": { - "node": ">= 8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "node_modules/jest-message-util": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", + "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", "dev": true, "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.2.0", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.2.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, "engines": { - "node": ">= 0.6" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/micromark": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", - "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/jest-mock": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", + "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", + "dev": true, "license": "MIT", "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-util": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/micromark-core-commonmark": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", - "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/jest-mock-vscode": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/jest-mock-vscode/-/jest-mock-vscode-4.0.5.tgz", + "integrity": "sha512-XLK3mZjKLAUpERm9p5j0nbDlTTYGUxvZLOFFCv5iM2dmi8LUszhlKGzYYnR9rvvbx3UYRRj+yuzK3Q0jK6s1jg==", + "dev": true, "license": "MIT", "dependencies": { - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-destination": "^2.0.0", - "micromark-factory-label": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-title": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-html-tag-name": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "vscode-uri": "^3.0.8" + }, + "engines": { + "node": ">20.0.0" + }, + "peerDependencies": { + "@types/vscode": "^1.90.0" } }, - "node_modules/micromark-factory-destination": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", - "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } } }, - "node_modules/micromark-factory-label": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", - "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", + "dev": true, "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/micromark-factory-space": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", - "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/jest-resolve": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.2.0.tgz", + "integrity": "sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A==", + "dev": true, "license": "MIT", "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-pnp-resolver": "^1.2.3", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "slash": "^3.0.0", + "unrs-resolver": "^1.7.11" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.2.0.tgz", + "integrity": "sha512-xTOIGug/0RmIe3mmCqCT95yO0vj6JURrn1TKWlNbhiAefJRWINNPgwVkrVgt/YaerPzY3iItufd80v3lOrFJ2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "30.0.1", + "jest-snapshot": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-runner": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.2.0.tgz", + "integrity": "sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.2.0", + "@jest/environment": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-docblock": "30.2.0", + "jest-environment-node": "30.2.0", + "jest-haste-map": "30.2.0", + "jest-leak-detector": "30.2.0", + "jest-message-util": "30.2.0", + "jest-resolve": "30.2.0", + "jest-runtime": "30.2.0", + "jest-util": "30.2.0", + "jest-watcher": "30.2.0", + "jest-worker": "30.2.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.2.0.tgz", + "integrity": "sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.2.0", + "@jest/fake-timers": "30.2.0", + "@jest/globals": "30.2.0", + "@jest/source-map": "30.0.1", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "cjs-module-lexer": "^2.1.0", + "collect-v8-coverage": "^1.0.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.2.0.tgz", + "integrity": "sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@babel/generator": "^7.27.5", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1", + "@babel/types": "^7.27.3", + "@jest/expect-utils": "30.2.0", + "@jest/get-type": "30.1.0", + "@jest/snapshot-utils": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "babel-preset-current-node-syntax": "^1.2.0", + "chalk": "^4.1.2", + "expect": "30.2.0", + "graceful-fs": "^4.2.11", + "jest-diff": "30.2.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-util": "30.2.0", + "pretty-format": "30.2.0", + "semver": "^7.7.2", + "synckit": "^0.11.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-util": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", + "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-util/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-validate": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.2.0.tgz", + "integrity": "sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0", + "@jest/types": "30.2.0", + "camelcase": "^6.3.0", + "chalk": "^4.1.2", + "leven": "^3.1.0", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.2.0.tgz", + "integrity": "sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "jest-util": "30.2.0", + "string-length": "^4.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-worker": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.2.0.tgz", + "integrity": "sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.2.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.1.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "license": "MIT" + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "license": "MIT", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dev": true, + "license": "(MIT OR GPL-3.0-or-later)", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/jwa": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.3.tgz", + "integrity": "sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g==", + "license": "MIT", + "dependencies": { + "jwa": "^1.4.2", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/keyborg": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/keyborg/-/keyborg-2.6.0.tgz", + "integrity": "sha512-o5kvLbuTF+o326CMVYpjlaykxqYP9DphFQZ2ZpgrvBouyvOxyEB7oqe8nOLFpiV5VCtz0D3pt8gXQYWpLpBnmA==", + "license": "MIT" + }, + "node_modules/keytar": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz", + "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-addon-api": "^4.3.0", + "prebuild-install": "^7.0.1" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/launch-editor": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.12.0.tgz", + "integrity": "sha512-giOHXoOtifjdHqUamwKq6c49GzBdLjvxrd2D+Q4V6uOHopJv7p9VJxikDsQ/CBXZbEITgUqSVHXLTG3VhPP1Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "picocolors": "^1.1.1", + "shell-quote": "^1.8.3" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/loader-runner": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", + "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "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", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/lowercase-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", + "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "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/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it/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, + "license": "Python-2.0" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/md5": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" + } + }, + "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", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true, + "license": "MIT" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "4.51.0", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.51.0.tgz", + "integrity": "sha512-4zngfkVM/GpIhC8YazOsM6E8hoB33NP0BCESPOA6z7qaL6umPJNqkO8CNYaLV2FB2MV6H1O3x2luHHOSqppv+A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/json-pack": "^1.11.0", + "@jsonjoy.com/util": "^1.9.0", + "glob-to-regex.js": "^1.0.1", + "thingies": "^2.5.0", + "tree-dump": "^1.0.3", + "tslib": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + } + }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "license": "MIT" + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-response": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", + "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true, + "license": "ISC" + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/mocha": { + "version": "11.7.5", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz", + "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==", + "dev": true, + "license": "MIT", + "dependencies": { + "browser-stdout": "^1.3.1", + "chokidar": "^4.0.1", + "debug": "^4.3.5", + "diff": "^7.0.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^10.4.5", + "he": "^1.2.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^9.0.5", + "ms": "^2.1.3", + "picocolors": "^1.1.1", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^9.2.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/mocha-junit-reporter": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-2.2.1.tgz", + "integrity": "sha512-iDn2tlKHn8Vh8o4nCzcUVW4q7iXp7cC4EB78N0cDHIobLymyHNwe0XG8HEHHjc3hJlXm0Vy6zcrxaIhnI2fWmw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "md5": "^2.3.0", + "mkdirp": "^3.0.0", + "strip-ansi": "^6.0.1", + "xml": "^1.0.1" + }, + "peerDependencies": { + "mocha": ">=2.2.5" + } + }, + "node_modules/mocha-junit-reporter/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/mocha-junit-reporter/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/mocha-multi-reporters": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/mocha-multi-reporters/-/mocha-multi-reporters-1.5.1.tgz", + "integrity": "sha512-Yb4QJOaGLIcmB0VY7Wif5AjvLMUFAdV57D2TWEva1Y0kU/3LjKpeRVmlMIfuO1SVbauve459kgtIizADqxMWPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "lodash": "^4.17.15" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "mocha": ">=3.1.2" + } + }, + "node_modules/mocha/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, + "license": "Python-2.0" + }, + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } }, - "node_modules/micromark-factory-title": { + "node_modules/monaco-editor": { + "version": "0.52.2", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz", + "integrity": "sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==", + "license": "MIT" + }, + "node_modules/monaco-editor-webpack-plugin": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-7.1.1.tgz", + "integrity": "sha512-WxdbFHS3Wtz4V9hzhe/Xog5hQRSMxmDLkEEYZwqMDHgJlkZo00HVFZR0j5d0nKypjTUkkygH3dDSXERLG4757A==", + "dev": true, + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.2" + }, + "peerDependencies": { + "monaco-editor": ">= 0.31.0", + "webpack": "^4.5.0 || 5.x" + } + }, + "node_modules/mongodb": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-7.0.0.tgz", + "integrity": "sha512-vG/A5cQrvGGvZm2mTnCSz1LUcbOPl83hfB6bxULKQ8oFZauyox/2xbZOoGNl+64m8VBrETkdGCDBdOsCr3F3jg==", + "license": "Apache-2.0", + "dependencies": { + "@mongodb-js/saslprep": "^1.3.0", + "bson": "^7.0.0", + "mongodb-connection-string-url": "^7.0.0" + }, + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.806.0", + "@mongodb-js/zstd": "^7.0.0", + "gcp-metadata": "^7.0.1", + "kerberos": "^7.0.0", + "mongodb-client-encryption": ">=7.0.0 <7.1.0", + "snappy": "^7.3.2", + "socks": "^2.8.6" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz", + "integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==", + "license": "Apache-2.0", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^14.1.0 || ^13.0.0" + } + }, + "node_modules/mongodb-explain-compat": { + "version": "3.3.23", + "resolved": "https://registry.npmjs.org/mongodb-explain-compat/-/mongodb-explain-compat-3.3.23.tgz", + "integrity": "sha512-3OygQjzjHr0hsT3y0f91yP7Ylp+2bbEM3IPil2yv+9avmGhA9Ru+CcgTXI+IfkfNlbcly/w7alvHDk+dlX28QQ==", + "license": "SSPL" + }, + "node_modules/mongodb/node_modules/@types/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-N8WXpbE6Wgri7KUSvrmQcqrMllKZ9uxkYWMt+mCSGwNc0Hsw9VQTW7ApqI4XNrx6/SaM2QQJCzMPDEXE058s+Q==", + "license": "MIT", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, + "node_modules/mongodb/node_modules/mongodb-connection-string-url": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-7.0.0.tgz", + "integrity": "sha512-irhhjRVLE20hbkRl4zpAYLnDMM+zIZnp0IDB9akAFFUZp/3XdOfwwddc7y6cNvF2WCEtfTYRwYbIfYa2kVY0og==", + "license": "Apache-2.0", + "dependencies": { + "@types/whatwg-url": "^13.0.0", + "whatwg-url": "^14.1.0" + }, + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/moo": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", + "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==", + "license": "BSD-3-Clause" + }, + "node_modules/mrmime": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", - "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dev": true, + "license": "MIT", + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/multiple-select-vanilla": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/multiple-select-vanilla/-/multiple-select-vanilla-4.4.0.tgz", + "integrity": "sha512-QxZep610yATWMZhDMq0kzZWZSTb/Iffc0OdknY1El5SOjSm0o7CSHxN7CfOJRlbSyYGNv4TyFlL5A8FRN08F2A==", + "license": "MIT", + "dependencies": { + "@types/trusted-types": "^2.0.7" + }, + "funding": { + "type": "ko_fi", + "url": "https://ko-fi.com/ghiscoding" + } + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true, + "license": "ISC" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, "funding": [ { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/nearley": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", + "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", + "license": "MIT", + "dependencies": { + "commander": "^2.19.0", + "moo": "^0.5.0", + "railroad-diagrams": "^1.0.0", + "randexp": "0.4.6" + }, + "bin": { + "nearley-railroad": "bin/nearley-railroad.js", + "nearley-test": "bin/nearley-test.js", + "nearley-unparse": "bin/nearley-unparse.js", + "nearleyc": "bin/nearleyc.js" + }, + "funding": { + "type": "individual", + "url": "https://nearley.js.org/#give-to-nearley" + } + }, + "node_modules/nearley/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-abi": { + "version": "3.85.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.85.0.tgz", + "integrity": "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==", + "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" } }, - "node_modules/micromark-factory-whitespace": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", - "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", + "dev": true, "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "optional": true + }, + "node_modules/node-forge": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.2.tgz", + "integrity": "sha512-6xKiQ+cph9KImrRh0VsjH2d8/GXA4FIMlgU4B757iI1ApvcyA9VlouP0yZJha01V+huImO+kKMU7ih+2+E14fw==", + "dev": true, + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" } }, - "node_modules/micromark-util-character": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", - "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/node-html-markdown": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/node-html-markdown/-/node-html-markdown-1.3.0.tgz", + "integrity": "sha512-OeFi3QwC/cPjvVKZ114tzzu+YoR+v9UXW5RwSXGUqGb0qCl0DvP406tzdL7SFn8pZrMyzXoisfG2zcuF9+zw4g==", + "dev": true, "license": "MIT", "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "node-html-parser": "^6.1.1" + }, + "engines": { + "node": ">=10.0.0" } }, - "node_modules/micromark-util-chunked": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", - "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/node-html-parser": { + "version": "6.1.13", + "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.13.tgz", + "integrity": "sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==", + "dev": true, "license": "MIT", "dependencies": { - "micromark-util-symbol": "^2.0.0" + "css-select": "^5.1.0", + "he": "1.2.0" } }, - "node_modules/micromark-util-classify-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", - "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-sarif-builder": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/node-sarif-builder/-/node-sarif-builder-3.3.1.tgz", + "integrity": "sha512-8z5dAbhpxmk/WRQHXlv4V0h+9Y4Ugk+w08lyhV/7E/CQX9yDdBc3025/EG+RSMJU2aPFh/IQ7XDV7Ti5TLt/TA==", + "dev": true, "license": "MIT", "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "@types/sarif": "^2.1.7", + "fs-extra": "^11.1.1" + }, + "engines": { + "node": ">=20" } }, - "node_modules/micromark-util-combine-extensions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", - "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", + "node_modules/normalize-package-data": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", + "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "micromark-util-chunked": "^2.0.0", - "micromark-util-types": "^2.0.0" + "hosted-git-info": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/micromark-util-decode-numeric-character-reference": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", - "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", + "node_modules/normalize-package-data/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dev": true, + "license": "ISC", "dependencies": { - "micromark-util-symbol": "^2.0.0" + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/micromark-util-decode-string": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", - "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/normalize-package-data/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.1.0.tgz", + "integrity": "sha512-X06Mfd/5aKsRHc0O0J5CUedwnPmnDtLF2+nq+KN9KSDlJHkPuh0JUviWjEWMe0SW/9TDdSLVPuk7L5gGTIA1/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, "license": "MIT", "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-symbol": "^2.0.0" + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/micromark-util-encode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", - "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/micromark-util-html-tag-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", - "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } }, - "node_modules/micromark-util-normalize-identifier": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", - "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, "license": "MIT", "dependencies": { - "micromark-util-symbol": "^2.0.0" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/micromark-util-resolve-all": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", - "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, "license": "MIT", "dependencies": { - "micromark-util-types": "^2.0.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", - "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, "license": "MIT", "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" } }, - "node_modules/micromark-util-subtokenize": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", - "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, "license": "MIT", "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/micromark-util-symbol": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", - "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-types": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", - "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true, "license": "MIT" }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dev": true, "license": "MIT", "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" + "ee-first": "1.1.1" }, "engines": { - "node": ">=8.6" + "node": ">= 0.8" } }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "dev": true, "license": "MIT", - "bin": { - "mime": "cli.js" - }, "engines": { - "node": ">=4" + "node": ">= 0.8" + } + }, + "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/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, + "node_modules/open": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", "license": "MIT", "dependencies": { - "mime-db": "1.52.0" + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mime-types/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" + "license": "(WTFPL OR MIT)", + "bin": { + "opener": "bin/opener-bin.js" } }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, "engines": { - "node": ">=6" + "node": ">= 0.8.0" } }, - "node_modules/mimic-function": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", - "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "node_modules/ora": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", + "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", "dev": true, "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "cli-cursor": "^5.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0" + }, "engines": { "node": ">=18" }, @@ -15629,1291 +17487,1264 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mimic-response": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", - "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", + "node_modules/ora/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "dev": true, "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "node_modules/ora/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", "dev": true, - "license": "ISC" + "license": "MIT" }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/ora/node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, + "license": "MIT", "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "node_modules/ora/node_modules/log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", "dev": true, "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" + "dependencies": { + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "node_modules/ora/node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", "dev": true, "license": "MIT", - "optional": true + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/mocha": { - "version": "11.7.5", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz", - "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==", + "node_modules/ora/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "license": "MIT", "dependencies": { - "browser-stdout": "^1.3.1", - "chokidar": "^4.0.1", - "debug": "^4.3.5", - "diff": "^7.0.0", - "escape-string-regexp": "^4.0.0", - "find-up": "^5.0.0", - "glob": "^10.4.5", - "he": "^1.2.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "log-symbols": "^4.1.0", - "minimatch": "^9.0.5", - "ms": "^2.1.3", - "picocolors": "^1.1.1", - "serialize-javascript": "^6.0.2", - "strip-json-comments": "^3.1.1", - "supports-color": "^8.1.1", - "workerpool": "^9.2.0", - "yargs": "^17.7.2", - "yargs-parser": "^21.1.1", - "yargs-unparser": "^2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha-junit-reporter": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-2.2.1.tgz", - "integrity": "sha512-iDn2tlKHn8Vh8o4nCzcUVW4q7iXp7cC4EB78N0cDHIobLymyHNwe0XG8HEHHjc3hJlXm0Vy6zcrxaIhnI2fWmw==", + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", "dev": true, "license": "MIT", "dependencies": { - "debug": "^4.3.4", - "md5": "^2.3.0", - "mkdirp": "^3.0.0", - "strip-ansi": "^6.0.1", - "xml": "^1.0.1" + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" }, - "peerDependencies": { - "mocha": ">=2.2.5" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mocha-junit-reporter/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==", + "node_modules/p-cancelable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12.20" } }, - "node_modules/mocha-junit-reporter/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==", + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha-multi-reporters": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/mocha-multi-reporters/-/mocha-multi-reporters-1.5.1.tgz", - "integrity": "sha512-Yb4QJOaGLIcmB0VY7Wif5AjvLMUFAdV57D2TWEva1Y0kU/3LjKpeRVmlMIfuO1SVbauve459kgtIizADqxMWPg==", + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "license": "MIT", "dependencies": { - "debug": "^4.1.1", - "lodash": "^4.17.15" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=6.0.0" + "node": ">=10" }, - "peerDependencies": { - "mocha": ">=3.1.2" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha/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, - "license": "Python-2.0" - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/p-map": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", + "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "node_modules/p-retry": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz", + "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==", "dev": true, "license": "MIT", "dependencies": { - "argparse": "^2.0.1" + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", + "retry": "^0.13.1" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "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", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "callsites": "^3.0.0" }, "engines": { - "node": ">=10" + "node": ">=6" + } + }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/monaco-editor": { - "version": "0.52.2", - "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz", - "integrity": "sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==", + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", "license": "MIT" }, - "node_modules/monaco-editor-webpack-plugin": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-7.1.1.tgz", - "integrity": "sha512-WxdbFHS3Wtz4V9hzhe/Xog5hQRSMxmDLkEEYZwqMDHgJlkZo00HVFZR0j5d0nKypjTUkkygH3dDSXERLG4757A==", + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "license": "MIT", "dependencies": { - "loader-utils": "^2.0.2" - }, - "peerDependencies": { - "monaco-editor": ">= 0.31.0", - "webpack": "^4.5.0 || 5.x" - } - }, - "node_modules/mongodb": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-7.0.0.tgz", - "integrity": "sha512-vG/A5cQrvGGvZm2mTnCSz1LUcbOPl83hfB6bxULKQ8oFZauyox/2xbZOoGNl+64m8VBrETkdGCDBdOsCr3F3jg==", - "license": "Apache-2.0", - "dependencies": { - "@mongodb-js/saslprep": "^1.3.0", - "bson": "^7.0.0", - "mongodb-connection-string-url": "^7.0.0" + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" }, "engines": { - "node": ">=20.19.0" - }, - "peerDependencies": { - "@aws-sdk/credential-providers": "^3.806.0", - "@mongodb-js/zstd": "^7.0.0", - "gcp-metadata": "^7.0.1", - "kerberos": "^7.0.0", - "mongodb-client-encryption": ">=7.0.0 <7.1.0", - "snappy": "^7.3.2", - "socks": "^2.8.6" + "node": ">=8" }, - "peerDependenciesMeta": { - "@aws-sdk/credential-providers": { - "optional": true - }, - "@mongodb-js/zstd": { - "optional": true - }, - "gcp-metadata": { - "optional": true - }, - "kerberos": { - "optional": true - }, - "mongodb-client-encryption": { - "optional": true - }, - "snappy": { - "optional": true - }, - "socks": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mongodb-connection-string-url": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz", - "integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==", - "license": "Apache-2.0", + "node_modules/parse-semver": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", + "integrity": "sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==", + "dev": true, + "license": "MIT", "dependencies": { - "@types/whatwg-url": "^11.0.2", - "whatwg-url": "^14.1.0 || ^13.0.0" + "semver": "^5.1.0" } }, - "node_modules/mongodb-explain-compat": { - "version": "3.3.23", - "resolved": "https://registry.npmjs.org/mongodb-explain-compat/-/mongodb-explain-compat-3.3.23.tgz", - "integrity": "sha512-3OygQjzjHr0hsT3y0f91yP7Ylp+2bbEM3IPil2yv+9avmGhA9Ru+CcgTXI+IfkfNlbcly/w7alvHDk+dlX28QQ==", - "license": "SSPL" - }, - "node_modules/mongodb/node_modules/@types/whatwg-url": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-13.0.0.tgz", - "integrity": "sha512-N8WXpbE6Wgri7KUSvrmQcqrMllKZ9uxkYWMt+mCSGwNc0Hsw9VQTW7ApqI4XNrx6/SaM2QQJCzMPDEXE058s+Q==", - "license": "MIT", - "dependencies": { - "@types/webidl-conversions": "*" + "node_modules/parse-semver/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" } }, - "node_modules/mongodb/node_modules/mongodb-connection-string-url": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-7.0.0.tgz", - "integrity": "sha512-irhhjRVLE20hbkRl4zpAYLnDMM+zIZnp0IDB9akAFFUZp/3XdOfwwddc7y6cNvF2WCEtfTYRwYbIfYa2kVY0og==", - "license": "Apache-2.0", + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dev": true, + "license": "MIT", "dependencies": { - "@types/whatwg-url": "^13.0.0", - "whatwg-url": "^14.1.0" + "entities": "^6.0.0" }, - "engines": { - "node": ">=20.19.0" + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/moo": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", - "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==", - "license": "BSD-3-Clause" - }, - "node_modules/mrmime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", - "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", + "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", "dev": true, "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "domhandler": "^5.0.3", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "node_modules/parse5-parser-stream": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", + "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", "dev": true, "license": "MIT", "dependencies": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" + "parse5": "^7.0.0" }, - "bin": { - "multicast-dns": "cli.js" + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/multiple-select-vanilla": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/multiple-select-vanilla/-/multiple-select-vanilla-4.4.0.tgz", - "integrity": "sha512-QxZep610yATWMZhDMq0kzZWZSTb/Iffc0OdknY1El5SOjSm0o7CSHxN7CfOJRlbSyYGNv4TyFlL5A8FRN08F2A==", + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/parseley": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.7.0.tgz", + "integrity": "sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw==", "license": "MIT", "dependencies": { - "@types/trusted-types": "^2.0.7" + "moo": "^0.5.1", + "nearley": "^2.20.1" }, "funding": { - "type": "ko_fi", - "url": "https://ko-fi.com/ghiscoding" + "url": "https://ko-fi.com/killymxi" } }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true, - "license": "ISC" + "license": "MIT", + "engines": { + "node": ">= 0.8" + } }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": ">=8" } }, - "node_modules/napi-build-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", - "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "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", - "optional": true + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/napi-postinstall": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", - "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "license": "MIT", - "bin": { - "napi-postinstall": "lib/cli.js" - }, "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/napi-postinstall" + "node": ">=8" } }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true, "license": "MIT" }, - "node_modules/nearley": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", - "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", - "license": "MIT", + "node_modules/path-scurry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", + "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { - "commander": "^2.19.0", - "moo": "^0.5.0", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6" + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" }, - "bin": { - "nearley-railroad": "bin/nearley-railroad.js", - "nearley-test": "bin/nearley-test.js", - "nearley-unparse": "bin/nearley-unparse.js", - "nearleyc": "bin/nearleyc.js" + "engines": { + "node": "20 || >=22" }, "funding": { - "type": "individual", - "url": "https://nearley.js.org/#give-to-nearley" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/nearley/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "license": "MIT" - }, - "node_modules/negotiator": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.2.tgz", + "integrity": "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==", "dev": true, - "license": "MIT", + "license": "ISC", "engines": { - "node": ">= 0.6" + "node": "20 || >=22" } }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "dev": true, "license": "MIT" }, - "node_modules/node-abi": { - "version": "3.85.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.85.0.tgz", - "integrity": "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==", + "node_modules/path-type": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", + "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", "dev": true, "license": "MIT", - "optional": true, - "dependencies": { - "semver": "^7.3.5" - }, "engines": { - "node": ">=10" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/node-addon-api": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", - "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "dev": true, - "license": "MIT", - "optional": true + "license": "MIT" }, - "node_modules/node-forge": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.2.tgz", - "integrity": "sha512-6xKiQ+cph9KImrRh0VsjH2d8/GXA4FIMlgU4B757iI1ApvcyA9VlouP0yZJha01V+huImO+kKMU7ih+2+E14fw==", + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, - "license": "(BSD-3-Clause OR GPL-2.0)", - "engines": { - "node": ">= 6.13.0" - } + "license": "ISC" }, - "node_modules/node-html-markdown": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/node-html-markdown/-/node-html-markdown-1.3.0.tgz", - "integrity": "sha512-OeFi3QwC/cPjvVKZ114tzzu+YoR+v9UXW5RwSXGUqGb0qCl0DvP406tzdL7SFn8pZrMyzXoisfG2zcuF9+zw4g==", + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", - "dependencies": { - "node-html-parser": "^6.1.1" - }, "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/node-html-parser": { - "version": "6.1.13", - "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.13.tgz", - "integrity": "sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==", - "dev": true, - "license": "MIT", - "dependencies": { - "css-select": "^5.1.0", - "he": "1.2.0" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">= 6" + } }, - "node_modules/node-sarif-builder": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/node-sarif-builder/-/node-sarif-builder-3.3.1.tgz", - "integrity": "sha512-8z5dAbhpxmk/WRQHXlv4V0h+9Y4Ugk+w08lyhV/7E/CQX9yDdBc3025/EG+RSMJU2aPFh/IQ7XDV7Ti5TLt/TA==", + "node_modules/piscina": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.9.2.tgz", + "integrity": "sha512-Fq0FERJWFEUpB4eSY59wSNwXD4RYqR+nR/WiEVcZW8IWfVBxJJafcgTEZDQo8k3w0sUarJ8RyVbbUF4GQ2LGbQ==", "dev": true, "license": "MIT", - "dependencies": { - "@types/sarif": "^2.1.7", - "fs-extra": "^11.1.1" - }, - "engines": { - "node": ">=20" + "optionalDependencies": { + "@napi-rs/nice": "^1.0.1" } }, - "node_modules/normalize-package-data": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", - "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "hosted-git-info": "^7.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" + "find-up": "^4.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/normalize-package-data/node_modules/hosted-git-info": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", - "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "lru-cache": "^10.0.1" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/normalize-package-data/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/normalize-url": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.1.0.tgz", - "integrity": "sha512-X06Mfd/5aKsRHc0O0J5CUedwnPmnDtLF2+nq+KN9KSDlJHkPuh0JUviWjEWMe0SW/9TDdSLVPuk7L5gGTIA1/w==", + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, "engines": { - "node": ">=14.16" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "license": "MIT", "dependencies": { - "path-key": "^3.0.0" + "p-limit": "^2.2.0" }, "engines": { "node": ">=8" } }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "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": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" + "license": "MIT", + "engines": { + "node": ">=4" } }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, "engines": { - "node": ">= 0.4" + "node": "^10 || ^12 || >=14" } }, - "node_modules/object.assign": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", - "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", + "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0", - "has-symbols": "^1.1.0", - "object-keys": "^1.1.1" + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.1.0" }, "engines": { - "node": ">= 0.4" + "node": "^10 || ^12 || >= 14" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "node_modules/postcss-modules-scope": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", + "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" + "postcss-selector-parser": "^7.0.0" }, "engines": { - "node": ">= 0.4" + "node": "^10 || ^12 || >= 14" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/object.groupby": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" + "icss-utils": "^5.0.0" }, "engines": { - "node": ">= 0.4" + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/object.values": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", - "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4" } }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true, "license": "MIT" }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "ee-first": "1.1.1" + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" }, "engines": { - "node": ">= 0.8" + "node": ">=10" } }, - "node_modules/on-headers": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", - "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8" - } - }, - "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", - "optional": true, - "dependencies": { - "wrappy": "1" + "node": ">= 0.8.0" } }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" + "bin": { + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=6" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/open": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", - "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "node_modules/prettier-plugin-organize-imports": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-4.3.0.tgz", + "integrity": "sha512-FxFz0qFhyBsGdIsb697f/EkvHzi5SZOhWAjxcx2dLt+Q532bAlhswcXGYB1yzjZ69kW8UoadFBw7TyNwlq96Iw==", + "dev": true, "license": "MIT", - "dependencies": { - "default-browser": "^5.2.1", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "wsl-utils": "^0.1.0" - }, - "engines": { - "node": ">=18" + "peerDependencies": { + "prettier": ">=2.0", + "typescript": ">=2.9", + "vue-tsc": "^2.1.0 || 3" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/opener": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "dev": true, - "license": "(WTFPL OR MIT)", - "bin": { - "opener": "bin/opener-bin.js" + "peerDependenciesMeta": { + "vue-tsc": { + "optional": true + } } }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "node_modules/pretty-format": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", + "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", "dev": true, "license": "MIT", "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" }, "engines": { - "node": ">= 0.8.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/ora": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", - "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "dependencies": { - "chalk": "^5.3.0", - "cli-cursor": "^5.0.0", - "cli-spinners": "^2.9.2", - "is-interactive": "^2.0.0", - "is-unicode-supported": "^2.0.0", - "log-symbols": "^6.0.0", - "stdin-discarder": "^0.2.2", - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0" - }, "engines": { - "node": ">=18" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/ora/node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "node_modules/pretty-format/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } + "license": "MIT" }, - "node_modules/ora/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "node_modules/priorityqueuejs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/priorityqueuejs/-/priorityqueuejs-2.0.0.tgz", + "integrity": "sha512-19BMarhgpq3x4ccvVi8k2QpJZcymo/iFUcrhPd4V96kYGovOdTsWwy7fxChYi4QY+m2EnGBWSX9Buakz+tWNQQ==", + "license": "MIT" + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true, "license": "MIT" }, - "node_modules/ora/node_modules/is-unicode-supported": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", - "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", "dev": true, "license": "MIT", - "engines": { - "node": ">=18" + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "license": "MIT", "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/ora/node_modules/log-symbols": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", - "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^5.3.0", - "is-unicode-supported": "^1.3.0" + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.10" } }, - "node_modules/ora/node_modules/log-symbols/node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "dev": true, "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.10" } }, - "node_modules/ora/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "node_modules/pseudo-localization": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/pseudo-localization/-/pseudo-localization-2.4.0.tgz", + "integrity": "sha512-ISYMOKY8+f+PmiXMFw2y6KLY74LBrv/8ml/VjjoVEV2k+MS+OJZz7ydciK5ntJwxPrKQPTU1+oXq9Mx2b0zEzg==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" + "flat": "^5.0.2", + "get-stdin": "^7.0.0", + "typescript": "^4.7.4", + "yargs": "^17.2.1" }, - "engines": { - "node": ">=18" + "bin": { + "pseudo-localization": "bin/pseudo-localize" + } + }, + "node_modules/pseudo-localization/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" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=4.2.0" } }, - "node_modules/own-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", - "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "get-intrinsic": "^1.2.6", - "object-keys": "^1.1.1", - "safe-push-apply": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, - "node_modules/p-cancelable": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", - "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", - "dev": true, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "license": "MIT", "engines": { - "node": ">=12.20" + "node": ">=6" } }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", "dev": true, "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/pure-rand": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz", + "integrity": "sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==", "dev": true, - "license": "MIT", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "p-limit": "^3.0.2" + "side-channel": "^1.1.0" }, "engines": { - "node": ">=10" + "node": ">=0.6" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/p-map": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", - "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "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/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-retry": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz", - "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==", - "dev": true, + "node_modules/railroad-diagrams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==", + "license": "CC0-1.0" + }, + "node_modules/randexp": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", "license": "MIT", "dependencies": { - "@types/retry": "0.12.2", - "is-network-error": "^1.0.0", - "retry": "^0.13.1" + "discontinuous-range": "1.0.0", + "ret": "~0.1.10" }, "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.12" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "safe-buffer": "^5.1.0" } }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true, - "license": "BlueOak-1.0.0" - }, - "node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true, - "license": "(MIT AND Zlib)" + "license": "MIT", + "engines": { + "node": ">= 0.6" + } }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", "dev": true, "license": "MIT", "dependencies": { - "callsites": "^3.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" }, "engines": { - "node": ">=6" + "node": ">= 0.8" } }, - "node_modules/parse-entities": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", - "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "node_modules/raw-body/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "^2.0.0", - "character-entities-legacy": "^3.0.0", - "character-reference-invalid": "^2.0.0", - "decode-named-character-reference": "^1.0.0", - "is-alphanumerical": "^2.0.0", - "is-decimal": "^2.0.0", - "is-hexadecimal": "^2.0.0" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/parse-entities/node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", - "license": "MIT" - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/parse-semver": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", - "integrity": "sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==", + "node_modules/raw-body/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "dev": true, "license": "MIT", - "dependencies": { - "semver": "^5.1.0" + "engines": { + "node": ">= 0.8" } }, - "node_modules/parse-semver/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, - "license": "ISC", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "optional": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, "bin": { - "semver": "bin/semver" + "rc": "cli.js" } }, - "node_modules/parse5": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", - "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "node_modules/rc-config-loader": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/rc-config-loader/-/rc-config-loader-4.1.3.tgz", + "integrity": "sha512-kD7FqML7l800i6pS6pvLyIE2ncbk9Du8Q0gp/4hMPhJU6ZxApkoLcGD8ZeqgiAlfwZ6BlETq6qqe+12DUL207w==", "dev": true, "license": "MIT", "dependencies": { - "entities": "^6.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "debug": "^4.3.4", + "js-yaml": "^4.1.0", + "json5": "^2.2.2", + "require-from-string": "^2.0.2" } }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", - "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", + "node_modules/rc-config-loader/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, + "license": "Python-2.0" + }, + "node_modules/rc-config-loader/node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { - "domhandler": "^5.0.3", - "parse5": "^7.0.0" + "argparse": "^2.0.1" }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/parse5-parser-stream": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", - "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "dev": true, "license": "MIT", - "dependencies": { - "parse5": "^7.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "optional": true, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/parse5/node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", - "dev": true, - "license": "BSD-2-Clause", + "node_modules/react": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", + "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", + "license": "MIT", "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/parseley": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.7.0.tgz", - "integrity": "sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw==", + "node_modules/react-dom": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", + "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", "license": "MIT", "dependencies": { - "moo": "^0.5.1", - "nearley": "^2.20.1" + "scheduler": "^0.27.0" }, - "funding": { - "url": "https://ko-fi.com/killymxi" + "peerDependencies": { + "react": "^19.2.0" } }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, + "node_modules/react-hotkeys-hook": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-5.2.1.tgz", + "integrity": "sha512-xbKh6zJxd/vJHT4Bw4+0pBD662Fk20V+VFhLqciCg+manTVO4qlqRqiwFOYelfHN9dBvWj9vxaPkSS26ZSIJGg==", "license": "MIT", - "engines": { - "node": ">= 0.8" + "workspaces": [ + "packages/*" + ], + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" } }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, + "node_modules/react-markdown": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz", + "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==", "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "html-url-attributes": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=18", + "react": ">=18" } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/path-parse": { + "node_modules/read": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-scurry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", - "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "ISC", "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" + "mute-stream": "~0.0.4" }, "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=0.8" } }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.2.tgz", - "integrity": "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==", + "node_modules/read-pkg": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", + "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", "dev": true, - "license": "ISC", + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.3", + "normalize-package-data": "^6.0.0", + "parse-json": "^8.0.0", + "type-fest": "^4.6.0", + "unicorn-magic": "^0.1.0" + }, "engines": { - "node": "20 || >=22" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-type": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", - "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", + "node_modules/read-pkg/node_modules/parse-json": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", + "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", "dev": true, "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "index-to-position": "^1.1.0", + "type-fest": "^4.39.1" + }, "engines": { "node": ">=18" }, @@ -16921,507 +18752,472 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true, - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "node_modules/read-pkg/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", "dev": true, - "license": "ISC" + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "node_modules/read-pkg/node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=8.6" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pirates": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", - "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 6" + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/piscina": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.9.2.tgz", - "integrity": "sha512-Fq0FERJWFEUpB4eSY59wSNwXD4RYqR+nR/WiEVcZW8IWfVBxJJafcgTEZDQo8k3w0sUarJ8RyVbbUF4GQ2LGbQ==", + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, - "license": "MIT", - "optionalDependencies": { - "@napi-rs/nice": "^1.0.1" - } + "license": "MIT" }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "dev": true, "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "resolve": "^1.20.0" }, "engines": { - "node": ">=8" + "node": ">= 10.13.0" } }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "license": "MIT" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" }, "engines": { - "node": ">=6" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" }, - "engines": { - "node": ">=8" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "dev": true, + "node_modules/remark-rehype": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", "license": "MIT", - "engines": { - "node": ">=4" + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/possible-typed-array-names": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", - "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=0.10.0" } }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", - "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", - "dev": true, - "license": "ISC", "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "node": ">=0.10.0" } }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", - "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", + "node_modules/requireindex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", + "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", "dev": true, "license": "MIT", - "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^7.0.0", - "postcss-value-parser": "^4.1.0" - }, "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "node": ">=0.10.5" } }, - "node_modules/postcss-modules-scope": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", - "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true, - "license": "ISC", - "dependencies": { - "postcss-selector-parser": "^7.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } + "license": "MIT" }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "icss-utils": "^5.0.0" + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" }, "engines": { - "node": "^10 || ^12 || >= 14" + "node": ">= 0.4" }, - "peerDependencies": { - "postcss": "^8.1.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, "license": "MIT", "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" + "resolve-from": "^5.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "node_modules/prebuild-install": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", - "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "license": "MIT", - "optional": true, - "dependencies": { - "detect-libc": "^2.0.0", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^2.0.0", - "node-abi": "^3.3.0", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^4.0.0", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - }, - "bin": { - "prebuild-install": "bin.js" - }, "engines": { - "node": ">=10" + "node": ">=4" } }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8.0" + "node": ">=10" } }, - "node_modules/prettier": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", - "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "node_modules/responselike": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", + "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", "dev": true, "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" + "dependencies": { + "lowercase-keys": "^3.0.0" }, "engines": { - "node": ">=14" + "node": ">=14.16" }, "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/prettier-plugin-organize-imports": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-4.3.0.tgz", - "integrity": "sha512-FxFz0qFhyBsGdIsb697f/EkvHzi5SZOhWAjxcx2dLt+Q532bAlhswcXGYB1yzjZ69kW8UoadFBw7TyNwlq96Iw==", + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, "license": "MIT", - "peerDependencies": { - "prettier": ">=2.0", - "typescript": ">=2.9", - "vue-tsc": "^2.1.0 || 3" + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" }, - "peerDependenciesMeta": { - "vue-tsc": { - "optional": true - } + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "node_modules/restore-cursor/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/schemas": "30.0.5", - "ansi-styles": "^5.2.0", - "react-is": "^18.3.1" + "mimic-function": "^5.0.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "license": "MIT", + "license": "ISC", "engines": { - "node": ">=10" + "node": ">=14" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/pretty-format/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true, - "license": "MIT" - }, - "node_modules/priorityqueuejs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/priorityqueuejs/-/priorityqueuejs-2.0.0.tgz", - "integrity": "sha512-19BMarhgpq3x4ccvVi8k2QpJZcymo/iFUcrhPd4V96kYGovOdTsWwy7fxChYi4QY+m2EnGBWSX9Buakz+tWNQQ==", - "license": "MIT" - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "license": "MIT" - }, - "node_modules/property-information": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", - "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "engines": { + "node": ">=0.12" } }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", "dev": true, "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, "engines": { - "node": ">= 0.10" + "node": ">= 4" } }, - "node_modules/proxy-addr/node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.10" + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, - "node_modules/pseudo-localization": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/pseudo-localization/-/pseudo-localization-2.4.0.tgz", - "integrity": "sha512-ISYMOKY8+f+PmiXMFw2y6KLY74LBrv/8ml/VjjoVEV2k+MS+OJZz7ydciK5ntJwxPrKQPTU1+oXq9Mx2b0zEzg==", + "node_modules/rimraf": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.2.tgz", + "integrity": "sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "flat": "^5.0.2", - "get-stdin": "^7.0.0", - "typescript": "^4.7.4", - "yargs": "^17.2.1" + "glob": "^13.0.0", + "package-json-from-dist": "^1.0.1" }, "bin": { - "pseudo-localization": "bin/pseudo-localize" - } - }, - "node_modules/pseudo-localization/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" + "rimraf": "dist/esm/bin.mjs" }, "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/pump": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", - "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rtl-css-js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz", + "integrity": "sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==", "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "@babel/runtime": "^7.1.2" } }, - "node_modules/punycode.js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", - "dev": true, + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", "license": "MIT", "engines": { - "node": ">=6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pure-rand": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz", - "integrity": "sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==", + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" + "type": "github", + "url": "https://github.com/sponsors/feross" }, { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } ], - "license": "MIT" + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } }, - "node_modules/qs": { - "version": "6.14.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", - "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", + "node_modules/run-script-os": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/run-script-os/-/run-script-os-1.1.6.tgz", + "integrity": "sha512-ql6P2LzhBTTDfzKts+Qo4H94VUKpxKDFz6QxxwaUZN0mwvi7L3lpOI7BqPCq7lgDh3XLl0dpeXwfcVIitlrYrw==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", + "bin": { + "run-os": "index.js", + "run-script-os": "index.js" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, + "license": "MIT", "dependencies": { - "side-channel": "^1.1.0" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" }, "engines": { - "node": ">=0.6" + "node": ">=0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true, + "license": "MIT" + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "funding": [ { "type": "github", @@ -17438,763 +19234,642 @@ ], "license": "MIT" }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/railroad-diagrams": { + "node_modules/safe-push-apply": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==", - "license": "CC0-1.0" - }, - "node_modules/randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", - "license": "MIT", - "dependencies": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", - "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", "dev": true, "license": "MIT", "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" + "es-errors": "^1.3.0", + "isarray": "^2.0.5" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "node_modules/safe-push-apply/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, - "node_modules/raw-body/node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", - "optional": true, "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc-config-loader": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/rc-config-loader/-/rc-config-loader-4.1.3.tgz", - "integrity": "sha512-kD7FqML7l800i6pS6pvLyIE2ncbk9Du8Q0gp/4hMPhJU6ZxApkoLcGD8ZeqgiAlfwZ6BlETq6qqe+12DUL207w==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4", - "js-yaml": "^4.1.0", - "json5": "^2.2.2", - "require-from-string": "^2.0.2" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/rc-config-loader/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==", + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, - "license": "Python-2.0" + "license": "MIT" }, - "node_modules/rc-config-loader/node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "node_modules/sass": { + "version": "1.94.2", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.94.2.tgz", + "integrity": "sha512-N+7WK20/wOr7CzA2snJcUSSNTCzeCGUTFY3OgeQP3mZ1aj9NMQ0mSTXwlrnd89j33zzQJGqIN52GIOmYrfq46A==", "dev": true, "license": "MIT", "dependencies": { - "argparse": "^2.0.1" + "chokidar": "^4.0.0", + "immutable": "^5.0.2", + "source-map-js": ">=0.6.2 <2.0.0" }, "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", - "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", - "license": "MIT", + "sass": "sass.js" + }, "engines": { - "node": ">=0.10.0" + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" } }, - "node_modules/react-dom": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", - "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", + "node_modules/sass-loader": { + "version": "16.0.6", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.6.tgz", + "integrity": "sha512-sglGzId5gmlfxNs4gK2U3h7HlVRfx278YK6Ono5lwzuvi1jxig80YiuHkaDBVsYIKFhx8wN7XSCI0M2IDS/3qA==", + "dev": true, "license": "MIT", "dependencies": { - "scheduler": "^0.27.0" + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "react": "^19.2.0" + "@rspack/core": "0.x || 1.x", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "webpack": { + "optional": true + } } }, - "node_modules/react-hotkeys-hook": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-5.2.1.tgz", - "integrity": "sha512-xbKh6zJxd/vJHT4Bw4+0pBD662Fk20V+VFhLqciCg+manTVO4qlqRqiwFOYelfHN9dBvWj9vxaPkSS26ZSIJGg==", - "license": "MIT", - "workspaces": [ - "packages/*" - ], - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } + "node_modules/sax": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz", + "integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==", + "dev": true, + "license": "BlueOak-1.0.0" }, - "node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", "license": "MIT" }, - "node_modules/react-markdown": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz", - "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==", + "node_modules/schema-utils": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", + "dev": true, "license": "MIT", "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "hast-util-to-jsx-runtime": "^2.0.0", - "html-url-attributes": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.0.0", - "unified": "^11.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "peerDependencies": { - "@types/react": ">=18", - "react": ">=18" + "url": "https://opencollective.com/webpack" } }, - "node_modules/react-refresh": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", - "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "node_modules/secretlint": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/secretlint/-/secretlint-10.2.2.tgz", + "integrity": "sha512-xVpkeHV/aoWe4vP4TansF622nBEImzCY73y/0042DuJ29iKIaqgoJ8fGxre3rVSHHbxar4FdJobmTnLp9AU0eg==", "dev": true, "license": "MIT", + "dependencies": { + "@secretlint/config-creator": "^10.2.2", + "@secretlint/formatter": "^10.2.2", + "@secretlint/node": "^10.2.2", + "@secretlint/profiler": "^10.2.2", + "debug": "^4.4.1", + "globby": "^14.1.0", + "read-pkg": "^9.0.1" + }, + "bin": { + "secretlint": "bin/secretlint.js" + }, "engines": { - "node": ">=0.10.0" + "node": ">=20.0.0" } }, - "node_modules/read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", + "node_modules/seek-bzip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-2.0.0.tgz", + "integrity": "sha512-SMguiTnYrhpLdk3PwfzHeotrcwi8bNV4iemL9tx9poR/yeaMYwB9VzR1w7b57DuWpuqR8n6oZboi0hj3AxZxQg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "mute-stream": "~0.0.4" + "commander": "^6.0.0" }, - "engines": { - "node": ">=0.8" + "bin": { + "seek-bunzip": "bin/seek-bunzip", + "seek-table": "bin/seek-bzip-table" } }, - "node_modules/read-pkg": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", - "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", + "node_modules/seek-bzip/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", "dev": true, "license": "MIT", - "dependencies": { - "@types/normalize-package-data": "^2.4.3", - "normalize-package-data": "^6.0.0", - "parse-json": "^8.0.0", - "type-fest": "^4.6.0", - "unicorn-magic": "^0.1.0" - }, "engines": { - "node": ">=18" + "node": ">= 6" + } + }, + "node_modules/selderee": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.6.0.tgz", + "integrity": "sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg==", + "license": "MIT", + "dependencies": { + "parseley": "^0.7.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://ko-fi.com/killymxi" } }, - "node_modules/read-pkg/node_modules/parse-json": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", - "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true, + "license": "MIT" + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "index-to-position": "^1.1.0", - "type-fest": "^4.39.1" + "@types/node-forge": "^1.3.0", + "node-forge": "^1" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10" } }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", + "node_modules/semaphore": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", + "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==", "engines": { - "node": ">=16" + "node": ">=0.8.0" + } + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=10" } }, - "node_modules/read-pkg/node_modules/unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "node_modules/semver-regex": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-4.0.5.tgz", + "integrity": "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "node_modules/semver-truncate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-3.0.0.tgz", + "integrity": "sha512-LJWA9kSvMolR51oDE6PN3kALBNaUdkxzAGcexw8gjMA8xr5zUqK0JiR3CgARSqanYF3Z1YHvsErb1KDgh+v7Rg==", "dev": true, "license": "MIT", "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true, - "license": "MIT", + "semver": "^7.3.5" + }, "engines": { - "node": ">= 14.18.0" + "node": ">=12" }, "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/rechoir": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", - "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dev": true, "license": "MIT", "dependencies": { - "resolve": "^1.20.0" + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" }, "engines": { - "node": ">= 10.13.0" + "node": ">= 0.8.0" } }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", - "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.1", - "which-builtin-type": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "ms": "2.0.0" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, "license": "MIT" }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", - "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "dev": true, "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "set-function-name": "^2.0.2" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.8" } }, - "node_modules/remark-parse": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", - "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", - "license": "MIT", + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "randombytes": "^2.1.0" } }, - "node_modules/remark-rehype": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", - "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dev": true, "license": "MIT", "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "mdast-util-to-hast": "^13.0.0", - "unified": "^11.0.0", - "vfile": "^6.0.0" + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/requireindex": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", - "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", "dev": true, "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, "engines": { - "node": ">=0.10.5" + "node": ">= 0.6" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true, + "license": "ISC" + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true, "license": "MIT" }, - "node_modules/resolve": { - "version": "1.22.11", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", - "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", "dev": true, "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.6" } - }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dev": true, "license": "MIT", "dependencies": { - "resolve-from": "^5.0.0" + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" }, "engines": { - "node": ">=8" + "node": ">= 0.8.0" } }, - "node_modules/resolve-cwd/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, "engines": { - "node": ">=4" + "node": ">= 0.4" } }, - "node_modules/responselike": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", - "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", "dev": true, "license": "MIT", "dependencies": { - "lowercase-keys": "^3.0.0" + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.4" } }, - "node_modules/restore-cursor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", - "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true, + "license": "MIT" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "dev": true, "license": "MIT", "dependencies": { - "onetime": "^7.0.0", - "signal-exit": "^4.1.0" + "kind-of": "^6.0.2" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/restore-cursor/node_modules/onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "license": "MIT", "dependencies": { - "mimic-function": "^5.0.0" + "shebang-regex": "^3.0.0" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/restore-cursor/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "license": "MIT", "engines": { - "node": ">=0.12" + "node": ">=8" } }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "node_modules/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", "dev": true, "license": "MIT", "engines": { - "node": ">= 4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/reusify": { + "node_modules/side-channel": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.2.tgz", - "integrity": "sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==", - "dev": true, - "license": "BlueOak-1.0.0", "dependencies": { - "glob": "^13.0.0", - "package-json-from-dist": "^1.0.1" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" }, "engines": { - "node": "20 || >=22" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/rtl-css-js": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz", - "integrity": "sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==", + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.1.2" - } - }, - "node_modules/run-applescript": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", - "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", - "license": "MIT", + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, "engines": { - "node": ">=18" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "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": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/run-script-os": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/run-script-os/-/run-script-os-1.1.6.tgz", - "integrity": "sha512-ql6P2LzhBTTDfzKts+Qo4H94VUKpxKDFz6QxxwaUZN0mwvi7L3lpOI7BqPCq7lgDh3XLl0dpeXwfcVIitlrYrw==", - "dev": true, - "license": "MIT", - "bin": { - "run-os": "index.js", - "run-script-os": "index.js" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safe-array-concat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", - "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "has-symbols": "^1.1.0", - "isarray": "^2.0.5" + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { - "node": ">=0.4" + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safe-array-concat/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true, - "license": "MIT" + "license": "ISC" }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, "funding": [ { "type": "github", @@ -18209,549 +19884,521 @@ "url": "https://feross.org/support" } ], - "license": "MIT" + "license": "MIT", + "optional": true }, - "node_modules/safe-push-apply": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", - "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", "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", + "optional": true, "dependencies": { - "es-errors": "^1.3.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" } }, - "node_modules/safe-push-apply/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true, - "license": "MIT" - }, - "node_modules/safe-regex-test": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "node_modules/sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-regex": "^1.2.1" + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 10" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", "dev": true, "license": "MIT" }, - "node_modules/sass": { - "version": "1.94.2", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.94.2.tgz", - "integrity": "sha512-N+7WK20/wOr7CzA2snJcUSSNTCzeCGUTFY3OgeQP3mZ1aj9NMQ0mSTXwlrnd89j33zzQJGqIN52GIOmYrfq46A==", + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "license": "MIT", - "dependencies": { - "chokidar": "^4.0.0", - "immutable": "^5.0.2", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" - }, "engines": { - "node": ">=14.0.0" - }, - "optionalDependencies": { - "@parcel/watcher": "^2.4.1" + "node": ">=8" } }, - "node_modules/sass-loader": { - "version": "16.0.6", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.6.tgz", - "integrity": "sha512-sglGzId5gmlfxNs4gK2U3h7HlVRfx278YK6Ono5lwzuvi1jxig80YiuHkaDBVsYIKFhx8wN7XSCI0M2IDS/3qA==", + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, "license": "MIT", "dependencies": { - "neo-async": "^2.6.2" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" }, "engines": { - "node": ">= 18.12.0" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slickgrid-react": { + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/slickgrid-react/-/slickgrid-react-9.9.0.tgz", + "integrity": "sha512-KUDIx3ErHGfYV4SzY4bkF7dseLM/jucc7PG+0ZoI6CsBySsUqaFhjZqBN9VUuxFRQJAzuB2KfQ5FvQyHylgyAg==", + "license": "MIT", + "dependencies": { + "@slickgrid-universal/common": "9.9.0", + "@slickgrid-universal/custom-footer-component": "9.9.0", + "@slickgrid-universal/empty-warning-component": "9.9.0", + "@slickgrid-universal/event-pub-sub": "9.9.0", + "@slickgrid-universal/pagination-component": "9.9.0", + "@slickgrid-universal/row-detail-view-plugin": "9.9.0", + "@slickgrid-universal/utils": "9.9.0", + "dequal": "^2.0.3", + "sortablejs": "^1.15.6" }, "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", - "sass": "^1.3.0", - "sass-embedded": "*", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "webpack": { - "optional": true - } + "react": ">=19.0.0" } }, - "node_modules/sax": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz", - "integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==", + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", "dev": true, - "license": "BlueOak-1.0.0" - }, - "node_modules/scheduler": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", - "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", - "license": "MIT" + "license": "MIT", + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } }, - "node_modules/schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", + "node_modules/sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==", "dev": true, "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" + "is-plain-obj": "^1.0.0" }, "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=0.10.0" } }, - "node_modules/secretlint": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/secretlint/-/secretlint-10.2.2.tgz", - "integrity": "sha512-xVpkeHV/aoWe4vP4TansF622nBEImzCY73y/0042DuJ29iKIaqgoJ8fGxre3rVSHHbxar4FdJobmTnLp9AU0eg==", + "node_modules/sort-keys-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", + "integrity": "sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==", "dev": true, "license": "MIT", "dependencies": { - "@secretlint/config-creator": "^10.2.2", - "@secretlint/formatter": "^10.2.2", - "@secretlint/node": "^10.2.2", - "@secretlint/profiler": "^10.2.2", - "debug": "^4.4.1", - "globby": "^14.1.0", - "read-pkg": "^9.0.1" - }, - "bin": { - "secretlint": "bin/secretlint.js" + "sort-keys": "^1.0.0" }, "engines": { - "node": ">=20.0.0" + "node": ">=0.10.0" + } + }, + "node_modules/sortablejs": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.6.tgz", + "integrity": "sha512-aNfiuwMEpfBM/CN6LY0ibyhxPfPbyFeBTYJKCvzkJ2GkUpazIt3H+QIPAMHwqQ7tMKaHz1Qj+rJJCqljnf4p3A==", + "license": "MIT" + }, + "node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/seek-bzip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-2.0.0.tgz", - "integrity": "sha512-SMguiTnYrhpLdk3PwfzHeotrcwi8bNV4iemL9tx9poR/yeaMYwB9VzR1w7b57DuWpuqR8n6oZboi0hj3AxZxQg==", + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, "license": "MIT", "dependencies": { - "commander": "^6.0.0" - }, - "bin": { - "seek-bunzip": "bin/seek-bunzip", - "seek-table": "bin/seek-bzip-table" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, - "node_modules/seek-bzip/node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "engines": { - "node": ">= 6" + "node": ">=0.10.0" } }, - "node_modules/selderee": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.6.0.tgz", - "integrity": "sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg==", + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", "license": "MIT", - "dependencies": { - "parseley": "^0.7.0" - }, "funding": { - "url": "https://ko-fi.com/killymxi" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", - "dev": true, - "license": "MIT" - }, - "node_modules/selfsigned": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", - "dev": true, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", "license": "MIT", "dependencies": { - "@types/node-forge": "^1.3.0", - "node-forge": "^1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semaphore": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", - "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==", - "engines": { - "node": ">=0.8.0" + "memory-pager": "^1.0.2" } }, - "node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/semver-regex": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-4.0.5.tgz", - "integrity": "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==", + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "license": "CC-BY-3.0" }, - "node_modules/semver-truncate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-3.0.0.tgz", - "integrity": "sha512-LJWA9kSvMolR51oDE6PN3kALBNaUdkxzAGcexw8gjMA8xr5zUqK0JiR3CgARSqanYF3Z1YHvsErb1KDgh+v7Rg==", + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, "license": "MIT", "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "node_modules/spdx-license-ids": { + "version": "3.0.22", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", + "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", "dev": true, "license": "MIT", "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=6.0.0" } }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", "dev": true, "license": "MIT", "dependencies": { - "ms": "2.0.0" + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" } }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, - "license": "MIT" - }, - "node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "node_modules/spdy-transport/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, "engines": { - "node": ">= 0.8" + "node": ">= 6" } }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" - } + "license": "BSD-3-Clause" }, - "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, "license": "MIT", "dependencies": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" + "escape-string-regexp": "^2.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=10" } }, - "node_modules/serve-index/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", + "dev": true, + "license": "MIT" + }, + "node_modules/state-local": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz", + "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==", + "license": "MIT" + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, "license": "MIT", - "dependencies": { - "ms": "2.0.0" + "engines": { + "node": ">= 0.8" } - }, - "node_modules/serve-index/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + }, + "node_modules/stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", "dev": true, "license": "MIT", "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" } }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "node_modules/streamx": { + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", + "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } }, - "node_modules/serve-index/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, - "license": "ISC" + "license": "MIT" }, - "node_modules/serve-index/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dev": true, "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=10" } }, - "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "node_modules/string-length/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", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - }, "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "node_modules/string-length/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": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=8" } }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "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": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=8" } }, - "node_modules/set-proto": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", - "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "node_modules/string-width-cjs": { + "name": "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": { - "dunder-proto": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=8" } }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true, - "license": "MIT" - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "node_modules/string-width-cjs/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": "ISC" + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "node_modules/string-width-cjs/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": { - "kind-of": "^6.0.2" + "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "node_modules/string-width/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", - "dependencies": { - "shebang-regex": "^3.0.0" - }, "engines": { "node": ">=8" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "node_modules/string-width/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/shell-quote": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", - "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, "engines": { "node": ">= 0.4" }, @@ -18759,18 +20406,17 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -18779,15 +20425,16 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -18796,2594 +20443,2733 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "node_modules/strip-ansi-cjs": { + "name": "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": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "node_modules/strip-ansi-cjs/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": "ISC" + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "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", - "optional": true + "engines": { + "node": ">=8" + } }, - "node_modules/simple-get": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "node_modules/strip-dirs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-3.0.0.tgz", + "integrity": "sha512-I0sdgcFTfKQlUPZyAqPJmSG3HLO9rWDFnxonnIbskYNM3DwFOeTNB5KzVq3dA1GdRAc/25b5Y7UO2TQfKWw4aQ==", "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", - "optional": true, + "license": "ISC", "dependencies": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" + "inspect-with-kind": "^1.0.5", + "is-plain-obj": "^1.1.0" } }, - "node_modules/sirv": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", - "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, "license": "MIT", - "dependencies": { - "@polka/url": "^1.0.0-next.24", - "mrmime": "^2.0.0", - "totalist": "^3.0.0" - }, "engines": { - "node": ">= 10" + "node": ">=6" } }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "license": "MIT", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "node_modules/strtok3": { + "version": "10.3.4", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.4.tgz", + "integrity": "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" + "@tokenizer/token": "^0.3.0" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "type": "github", + "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/slickgrid-react": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/slickgrid-react/-/slickgrid-react-9.9.0.tgz", - "integrity": "sha512-KUDIx3ErHGfYV4SzY4bkF7dseLM/jucc7PG+0ZoI6CsBySsUqaFhjZqBN9VUuxFRQJAzuB2KfQ5FvQyHylgyAg==", - "license": "MIT", + "node_modules/structured-source": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/structured-source/-/structured-source-4.0.0.tgz", + "integrity": "sha512-qGzRFNJDjFieQkl/sVOI2dUjHKRyL9dAJi2gCPGJLbJHBIkyOHxjuocpIEfbLioX+qSJpvbYdT49/YCdMznKxA==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@slickgrid-universal/common": "9.9.0", - "@slickgrid-universal/custom-footer-component": "9.9.0", - "@slickgrid-universal/empty-warning-component": "9.9.0", - "@slickgrid-universal/event-pub-sub": "9.9.0", - "@slickgrid-universal/pagination-component": "9.9.0", - "@slickgrid-universal/row-detail-view-plugin": "9.9.0", - "@slickgrid-universal/utils": "9.9.0", - "dequal": "^2.0.3", - "sortablejs": "^1.15.6" - }, - "peerDependencies": { - "react": ">=19.0.0" + "boundary": "^2.0.0" } }, - "node_modules/sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "node_modules/style-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-4.0.0.tgz", + "integrity": "sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA==", "dev": true, "license": "MIT", - "dependencies": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.27.0" } }, - "node_modules/sort-keys": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", - "integrity": "sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==", - "dev": true, + "node_modules/style-to-js": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", + "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", "license": "MIT", "dependencies": { - "is-plain-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" + "style-to-object": "1.0.14" } }, - "node_modules/sort-keys-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", - "integrity": "sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==", - "dev": true, + "node_modules/style-to-object": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", + "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", "license": "MIT", "dependencies": { - "sort-keys": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" + "inline-style-parser": "0.2.7" } }, - "node_modules/sortablejs": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.6.tgz", - "integrity": "sha512-aNfiuwMEpfBM/CN6LY0ibyhxPfPbyFeBTYJKCvzkJ2GkUpazIt3H+QIPAMHwqQ7tMKaHz1Qj+rJJCqljnf4p3A==", + "node_modules/stylis": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", + "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", "license": "MIT" }, - "node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">= 12" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "node_modules/supports-color": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "node_modules/supports-hyperlinks": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", + "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", "dev": true, "license": "MIT", "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=14.18" + }, + "funding": { + "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" } }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", - "license": "MIT", - "dependencies": { - "memory-pager": "^1.0.2" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "node_modules/swc-loader": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/swc-loader/-/swc-loader-0.2.6.tgz", + "integrity": "sha512-9Zi9UP2YmDpgmQVbyOPJClY0dwf58JDyDMQ7uRc4krmc72twNI2fvlBWHLqVekBpPc7h5NJkGVT1zNDxFrqhvg==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "@swc/counter": "^0.1.3" + }, + "peerDependencies": { + "@swc/core": "^1.2.147", + "webpack": ">=2" } }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true, - "license": "CC-BY-3.0" - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "node_modules/synckit": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", + "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", "dev": true, "license": "MIT", "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "@pkgr/core": "^0.2.9" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" } }, - "node_modules/spdx-license-ids": { - "version": "3.0.22", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", - "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "node_modules/table": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", + "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=6.0.0" + "node": ">=10.0.0" } }, - "node_modules/spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "node_modules/table/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", - "dependencies": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" + "engines": { + "node": ">=8" } }, - "node_modules/spdy-transport/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/table/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": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">= 6" + "node": ">=8" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, + "node_modules/tabster": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/tabster/-/tabster-8.5.6.tgz", + "integrity": "sha512-2vfrRGrx8O9BjdrtSlVA5fvpmbq5HQBRN13XFRg6LAvZ1Fr3QdBnswgT4YgFS5Bhoo5nxwgjRaRueI2Us/dv7g==", "license": "MIT", "dependencies": { - "escape-string-regexp": "^2.0.0" + "keyborg": "2.6.0", + "tslib": "^2.8.1" }, - "engines": { - "node": ">=10" + "optionalDependencies": { + "@rollup/rollup-linux-x64-gnu": "4.40.0" } }, - "node_modules/stackframe": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", - "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", - "dev": true, - "license": "MIT" - }, - "node_modules/state-local": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz", - "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==", - "license": "MIT" - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "node_modules/tapable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/stdin-discarder": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", - "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optional": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" } }, - "node_modules/stop-iteration-iterator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", - "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "node_modules/tar-fs/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "es-errors": "^1.3.0", - "internal-slot": "^1.1.0" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">= 6" } }, - "node_modules/streamx": { - "version": "2.23.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", - "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", + "node_modules/tar-fs/node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "dev": true, "license": "MIT", - "dependencies": { - "events-universal": "^1.0.0", - "fast-fifo": "^1.3.2", - "text-decoder": "^1.1.0" + "optional": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" } }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", "dev": true, "license": "MIT", "dependencies": { - "safe-buffer": "~5.1.0" + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" } }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, + "node_modules/tas-client": { + "version": "0.2.33", + "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.2.33.tgz", + "integrity": "sha512-V+uqV66BOQnWxvI6HjDnE4VkInmYZUQ4dgB7gzaDyFyFSK1i1nF/j7DpS9UbQAgV9NaF1XpcyuavnM1qOeiEIg==", "license": "MIT" }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "node_modules/terminal-link": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-4.0.0.tgz", + "integrity": "sha512-lk+vH+MccxNqgVqSnkMVKx4VLJfnLjDBGzH16JVZjKE2DoxP57s6/vt6JmXV5I3jBcfGrxNrYtC+mPtU7WJztA==", "dev": true, "license": "MIT", "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" + "ansi-escapes": "^7.0.0", + "supports-hyperlinks": "^3.2.0" }, "engines": { - "node": ">=10" - } - }, - "node_modules/string-length/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": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/string-length/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==", + "node_modules/terminal-link/node_modules/ansi-escapes": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.2.0.tgz", + "integrity": "sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "environment": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/terser": { + "version": "5.44.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz", + "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/string-width-cjs": { - "name": "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==", + "node_modules/terser-webpack-plugin": { + "version": "5.3.16", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", + "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "serialize-javascript": "^6.0.2", + "terser": "^5.31.1" }, "engines": { - "node": ">=8" + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } } }, - "node_modules/string-width-cjs/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==", + "node_modules/terser-webpack-plugin/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, "engines": { - "node": ">=8" + "node": ">= 10.13.0" } }, - "node_modules/string-width-cjs/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==", + "node_modules/terser-webpack-plugin/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/string-width/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==", + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, - "license": "MIT", + "license": "MIT" + }, + "node_modules/terser/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/string-width/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==", + "node_modules/terser/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, - "node_modules/string.prototype.trim": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", - "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "node_modules/test-exclude": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", + "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-data-property": "^1.1.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-object-atoms": "^1.0.0", - "has-property-descriptors": "^1.0.2" + "@istanbuljs/schema": "^0.1.2", + "glob": "^10.4.1", + "minimatch": "^9.0.4" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", - "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "node_modules/text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "b4a": "^1.6.4" } }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/textextensions": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-6.11.0.tgz", + "integrity": "sha512-tXJwSr9355kFJI3lbCkPpUH5cP8/M0GGy2xLO34aZCjMXBaK3SoPnZwr/oWmo1FdCnELcs4npdCIOFtq9W3ruQ==", "dev": true, - "license": "MIT", + "license": "Artistic-2.0", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "editions": "^6.21.0" }, "engines": { - "node": ">= 0.4" + "node": ">=4" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://bevry.me/fund" } }, - "node_modules/stringify-entities": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", - "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "node_modules/thingies": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.5.0.tgz", + "integrity": "sha512-s+2Bwztg6PhWUD7XMfeYm5qliDdSiZm7M7n8KjTkIsm3l/2lgVRc2/Gx/v+ZX8lT4FMA+i8aQvhcWylldc+ZNw==", + "dev": true, "license": "MIT", - "dependencies": { - "character-entities-html4": "^2.0.0", - "character-entities-legacy": "^3.0.0" + "engines": { + "node": ">=10.18" }, "funding": { "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "^2" } }, - "node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { - "node": ">=12" + "node": ">=12.0.0" }, "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, "engines": { - "node": ">=8" + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "node_modules/strip-ansi-cjs/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==", + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "node_modules/tmp": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=14.14" } }, - "node_modules/strip-dirs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-3.0.0.tgz", - "integrity": "sha512-I0sdgcFTfKQlUPZyAqPJmSG3HLO9rWDFnxonnIbskYNM3DwFOeTNB5KzVq3dA1GdRAc/25b5Y7UO2TQfKWw4aQ==", + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true, - "license": "ISC", - "dependencies": { - "inspect-with-kind": "^1.0.5", - "is-plain-obj": "^1.1.0" - } + "license": "BSD-3-Clause" }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, "engines": { - "node": ">=6" + "node": ">=8.0" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.6" } }, - "node_modules/strtok3": { - "version": "10.3.4", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.4.tgz", - "integrity": "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==", + "node_modules/token-types": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.1.tgz", + "integrity": "sha512-kh9LVIWH5CnL63Ipf0jhlBIy0UsrMj/NJDfpsy1SqOXlLKEVyXXYrnFxFT1yOOYVGBSApeVnjPw/sBz5BfEjAQ==", "dev": true, "license": "MIT", "dependencies": { - "@tokenizer/token": "^0.3.0" + "@borewit/text-codec": "^0.1.0", + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" }, "engines": { - "node": ">=18" + "node": ">=14.16" }, "funding": { "type": "github", "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/structured-source": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/structured-source/-/structured-source-4.0.0.tgz", - "integrity": "sha512-qGzRFNJDjFieQkl/sVOI2dUjHKRyL9dAJi2gCPGJLbJHBIkyOHxjuocpIEfbLioX+qSJpvbYdT49/YCdMznKxA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boundary": "^2.0.0" - } - }, - "node_modules/style-loader": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-4.0.0.tgz", - "integrity": "sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA==", + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", "dev": true, "license": "MIT", "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.27.0" - } - }, - "node_modules/style-to-js": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", - "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", - "license": "MIT", - "dependencies": { - "style-to-object": "1.0.14" + "node": ">=6" } }, - "node_modules/style-to-object": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", - "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", + "node_modules/tr46": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", "license": "MIT", "dependencies": { - "inline-style-parser": "0.2.7" + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" } }, - "node_modules/stylis": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", - "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", - "license": "MIT" - }, - "node_modules/supports-color": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", - "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", + "node_modules/tree-dump": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.1.0.tgz", + "integrity": "sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": ">=18" + "node": ">=10.0" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" } }, - "node_modules/supports-hyperlinks": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", - "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", - "dev": true, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">=14.18" - }, "funding": { - "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/supports-hyperlinks/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=18.12" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "typescript": ">=4.8.4" } }, - "node_modules/swc-loader": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/swc-loader/-/swc-loader-0.2.6.tgz", - "integrity": "sha512-9Zi9UP2YmDpgmQVbyOPJClY0dwf58JDyDMQ7uRc4krmc72twNI2fvlBWHLqVekBpPc7h5NJkGVT1zNDxFrqhvg==", + "node_modules/ts-jest": { + "version": "29.4.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.5.tgz", + "integrity": "sha512-HO3GyiWn2qvTQA4kTgjDcXiMwYQt68a1Y8+JuLRVpdIzm+UOLSHgl/XqR4c6nzJkq5rOkjc02O2I7P7l/Yof0Q==", "dev": true, "license": "MIT", "dependencies": { - "@swc/counter": "^0.1.3" + "bs-logger": "^0.2.6", + "fast-json-stable-stringify": "^2.1.0", + "handlebars": "^4.7.8", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.7.3", + "type-fest": "^4.41.0", + "yargs-parser": "^21.1.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" }, "peerDependencies": { - "@swc/core": "^1.2.147", - "webpack": ">=2" + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0 || ^30.0.0", + "@jest/types": "^29.0.0 || ^30.0.0", + "babel-jest": "^29.0.0 || ^30.0.0", + "jest": "^29.0.0 || ^30.0.0", + "jest-util": "^29.0.0 || ^30.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jest-util": { + "optional": true + } } }, - "node_modules/synckit": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", - "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", + "node_modules/ts-jest/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", "dev": true, - "license": "MIT", - "dependencies": { - "@pkgr/core": "^0.2.9" - }, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": ">=16" }, "funding": { - "url": "https://opencollective.com/synckit" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/table": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", - "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", + "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": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" + "@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" }, - "engines": { - "node": ">=10.0.0" + "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/table/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==", + "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": "MIT", + "license": "BSD-3-Clause", "engines": { - "node": ">=8" + "node": ">=0.3.1" } }, - "node_modules/table/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==", + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" } }, - "node_modules/tabster": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/tabster/-/tabster-8.5.6.tgz", - "integrity": "sha512-2vfrRGrx8O9BjdrtSlVA5fvpmbq5HQBRN13XFRg6LAvZ1Fr3QdBnswgT4YgFS5Bhoo5nxwgjRaRueI2Us/dv7g==", + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, "license": "MIT", "dependencies": { - "keyborg": "2.6.0", - "tslib": "^2.8.1" + "minimist": "^1.2.0" }, - "optionalDependencies": { - "@rollup/rollup-linux-x64-gnu": "4.40.0" + "bin": { + "json5": "lib/cli.js" } }, - "node_modules/tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=4" } }, - "node_modules/tar-fs": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", - "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", "dev": true, "license": "MIT", - "optional": true, - "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" } }, - "node_modules/tar-fs/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "optional": true, "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "safe-buffer": "^5.0.1" }, "engines": { - "node": ">= 6" + "node": "*" } }, - "node_modules/tar-fs/node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "license": "MIT", - "optional": true, - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" + "dependencies": { + "prelude-ls": "^1.2.1" }, "engines": { - "node": ">=6" + "node": ">= 0.8.0" } }, - "node_modules/tar-stream": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", - "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, "license": "MIT", - "dependencies": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" + "engines": { + "node": ">=4" } }, - "node_modules/tas-client": { - "version": "0.2.33", - "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.2.33.tgz", - "integrity": "sha512-V+uqV66BOQnWxvI6HjDnE4VkInmYZUQ4dgB7gzaDyFyFSK1i1nF/j7DpS9UbQAgV9NaF1XpcyuavnM1qOeiEIg==", - "license": "MIT" - }, - "node_modules/terminal-link": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-4.0.0.tgz", - "integrity": "sha512-lk+vH+MccxNqgVqSnkMVKx4VLJfnLjDBGzH16JVZjKE2DoxP57s6/vt6JmXV5I3jBcfGrxNrYtC+mPtU7WJztA==", + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, - "license": "MIT", - "dependencies": { - "ansi-escapes": "^7.0.0", - "supports-hyperlinks": "^3.2.0" - }, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=18" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/terminal-link/node_modules/ansi-escapes": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.2.0.tgz", - "integrity": "sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==", + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, "license": "MIT", "dependencies": { - "environment": "^1.0.0" + "media-typer": "0.3.0", + "mime-types": "~2.1.24" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.6" } }, - "node_modules/terser": { - "version": "5.44.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz", - "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" }, "engines": { - "node": ">=10" + "node": ">= 0.4" } }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.16", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", - "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", - "jest-worker": "^27.4.5", - "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", - "terser": "^5.31.1" + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" }, "engines": { - "node": ">= 10.13.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/terser-webpack-plugin/node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" }, "engines": { - "node": ">= 10.13.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/terser-webpack-plugin/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/terser/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/terser/node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "node_modules/typed-rest-client": { + "version": "1.8.11", + "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.11.tgz", + "integrity": "sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==", "dev": true, "license": "MIT", "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "qs": "^6.9.1", + "tunnel": "0.0.6", + "underscore": "^1.12.1" } }, - "node_modules/test-exclude": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", - "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", - "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^10.4.1", - "minimatch": "^9.0.4" + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" }, "engines": { - "node": ">=18" + "node": ">=14.17" } }, - "node_modules/text-decoder": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", - "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "node_modules/typescript-eslint": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.47.0.tgz", + "integrity": "sha512-Lwe8i2XQ3WoMjua/r1PHrCTpkubPYJCAfOurtn+mtTzqB6jNd+14n9UN1bJ4s3F49x9ixAm0FLflB/JzQ57M8Q==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "b4a": "^1.6.4" + "@typescript-eslint/eslint-plugin": "8.47.0", + "@typescript-eslint/parser": "8.47.0", + "@typescript-eslint/typescript-estree": "8.47.0", + "@typescript-eslint/utils": "8.47.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/project-service": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.47.0.tgz", + "integrity": "sha512-2X4BX8hUeB5JcA1TQJ7GjcgulXQ+5UkNb0DL8gHsHUHdFoiCTJoYLTpib3LtSDPZsRET5ygN4qqIWrHyYIKERA==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.47.0", + "@typescript-eslint/types": "^8.47.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } }, - "node_modules/textextensions": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-6.11.0.tgz", - "integrity": "sha512-tXJwSr9355kFJI3lbCkPpUH5cP8/M0GGy2xLO34aZCjMXBaK3SoPnZwr/oWmo1FdCnELcs4npdCIOFtq9W3ruQ==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/scope-manager": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.47.0.tgz", + "integrity": "sha512-a0TTJk4HXMkfpFkL9/WaGTNuv7JWfFTQFJd6zS9dVAjKsojmv9HT55xzbEpnZoY+VUb+YXLMp+ihMLz/UlZfDg==", "dev": true, - "license": "Artistic-2.0", + "license": "MIT", "dependencies": { - "editions": "^6.21.0" + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/visitor-keys": "8.47.0" }, "engines": { - "node": ">=4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://bevry.me/fund" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/thingies": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.5.0.tgz", - "integrity": "sha512-s+2Bwztg6PhWUD7XMfeYm5qliDdSiZm7M7n8KjTkIsm3l/2lgVRc2/Gx/v+ZX8lT4FMA+i8aQvhcWylldc+ZNw==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.47.0.tgz", + "integrity": "sha512-ybUAvjy4ZCL11uryalkKxuT3w3sXJAuWhOoGS3T/Wu+iUu1tGJmk5ytSY8gbdACNARmcYEB0COksD2j6hfGK2g==", "dev": true, "license": "MIT", "engines": { - "node": ">=10.18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "tslib": "^2" + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true, - "license": "MIT" - }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/types": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.47.0.tgz", + "integrity": "sha512-nHAE6bMKsizhA2uuYZbEbmp5z2UpffNrPEqiKIeN7VsV6UY/roxanWfoRrf6x/k9+Obf+GQdkm0nPU+vnMXo9A==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.47.0.tgz", + "integrity": "sha512-k6ti9UepJf5NpzCjH31hQNLHQWupTRPhZ+KFF8WtTuTpy7uHPfeg2NM7cP27aCGajoEplxJDFVCEm9TGPYyiVg==", "dev": true, "license": "MIT", "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" + "@typescript-eslint/project-service": "8.47.0", + "@typescript-eslint/tsconfig-utils": "8.47.0", + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/visitor-keys": "8.47.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" }, "engines": { - "node": ">=12.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.47.0.tgz", + "integrity": "sha512-g7XrNf25iL4TJOiPqatNuaChyqt49a/onq5YsJ9+hXeugK+41LVg7AxikMfM02PC6jbNtZLCJj6AUcQXJS/jGQ==", "dev": true, "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.47.0", + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/typescript-estree": "8.47.0" + }, "engines": { - "node": ">=12.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependencies": { - "picomatch": "^3 || ^4" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.47.0.tgz", + "integrity": "sha512-SIV3/6eftCy1bNzCQoPmbWsRLujS8t5iDIZ4spZOBHqrM+yfX2ogg8Tt3PDTAVKw3sSCiUgg30uOAvK2r9zGjQ==", "dev": true, "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.47.0", + "eslint-visitor-keys": "^4.2.1" + }, "engines": { - "node": ">=12" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/tmp": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", - "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", "dev": true, - "license": "MIT", + "license": "MIT" + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, "engines": { - "node": ">=14.14" + "node": ">=0.8.0" } }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "node_modules/uint8array-extras": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz", + "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==", "dev": true, - "license": "BSD-3-Clause" + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "node_modules/un-flatten-tree": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/un-flatten-tree/-/un-flatten-tree-2.0.12.tgz", + "integrity": "sha512-E7v59ADEqVQs9gTZYxoe3uGs6Jj/a3gJ7lSJaTIBTc5w0+B3PJ/kVjs/Y/A26NBWEW8WAo556PpRatH4XHZR1w==", + "license": "MIT" + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, "license": "MIT", "dependencies": { - "is-number": "^7.0.0" + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" }, "engines": { - "node": ">=8.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "node_modules/underscore": { + "version": "1.13.7", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", + "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.16.0.tgz", + "integrity": "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.6" + "node": ">=20.18.1" } }, - "node_modules/token-types": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.1.tgz", - "integrity": "sha512-kh9LVIWH5CnL63Ipf0jhlBIy0UsrMj/NJDfpsy1SqOXlLKEVyXXYrnFxFT1yOOYVGBSApeVnjPw/sBz5BfEjAQ==", + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", "dev": true, "license": "MIT", - "dependencies": { - "@borewit/text-codec": "^0.1.0", - "@tokenizer/token": "^0.3.0", - "ieee754": "^1.2.1" - }, "engines": { - "node": ">=14.16" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/totalist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", - "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", - "dev": true, + "node_modules/unified/node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", "license": "MIT", "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tr46": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", - "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", "license": "MIT", "dependencies": { - "punycode": "^2.3.1" + "@types/unist": "^3.0.0" }, - "engines": { - "node": ">=18" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/tree-dump": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.1.0.tgz", - "integrity": "sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10.0" + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/trim-lines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", - "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/trough": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", - "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", - "dev": true, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", "license": "MIT", - "engines": { - "node": ">=18.12" + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" }, - "peerDependencies": { - "typescript": ">=4.8.4" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/ts-jest": { - "version": "29.4.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.5.tgz", - "integrity": "sha512-HO3GyiWn2qvTQA4kTgjDcXiMwYQt68a1Y8+JuLRVpdIzm+UOLSHgl/XqR4c6nzJkq5rOkjc02O2I7P7l/Yof0Q==", + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", - "dependencies": { - "bs-logger": "^0.2.6", - "fast-json-stable-stringify": "^2.1.0", - "handlebars": "^4.7.8", - "json5": "^2.2.3", - "lodash.memoize": "^4.1.2", - "make-error": "^1.3.6", - "semver": "^7.7.3", - "type-fest": "^4.41.0", - "yargs-parser": "^21.1.1" - }, - "bin": { - "ts-jest": "cli.js" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/transform": "^29.0.0 || ^30.0.0", - "@jest/types": "^29.0.0 || ^30.0.0", - "babel-jest": "^29.0.0 || ^30.0.0", - "jest": "^29.0.0 || ^30.0.0", - "jest-util": "^29.0.0 || ^30.0.0", - "typescript": ">=4.3 <6" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@jest/transform": { - "optional": true - }, - "@jest/types": { - "optional": true - }, - "babel-jest": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "jest-util": { - "optional": true - } + "node": ">= 10.0.0" } }, - "node_modules/ts-jest/node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "MIT", "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8" } }, - "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==", + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", "dev": true, + "hasInstallScript": 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" + "napi-postinstall": "^0.3.0" }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" + "funding": { + "url": "https://opencollective.com/unrs-resolver" }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" }, - "@swc/wasm": { - "optional": true + { + "type": "github", + "url": "https://github.com/sponsors/ai" } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "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==", + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" } }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", "dev": true, + "license": "MIT" + }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", "license": "MIT", - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "node_modules/tsconfig-paths/node_modules/json5": { + "node_modules/util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } + "license": "MIT" }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">= 0.4.0" } }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "license": "MIT", - "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "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": "Apache-2.0", - "optional": 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", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", "dependencies": { - "safe-buffer": "^5.0.1" + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" }, "engines": { - "node": "*" + "node": ">=10.12.0" } }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "node_modules/vanilla-calendar-pro": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/vanilla-calendar-pro/-/vanilla-calendar-pro-3.0.5.tgz", + "integrity": "sha512-4X9bmTo1/KzbZrB7B6mZXtvVXIhcKxaVSnFZuaVtps7tshKJDxgaIElkgdia6IjB5qWetWuu7kZ+ZaV1sPxy6w==", + "license": "MIT", + "funding": { + "type": "individual", + "url": "https://buymeacoffee.com/uvarov" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">= 0.8" } }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "node_modules/version-range": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/version-range/-/version-range-4.15.0.tgz", + "integrity": "sha512-Ck0EJbAGxHwprkzFO966t4/5QkRuzh+/I1RxhLgUKKwEn+Cd8NwM60mE3AqBZg5gYODoXW0EFsQvbZjRlvdqbg==", "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "Artistic-2.0", "engines": { - "node": ">=10" + "node": ">=4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://bevry.me/fund" } }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", "license": "MIT", "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" }, - "engines": { - "node": ">= 0.6" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/typed-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", - "dev": true, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vscode-json-languageservice": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-5.6.3.tgz", + "integrity": "sha512-UDF7sJF5t7mzUzXL6dsClkvnHS4xnDL/gOMKGQiizRHmswlk/xSPGZxEvAtszWQF0ImNcJ0j9l+rHuefGzit1w==", + "license": "MIT", + "dependencies": { + "@vscode/l10n": "^0.0.18", + "jsonc-parser": "^3.3.1", + "vscode-languageserver-textdocument": "^1.0.12", + "vscode-languageserver-types": "^3.17.5", + "vscode-uri": "^3.1.0" + } + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=14.0.0" } }, - "node_modules/typed-array-byte-length": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", - "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", - "dev": true, + "node_modules/vscode-languageclient": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz", + "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.14" + "minimatch": "^5.1.0", + "semver": "^7.3.7", + "vscode-languageserver-protocol": "3.17.5" + }, + "engines": { + "vscode": "^1.82.0" + } + }, + "node_modules/vscode-languageclient/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10" } }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", - "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", - "dev": true, + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.15", - "reflect.getprototypeof": "^1.0.9" - }, - "engines": { - "node": ">= 0.4" + "vscode-languageserver-protocol": "3.17.5" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" } }, - "node_modules/typed-array-length": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", - "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", - "dev": true, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0", - "reflect.getprototypeof": "^1.0.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" } }, - "node_modules/typed-rest-client": { - "version": "1.8.11", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.11.tgz", - "integrity": "sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==", - "dev": true, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", + "license": "MIT" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "license": "MIT" + }, + "node_modules/vscode-tas-client": { + "version": "0.1.84", + "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.84.tgz", + "integrity": "sha512-rUTrUopV+70hvx1hW5ebdw1nd6djxubkLvVxjGdyD/r5v/wcVF41LIfiAtbm5qLZDtQdsMH1IaCuDoluoIa88w==", "license": "MIT", "dependencies": { - "qs": "^6.9.1", - "tunnel": "0.0.6", - "underscore": "^1.12.1" + "tas-client": "0.2.33" + }, + "engines": { + "vscode": "^1.85.0" } }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "license": "MIT" + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" + "dependencies": { + "makeerror": "1.0.12" } }, - "node_modules/typescript-eslint": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.47.0.tgz", - "integrity": "sha512-Lwe8i2XQ3WoMjua/r1PHrCTpkubPYJCAfOurtn+mtTzqB6jNd+14n9UN1bJ4s3F49x9ixAm0FLflB/JzQ57M8Q==", + "node_modules/watchpack": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.47.0", - "@typescript-eslint/parser": "8.47.0", - "@typescript-eslint/typescript-estree": "8.47.0", - "@typescript-eslint/utils": "8.47.0" + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" + "node": ">=10.13.0" } }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/project-service": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.47.0.tgz", - "integrity": "sha512-2X4BX8hUeB5JcA1TQJ7GjcgulXQ+5UkNb0DL8gHsHUHdFoiCTJoYLTpib3LtSDPZsRET5ygN4qqIWrHyYIKERA==", + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.47.0", - "@typescript-eslint/types": "^8.47.0", - "debug": "^4.3.4" - }, + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/web-tree-sitter": { + "version": "0.20.8", + "resolved": "https://registry.npmjs.org/web-tree-sitter/-/web-tree-sitter-0.20.8.tgz", + "integrity": "sha512-weOVgZ3aAARgdnb220GqYuh7+rZU0Ka9k9yfKtGAzEYMa6GgiCzW9JjQRJyCJakvibQW+dfjJdihjInKuuCAUQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" + "node": ">=12" } }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/scope-manager": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.47.0.tgz", - "integrity": "sha512-a0TTJk4HXMkfpFkL9/WaGTNuv7JWfFTQFJd6zS9dVAjKsojmv9HT55xzbEpnZoY+VUb+YXLMp+ihMLz/UlZfDg==", + "node_modules/webpack": { + "version": "5.105.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.0.tgz", + "integrity": "sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.47.0", - "@typescript-eslint/visitor-keys": "8.47.0" + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.15.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.28.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.19.0", + "es-module-lexer": "^2.0.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.3.1", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "terser-webpack-plugin": "^5.3.16", + "watchpack": "^2.5.1", + "webpack-sources": "^3.3.3" + }, + "bin": { + "webpack": "bin/webpack.js" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=10.13.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } } }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.47.0.tgz", - "integrity": "sha512-ybUAvjy4ZCL11uryalkKxuT3w3sXJAuWhOoGS3T/Wu+iUu1tGJmk5ytSY8gbdACNARmcYEB0COksD2j6hfGK2g==", + "node_modules/webpack-bundle-analyzer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-5.0.1.tgz", + "integrity": "sha512-PUp3YFOHysSw8t+13rcF+8o5SGaP/AZ5KnIF3qJfFodv4xJkmixnfcyy+LOwNadpzvyrEKpaMlewAG2sFUfdpw==", "dev": true, "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "dependencies": { + "@discoveryjs/json-ext": "0.5.7", + "acorn": "^8.0.4", + "acorn-walk": "^8.0.0", + "commander": "^7.2.0", + "debounce": "^1.2.1", + "escape-string-regexp": "^4.0.0", + "html-escaper": "^2.0.2", + "opener": "^1.5.2", + "picocolors": "^1.0.0", + "sirv": "^2.0.3", + "ws": "^7.3.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "bin": { + "webpack-bundle-analyzer": "lib/bin/analyzer.js" }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" + "engines": { + "node": ">= 20.9.0" } }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/types": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.47.0.tgz", - "integrity": "sha512-nHAE6bMKsizhA2uuYZbEbmp5z2UpffNrPEqiKIeN7VsV6UY/roxanWfoRrf6x/k9+Obf+GQdkm0nPU+vnMXo9A==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node_modules/webpack-bundle-analyzer/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" } }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.47.0.tgz", - "integrity": "sha512-k6ti9UepJf5NpzCjH31hQNLHQWupTRPhZ+KFF8WtTuTpy7uHPfeg2NM7cP27aCGajoEplxJDFVCEm9TGPYyiVg==", + "node_modules/webpack-bundle-analyzer/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.47.0", - "@typescript-eslint/tsconfig-utils": "8.47.0", - "@typescript-eslint/types": "8.47.0", - "@typescript-eslint/visitor-keys": "8.47.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" - }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.47.0.tgz", - "integrity": "sha512-g7XrNf25iL4TJOiPqatNuaChyqt49a/onq5YsJ9+hXeugK+41LVg7AxikMfM02PC6jbNtZLCJj6AUcQXJS/jGQ==", + "node_modules/webpack-cli": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-6.0.1.tgz", + "integrity": "sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.47.0", - "@typescript-eslint/types": "8.47.0", - "@typescript-eslint/typescript-estree": "8.47.0" + "@discoveryjs/json-ext": "^0.6.1", + "@webpack-cli/configtest": "^3.0.1", + "@webpack-cli/info": "^3.0.1", + "@webpack-cli/serve": "^3.0.1", + "colorette": "^2.0.14", + "commander": "^12.1.0", + "cross-spawn": "^7.0.3", + "envinfo": "^7.14.0", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^6.0.1" + }, + "bin": { + "webpack-cli": "bin/cli.js" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18.12.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" + "webpack": "^5.82.0" + }, + "peerDependenciesMeta": { + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } } }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.47.0.tgz", - "integrity": "sha512-SIV3/6eftCy1bNzCQoPmbWsRLujS8t5iDIZ4spZOBHqrM+yfX2ogg8Tt3PDTAVKw3sSCiUgg30uOAvK2r9zGjQ==", + "node_modules/webpack-cli/node_modules/@discoveryjs/json-ext": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.3.tgz", + "integrity": "sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==", "dev": true, "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.47.0", - "eslint-visitor-keys": "^4.2.1" - }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=14.17.0" } }, - "node_modules/uc.micro": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "dev": true, - "license": "MIT" - }, - "node_modules/uglify-js": { - "version": "3.19.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", - "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "node_modules/webpack-cli/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, + "license": "MIT", "engines": { - "node": ">=0.8.0" + "node": ">=18" } }, - "node_modules/uint8array-extras": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz", - "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==", + "node_modules/webpack-dev-middleware": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.5.tgz", + "integrity": "sha512-uxQ6YqGdE4hgDKNf7hUiPXOdtkXvBJXrfEGYSx7P7LC8hnUYGK70X6xQXUvXeNyBDDcsiQXpG2m3G9vxowaEuA==", "dev": true, "license": "MIT", + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^4.43.1", + "mime-types": "^3.0.1", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, "engines": { - "node": ">=18" + "node": ">= 18.12.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } } }, - "node_modules/un-flatten-tree": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/un-flatten-tree/-/un-flatten-tree-2.0.12.tgz", - "integrity": "sha512-E7v59ADEqVQs9gTZYxoe3uGs6Jj/a3gJ7lSJaTIBTc5w0+B3PJ/kVjs/Y/A26NBWEW8WAo556PpRatH4XHZR1w==", - "license": "MIT" - }, - "node_modules/unbox-primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", - "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "node_modules/webpack-dev-middleware/node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "has-bigints": "^1.0.2", - "has-symbols": "^1.1.0", - "which-boxed-primitive": "^1.1.1" + "mime-db": "^1.54.0" }, "engines": { - "node": ">= 0.4" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "node_modules/webpack-dev-server": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.2.tgz", + "integrity": "sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg==", "dev": true, "license": "MIT", "dependencies": { - "buffer": "^5.2.1", - "through": "^2.3.8" - } - }, - "node_modules/underscore": { - "version": "1.13.7", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", - "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", - "dev": true, - "license": "MIT" - }, - "node_modules/undici": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.16.0.tgz", - "integrity": "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==", - "dev": true, - "license": "MIT", + "@types/bonjour": "^3.5.13", + "@types/connect-history-api-fallback": "^1.5.4", + "@types/express": "^4.17.21", + "@types/express-serve-static-core": "^4.17.21", + "@types/serve-index": "^1.9.4", + "@types/serve-static": "^1.15.5", + "@types/sockjs": "^0.3.36", + "@types/ws": "^8.5.10", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.2.1", + "chokidar": "^3.6.0", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "express": "^4.21.2", + "graceful-fs": "^4.2.6", + "http-proxy-middleware": "^2.0.9", + "ipaddr.js": "^2.1.0", + "launch-editor": "^2.6.1", + "open": "^10.0.3", + "p-retry": "^6.2.0", + "schema-utils": "^4.2.0", + "selfsigned": "^2.4.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^7.4.2", + "ws": "^8.18.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, "engines": { - "node": ">=20.18.1" + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } } - }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/unicorn-magic": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", - "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + }, + "node_modules/webpack-dev-server/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, "engines": { - "node": ">=18" + "node": ">= 8.10.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/unified": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", - "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "node_modules/webpack-dev-server/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0", - "bail": "^2.0.0", - "devlop": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^6.0.0" + "picomatch": "^2.2.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=8.10.0" } }, - "node_modules/unified/node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "node_modules/webpack-dev-server/node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "dev": true, "license": "MIT", "engines": { - "node": ">=12" + "node": ">=10.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/unist-util-is": { + "node_modules/webpack-merge": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", - "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0" + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/unist-util-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", - "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "node_modules/webpack-sources": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", + "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=10.13.0" } }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", - "license": "MIT", + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@types/unist": "^3.0.0" + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=8.0.0" } }, - "node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" } }, - "node_modules/unist-util-visit-parents": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", - "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", - "license": "MIT", + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=0.8.0" } }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": ">= 10.0.0" + "node": ">=0.8.0" } }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", "dev": true, "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, "engines": { - "node": ">= 0.8" + "node": ">=18" } }, - "node_modules/unrs-resolver": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", - "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", "dev": true, - "hasInstallScript": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", "license": "MIT", "dependencies": { - "napi-postinstall": "^0.3.0" - }, - "funding": { - "url": "https://opencollective.com/unrs-resolver" + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" }, - "optionalDependencies": { - "@unrs/resolver-binding-android-arm-eabi": "1.11.1", - "@unrs/resolver-binding-android-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-x64": "1.11.1", - "@unrs/resolver-binding-freebsd-x64": "1.11.1", - "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", - "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", - "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-musl": "1.11.1", - "@unrs/resolver-binding-wasm32-wasi": "1.11.1", - "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", - "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", - "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + "engines": { + "node": ">=18" } }, - "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", + "license": "ISC", "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" + "isexe": "^2.0.0" }, "bin": { - "update-browserslist-db": "cli.js" + "node-which": "bin/node-which" }, - "peerDependencies": { - "browserslist": ">= 4.21.0" + "engines": { + "node": ">= 8" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "punycode": "^2.1.0" + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/url-join": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", - "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", "dev": true, - "license": "MIT" - }, - "node_modules/use-sync-external-store": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", - "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", "license": "MIT", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/which-builtin-type/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true, "license": "MIT" }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, "engines": { - "node": ">= 0.4.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "dev": true, "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", "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", - "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, - "license": "ISC", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, + "license": "MIT", "engines": { - "node": ">=10.12.0" + "node": ">=0.10.0" } }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "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": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/vanilla-calendar-pro": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/vanilla-calendar-pro/-/vanilla-calendar-pro-3.0.5.tgz", - "integrity": "sha512-4X9bmTo1/KzbZrB7B6mZXtvVXIhcKxaVSnFZuaVtps7tshKJDxgaIElkgdia6IjB5qWetWuu7kZ+ZaV1sPxy6w==", - "license": "MIT", - "funding": { - "type": "individual", - "url": "https://buymeacoffee.com/uvarov" - } + "license": "MIT" }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "node_modules/workerpool": { + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz", + "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } + "license": "Apache-2.0" }, - "node_modules/version-range": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/version-range/-/version-range-4.15.0.tgz", - "integrity": "sha512-Ck0EJbAGxHwprkzFO966t4/5QkRuzh+/I1RxhLgUKKwEn+Cd8NwM60mE3AqBZg5gYODoXW0EFsQvbZjRlvdqbg==", + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, - "license": "Artistic-2.0", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, "engines": { - "node": ">=4" + "node": ">=12" }, "funding": { - "url": "https://bevry.me/fund" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/vfile": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", - "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "node_modules/wrap-ansi-cjs": { + "name": "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": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/vfile-message": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", - "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "node_modules/wrap-ansi-cjs/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", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=8" } }, - "node_modules/vscode-json-languageservice": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-5.6.3.tgz", - "integrity": "sha512-UDF7sJF5t7mzUzXL6dsClkvnHS4xnDL/gOMKGQiizRHmswlk/xSPGZxEvAtszWQF0ImNcJ0j9l+rHuefGzit1w==", + "node_modules/wrap-ansi-cjs/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": { - "@vscode/l10n": "^0.0.18", - "jsonc-parser": "^3.3.1", - "vscode-languageserver-textdocument": "^1.0.12", - "vscode-languageserver-types": "^3.17.5", - "vscode-uri": "^3.1.0" + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/vscode-jsonrpc": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", - "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, "license": "MIT", "engines": { - "node": ">=14.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/vscode-languageclient": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz", - "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==", + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, "license": "MIT", "dependencies": { - "minimatch": "^5.1.0", - "semver": "^7.3.7", - "vscode-languageserver-protocol": "3.17.5" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "vscode": "^1.82.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/vscode-languageclient/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "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/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">=10" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/vscode-languageserver": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", - "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", - "license": "MIT", - "dependencies": { - "vscode-languageserver-protocol": "3.17.5" + "node_modules/write-file-atomic/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" }, - "bin": { - "installServerIntoExtension": "bin/installServerIntoExtension" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/vscode-languageserver-protocol": { - "version": "3.17.5", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", - "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "dev": true, "license": "MIT", - "dependencies": { - "vscode-jsonrpc": "8.2.0", - "vscode-languageserver-types": "3.17.5" + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", - "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", - "license": "MIT" - }, - "node_modules/vscode-languageserver-types": { - "version": "3.17.5", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", - "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", - "license": "MIT" - }, - "node_modules/vscode-tas-client": { - "version": "0.1.84", - "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.84.tgz", - "integrity": "sha512-rUTrUopV+70hvx1hW5ebdw1nd6djxubkLvVxjGdyD/r5v/wcVF41LIfiAtbm5qLZDtQdsMH1IaCuDoluoIa88w==", + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", "license": "MIT", "dependencies": { - "tas-client": "0.2.33" + "is-wsl": "^3.1.0" }, "engines": { - "vscode": "^1.85.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/vscode-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", - "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", - "license": "MIT" - }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "node_modules/xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", + "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "makeerror": "1.0.12" - } + "license": "MIT" }, - "node_modules/watchpack": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", - "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", + "node_modules/xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", "dev": true, "license": "MIT", "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" }, "engines": { - "node": ">=10.13.0" + "node": ">=4.0.0" } }, - "node_modules/wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", "dev": true, "license": "MIT", - "dependencies": { - "minimalistic-assert": "^1.0.0" + "engines": { + "node": ">=4.0" } }, - "node_modules/web-tree-sitter": { - "version": "0.20.8", - "resolved": "https://registry.npmjs.org/web-tree-sitter/-/web-tree-sitter-0.20.8.tgz", - "integrity": "sha512-weOVgZ3aAARgdnb220GqYuh7+rZU0Ka9k9yfKtGAzEYMa6GgiCzW9JjQRJyCJakvibQW+dfjJdihjInKuuCAUQ==", + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, - "license": "MIT" - }, - "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "license": "BSD-2-Clause", + "license": "ISC", "engines": { - "node": ">=12" + "node": ">=10" } }, - "node_modules/webpack": { - "version": "5.105.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.0.tgz", - "integrity": "sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw==", + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true, - "license": "MIT", - "dependencies": { - "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.8", - "@types/json-schema": "^7.0.15", - "@webassemblyjs/ast": "^1.14.1", - "@webassemblyjs/wasm-edit": "^1.14.1", - "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.15.0", - "acorn-import-phases": "^1.0.3", - "browserslist": "^4.28.1", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.19.0", - "es-module-lexer": "^2.0.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.3.1", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^4.3.3", - "tapable": "^2.3.0", - "terser-webpack-plugin": "^5.3.16", - "watchpack": "^2.5.1", - "webpack-sources": "^3.3.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } + "license": "ISC" }, - "node_modules/webpack-bundle-analyzer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-5.0.1.tgz", - "integrity": "sha512-PUp3YFOHysSw8t+13rcF+8o5SGaP/AZ5KnIF3qJfFodv4xJkmixnfcyy+LOwNadpzvyrEKpaMlewAG2sFUfdpw==", + "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": { - "@discoveryjs/json-ext": "0.5.7", - "acorn": "^8.0.4", - "acorn-walk": "^8.0.0", - "commander": "^7.2.0", - "debounce": "^1.2.1", - "escape-string-regexp": "^4.0.0", - "html-escaper": "^2.0.2", - "opener": "^1.5.2", - "picocolors": "^1.0.0", - "sirv": "^2.0.3", - "ws": "^7.3.1" - }, - "bin": { - "webpack-bundle-analyzer": "lib/bin/analyzer.js" + "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": ">= 20.9.0" + "node": ">=12" } }, - "node_modules/webpack-bundle-analyzer/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "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/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, "license": "MIT", + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, "engines": { - "node": ">= 10" + "node": ">=10" } }, - "node_modules/webpack-bundle-analyzer/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/yargs-unparser/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "license": "MIT", "engines": { @@ -21393,843 +23179,1285 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/webpack-cli": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-6.0.1.tgz", - "integrity": "sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw==", + "node_modules/yargs-unparser/node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, "license": "MIT", - "dependencies": { - "@discoveryjs/json-ext": "^0.6.1", - "@webpack-cli/configtest": "^3.0.1", - "@webpack-cli/info": "^3.0.1", - "@webpack-cli/serve": "^3.0.1", - "colorette": "^2.0.14", - "commander": "^12.1.0", - "cross-spawn": "^7.0.3", - "envinfo": "^7.14.0", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^3.1.1", - "rechoir": "^0.8.0", - "webpack-merge": "^6.0.1" - }, - "bin": { - "webpack-cli": "bin/cli.js" - }, "engines": { - "node": ">=18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.82.0" - }, - "peerDependenciesMeta": { - "webpack-bundle-analyzer": { - "optional": true - }, - "webpack-dev-server": { - "optional": true - } + "node": ">=8" } }, - "node_modules/webpack-cli/node_modules/@discoveryjs/json-ext": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.3.tgz", - "integrity": "sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==", + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", "dev": true, "license": "MIT", - "engines": { - "node": ">=14.17.0" + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" } }, - "node_modules/webpack-cli/node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "node_modules/yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3" + } + }, + "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": ">=18" + "node": ">=6" } }, - "node_modules/webpack-dev-middleware": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.5.tgz", - "integrity": "sha512-uxQ6YqGdE4hgDKNf7hUiPXOdtkXvBJXrfEGYSx7P7LC8hnUYGK70X6xQXUvXeNyBDDcsiQXpG2m3G9vxowaEuA==", + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "license": "MIT", - "dependencies": { - "colorette": "^2.0.10", - "memfs": "^4.43.1", - "mime-types": "^3.0.1", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, "engines": { - "node": ">= 18.12.0" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - } + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/webpack-dev-middleware/node_modules/mime-types": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", - "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "node_modules/zod": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.13.tgz", + "integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "packages/documentdb-constants": { + "name": "@vscode-documentdb/documentdb-constants", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "@types/jest": "^29.5.14", + "jest": "^29.7.0", + "prettier": "~3.6.2", + "ts-jest": "^29.3.4", + "ts-node": "^10.9.2" + } + }, + "packages/documentdb-constants/node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" + }, + "packages/documentdb-constants/node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "license": "MIT", "dependencies": { - "mime-db": "^1.54.0" + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" }, "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/webpack-dev-server": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.2.tgz", - "integrity": "sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg==", + "packages/documentdb-constants/node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, "license": "MIT", "dependencies": { - "@types/bonjour": "^3.5.13", - "@types/connect-history-api-fallback": "^1.5.4", - "@types/express": "^4.17.21", - "@types/express-serve-static-core": "^4.17.21", - "@types/serve-index": "^1.9.4", - "@types/serve-static": "^1.15.5", - "@types/sockjs": "^0.3.36", - "@types/ws": "^8.5.10", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.2.1", - "chokidar": "^3.6.0", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "express": "^4.21.2", - "graceful-fs": "^4.2.6", - "http-proxy-middleware": "^2.0.9", - "ipaddr.js": "^2.1.0", - "launch-editor": "^2.6.1", - "open": "^10.0.3", - "p-retry": "^6.2.0", - "schema-utils": "^4.2.0", - "selfsigned": "^2.4.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^7.4.2", - "ws": "^8.18.0" - }, - "bin": { - "webpack-dev-server": "bin/webpack-dev-server.js" - }, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { - "webpack": "^5.0.0" + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "peerDependenciesMeta": { - "webpack": { - "optional": true - }, - "webpack-cli": { + "node-notifier": { "optional": true } } }, - "node_modules/webpack-dev-server/node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "packages/documentdb-constants/node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, "license": "MIT", "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" }, "engines": { - "node": ">= 8.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/documentdb-constants/node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/documentdb-constants/node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/webpack-dev-server/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "packages/documentdb-constants/node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, "license": "MIT", "dependencies": { - "picomatch": "^2.2.1" + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": ">=8.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "packages/documentdb-constants/node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, "engines": { - "node": ">=10.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/documentdb-constants/node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { + "node-notifier": { "optional": true } } }, - "node_modules/webpack-merge": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", - "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "packages/documentdb-constants/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "license": "MIT", "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.1" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": ">=18.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/webpack-sources": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "packages/documentdb-constants/node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, "engines": { - "node": ">=10.13.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/webpack/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "packages/documentdb-constants/node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" }, "engines": { - "node": ">=8.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/webpack/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "packages/documentdb-constants/node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, "engines": { - "node": ">=4.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "packages/documentdb-constants/node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" }, "engines": { - "node": ">=0.8.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "packages/documentdb-constants/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, "engines": { - "node": ">=0.8.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/whatwg-encoding": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", - "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "packages/documentdb-constants/node_modules/@sinclair/typebox": { + "version": "0.27.10", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", + "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==", + "dev": true, + "license": "MIT" + }, + "packages/documentdb-constants/node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "packages/documentdb-constants/node_modules/@types/jest": { + "version": "29.5.14", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", + "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", "dev": true, "license": "MIT", "dependencies": { - "iconv-lite": "0.6.3" - }, - "engines": { - "node": ">=18" + "expect": "^29.0.0", + "pretty-format": "^29.0.0" } }, - "node_modules/whatwg-mimetype": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", - "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "packages/documentdb-constants/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": ">=18" + "node": ">=8" } }, - "node_modules/whatwg-url": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", - "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "packages/documentdb-constants/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, "license": "MIT", - "dependencies": { - "tr46": "^5.1.0", - "webidl-conversions": "^7.0.0" - }, "engines": { - "node": ">=18" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "packages/documentdb-constants/node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" }, "engines": { - "node": ">= 8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" } }, - "node_modules/which-boxed-primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", - "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "packages/documentdb-constants/node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "is-bigint": "^1.1.0", - "is-boolean-object": "^1.2.1", - "is-number-object": "^1.1.1", - "is-string": "^1.1.1", - "is-symbol": "^1.1.1" + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/which-builtin-type": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", - "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "packages/documentdb-constants/node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "call-bound": "^1.0.2", - "function.prototype.name": "^1.1.6", - "has-tostringtag": "^1.0.2", - "is-async-function": "^2.0.0", - "is-date-object": "^1.1.0", - "is-finalizationregistry": "^1.1.0", - "is-generator-function": "^1.0.10", - "is-regex": "^1.2.1", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.1.0", - "which-collection": "^1.0.2", - "which-typed-array": "^1.1.16" + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/which-builtin-type/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "packages/documentdb-constants/node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "MIT" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } }, - "node_modules/which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "packages/documentdb-constants/node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dev": true, "license": "MIT", "dependencies": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/which-typed-array": { - "version": "1.1.19", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", - "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "packages/documentdb-constants/node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "for-each": "^0.3.5", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2" + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/wildcard": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", - "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "packages/documentdb-constants/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "packages/documentdb-constants/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "packages/documentdb-constants/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, - "license": "MIT" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "node_modules/workerpool": { - "version": "9.3.4", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz", - "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==", + "packages/documentdb-constants/node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", "dev": true, - "license": "Apache-2.0" + "license": "MIT" }, - "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "packages/documentdb-constants/node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/documentdb-constants/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "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/chalk/wrap-ansi?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/wrap-ansi-cjs": { - "name": "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==", + "packages/documentdb-constants/node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi-cjs/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==", + "packages/documentdb-constants/node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/wrap-ansi-cjs/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==", + "packages/documentdb-constants/node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "packages/documentdb-constants/node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "packages/documentdb-constants/node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "packages/documentdb-constants/node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dev": true, "license": "MIT", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } } }, - "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==", + "packages/documentdb-constants/node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, - "license": "ISC", - "optional": true + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/write-file-atomic": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", - "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "packages/documentdb-constants/node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" + "detect-newline": "^3.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/write-file-atomic/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "packages/documentdb-constants/node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "packages/documentdb-constants/node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dev": true, "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, "engines": { - "node": ">=8.3.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/documentdb-constants/node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/wsl-utils": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", - "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "packages/documentdb-constants/node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, "license": "MIT", "dependencies": { - "is-wsl": "^3.1.0" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/xml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", + "packages/documentdb-constants/node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/xml2js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", - "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "packages/documentdb-constants/node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, "license": "MIT", "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { - "node": ">=4.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "packages/documentdb-constants/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, "engines": { - "node": ">=4.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "packages/documentdb-constants/node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, - "license": "ISC", + "license": "MIT", "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "packages/documentdb-constants/node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "packages/documentdb-constants/node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dev": true, "license": "MIT", "dependencies": { - "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" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" }, "engines": { - "node": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "packages/documentdb-constants/node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, - "license": "ISC", + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, "engines": { - "node": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "packages/documentdb-constants/node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", "dev": true, "license": "MIT", "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "packages/documentdb-constants/node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/yargs-unparser/node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "packages/documentdb-constants/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "packages/documentdb-constants/node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, "license": "MIT", "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/yazl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", - "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "packages/documentdb-constants/node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dev": true, "license": "MIT", "dependencies": { - "buffer-crc32": "~0.2.3" + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "packages/documentdb-constants/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, "engines": { - "node": ">=6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "packages/documentdb-constants/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=10" + "node": "*" + } + }, + "packages/documentdb-constants/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/zod": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.13.tgz", - "integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==", + "packages/documentdb-constants/node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "packages/documentdb-constants/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "packages/documentdb-constants/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "packages/documentdb-constants/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", - "funding": { - "url": "https://github.com/sponsors/colinhacks" + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "packages/documentdb-constants/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "packages/documentdb-constants": { - "name": "@vscode-documentdb/documentdb-constants", - "version": "1.0.0", - "license": "MIT", - "devDependencies": { - "prettier": "~3.6.2", - "ts-node": "^10.9.2" + "packages/documentdb-constants/node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "packages/documentdb-constants/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "packages/schema-analyzer": { diff --git a/packages/documentdb-constants/jest.config.js b/packages/documentdb-constants/jest.config.js index 388d1e1d1..a39810b1f 100644 --- a/packages/documentdb-constants/jest.config.js +++ b/packages/documentdb-constants/jest.config.js @@ -1,7 +1,10 @@ /** @type {import('ts-jest').JestConfigWithTsJest} **/ module.exports = { + // Limit workers to avoid OOM kills on machines with many cores. + // Each ts-jest worker loads the TypeScript compiler and consumes ~500MB+. + maxWorkers: '50%', testEnvironment: 'node', - testMatch: ['/test/**/*.test.ts'], + testMatch: ['/src/**/*.test.ts'], transform: { '^.+\\.tsx?$': ['ts-jest', {}], }, diff --git a/packages/documentdb-constants/package.json b/packages/documentdb-constants/package.json index cb612d748..1b78cae79 100644 --- a/packages/documentdb-constants/package.json +++ b/packages/documentdb-constants/package.json @@ -23,7 +23,10 @@ }, "license": "MIT", "devDependencies": { - "ts-node": "^10.9.2", - "prettier": "~3.6.2" + "@types/jest": "^29.5.14", + "jest": "^29.7.0", + "prettier": "~3.6.2", + "ts-jest": "^29.3.4", + "ts-node": "^10.9.2" } } diff --git a/packages/documentdb-constants/src/docLinks.test.ts b/packages/documentdb-constants/src/docLinks.test.ts new file mode 100644 index 000000000..444b5423e --- /dev/null +++ b/packages/documentdb-constants/src/docLinks.test.ts @@ -0,0 +1,72 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Unit tests for docLinks.ts — URL generation for DocumentDB operator docs. + */ + +import { getDocBase, getDocLink } from './index'; + +describe('docLinks', () => { + test('getDocBase returns the expected base URL', () => { + expect(getDocBase()).toBe('https://learn.microsoft.com/en-us/azure/documentdb/operators'); + }); + + describe('getDocLink', () => { + test('generates correct URL for comparison query operator', () => { + const link = getDocLink('$eq', 'query:comparison'); + expect(link).toBe('https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$eq'); + }); + + test('generates correct URL for aggregation stage', () => { + const link = getDocLink('$match', 'stage'); + expect(link).toBe('https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$match'); + }); + + test('generates correct URL for accumulator', () => { + const link = getDocLink('$sum', 'accumulator'); + expect(link).toBe('https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$sum'); + }); + + test('generates correct URL for field update operator', () => { + const link = getDocLink('$set', 'update:field'); + expect(link).toBe('https://learn.microsoft.com/en-us/azure/documentdb/operators/field-update/$set'); + }); + + test('generates correct URL for array expression operator', () => { + const link = getDocLink('$filter', 'expr:array'); + expect(link).toBe('https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$filter'); + }); + + test('generates correct URL for type expression operator (nested dir)', () => { + const link = getDocLink('$convert', 'expr:type'); + expect(link).toBe( + 'https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/type-expression/$convert', + ); + }); + + test('generates correct URL for window operator', () => { + const link = getDocLink('$rank', 'window'); + expect(link).toBe('https://learn.microsoft.com/en-us/azure/documentdb/operators/window-operators/$rank'); + }); + + test('lowercases operator names in URLs', () => { + const link = getDocLink('$AddFields', 'stage'); + expect(link).toBe('https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$addfields'); + }); + + test('returns undefined for unknown meta tag', () => { + expect(getDocLink('$eq', 'unknown:tag')).toBeUndefined(); + }); + + test('returns undefined for BSON meta tag (no docs directory)', () => { + expect(getDocLink('ObjectId', 'bson')).toBeUndefined(); + }); + + test('returns undefined for variable meta tag (no docs directory)', () => { + expect(getDocLink('$$NOW', 'variable')).toBeUndefined(); + }); + }); +}); diff --git a/packages/documentdb-constants/src/getFilteredCompletions.test.ts b/packages/documentdb-constants/src/getFilteredCompletions.test.ts new file mode 100644 index 000000000..b188dbc47 --- /dev/null +++ b/packages/documentdb-constants/src/getFilteredCompletions.test.ts @@ -0,0 +1,222 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Unit tests for getFilteredCompletions and completion presets. + */ + +import { + EXPRESSION_COMPLETION_META, + FILTER_COMPLETION_META, + GROUP_EXPRESSION_COMPLETION_META, + PROJECTION_COMPLETION_META, + STAGE_COMPLETION_META, + UPDATE_COMPLETION_META, + WINDOW_COMPLETION_META, + getAllCompletions, + getFilteredCompletions, +} from './index'; + +describe('getFilteredCompletions', () => { + test('returns all operators when filtering by all top-level meta prefixes', () => { + const all = getAllCompletions(); + expect(all.length).toBeGreaterThan(0); + }); + + test('filtering by "query" returns only query operators', () => { + const results = getFilteredCompletions({ meta: ['query'] }); + expect(results.length).toBeGreaterThan(0); + for (const r of results) { + expect(r.meta).toMatch(/^query/); + } + }); + + test('filtering by "query:comparison" returns only comparison operators', () => { + const results = getFilteredCompletions({ meta: ['query:comparison'] }); + expect(results.length).toBe(8); // $eq, $gt, $gte, $in, $lt, $lte, $ne, $nin + for (const r of results) { + expect(r.meta).toBe('query:comparison'); + } + }); + + test('filtering by "stage" returns aggregation pipeline stages', () => { + const results = getFilteredCompletions({ meta: ['stage'] }); + expect(results.length).toBe(35); + for (const r of results) { + expect(r.meta).toBe('stage'); + } + }); + + test('filtering by "update" returns all update operators', () => { + const results = getFilteredCompletions({ meta: ['update'] }); + expect(results.length).toBe(22); + for (const r of results) { + expect(r.meta).toMatch(/^update/); + } + }); + + test('filtering by "accumulator" returns accumulator operators', () => { + const results = getFilteredCompletions({ meta: ['accumulator'] }); + expect(results.length).toBe(21); + for (const r of results) { + expect(r.meta).toBe('accumulator'); + } + }); + + test('filtering by "expr" returns all expression operators', () => { + const results = getFilteredCompletions({ meta: ['expr'] }); + expect(results.length).toBeGreaterThan(100); + for (const r of results) { + expect(r.meta).toMatch(/^expr:/); + } + }); + + test('filtering by "window" returns window operators', () => { + const results = getFilteredCompletions({ meta: ['window'] }); + expect(results.length).toBe(27); + for (const r of results) { + expect(r.meta).toBe('window'); + } + }); + + test('filtering by "bson" returns BSON constructors', () => { + const results = getFilteredCompletions({ meta: ['bson'] }); + expect(results.length).toBe(10); + for (const r of results) { + expect(r.meta).toBe('bson'); + } + }); + + test('filtering by "variable" returns system variables', () => { + const results = getFilteredCompletions({ meta: ['variable'] }); + expect(results.length).toBe(7); + for (const r of results) { + expect(r.meta).toBe('variable'); + } + }); + + test('filtering by multiple meta tags combines results', () => { + const queryOnly = getFilteredCompletions({ meta: ['query'] }); + const stageOnly = getFilteredCompletions({ meta: ['stage'] }); + const combined = getFilteredCompletions({ meta: ['query', 'stage'] }); + expect(combined.length).toBe(queryOnly.length + stageOnly.length); + }); + + test('empty meta array returns no results', () => { + const results = getFilteredCompletions({ meta: [] }); + expect(results.length).toBe(0); + }); + + test('unknown meta tag returns no results', () => { + const results = getFilteredCompletions({ meta: ['nonexistent'] }); + expect(results.length).toBe(0); + }); + + describe('BSON type filtering', () => { + test('filtering by bsonTypes narrows type-specific operators', () => { + const allQuery = getFilteredCompletions({ meta: ['query'] }); + const stringOnly = getFilteredCompletions({ + meta: ['query'], + bsonTypes: ['string'], + }); + // String-only should have fewer or equal operators (universal + string-specific) + expect(stringOnly.length).toBeLessThanOrEqual(allQuery.length); + expect(stringOnly.length).toBeGreaterThan(0); + }); + + test('universal operators (no applicableBsonTypes) always pass BSON filter', () => { + const withBsonFilter = getFilteredCompletions({ + meta: ['query:comparison'], + bsonTypes: ['string'], + }); + // All comparison operators are universal + expect(withBsonFilter.length).toBe(8); + }); + + test('type-specific operators are excluded when BSON type does not match', () => { + const stringOps = getFilteredCompletions({ + meta: ['query'], + bsonTypes: ['number'], + }); + // $regex should NOT be included (it's string-only) + const hasRegex = stringOps.some((op) => op.value === '$regex'); + expect(hasRegex).toBe(false); + }); + + test('type-specific operators are included when BSON type matches', () => { + const stringOps = getFilteredCompletions({ + meta: ['query'], + bsonTypes: ['string'], + }); + // $regex should be included for string type + const hasRegex = stringOps.some((op) => op.value === '$regex'); + expect(hasRegex).toBe(true); + }); + }); +}); + +describe('completion context presets', () => { + test('FILTER_COMPLETION_META returns query + bson + variable', () => { + const results = getFilteredCompletions({ meta: FILTER_COMPLETION_META }); + const metas = new Set(results.map((r) => r.meta.split(':')[0])); + expect(metas).toContain('query'); + expect(metas).toContain('bson'); + expect(metas).toContain('variable'); + expect(metas).not.toContain('stage'); + expect(metas).not.toContain('update'); + }); + + test('STAGE_COMPLETION_META returns only stages', () => { + const results = getFilteredCompletions({ meta: STAGE_COMPLETION_META }); + expect(results.length).toBe(35); + for (const r of results) { + expect(r.meta).toBe('stage'); + } + }); + + test('UPDATE_COMPLETION_META returns only update operators', () => { + const results = getFilteredCompletions({ meta: UPDATE_COMPLETION_META }); + expect(results.length).toBe(22); + for (const r of results) { + expect(r.meta).toMatch(/^update/); + } + }); + + test('GROUP_EXPRESSION_COMPLETION_META returns expr + accumulator + bson + variable', () => { + const results = getFilteredCompletions({ meta: GROUP_EXPRESSION_COMPLETION_META }); + const metaPrefixes = new Set(results.map((r) => r.meta.split(':')[0])); + expect(metaPrefixes).toContain('expr'); + expect(metaPrefixes).toContain('accumulator'); + expect(metaPrefixes).toContain('bson'); + expect(metaPrefixes).toContain('variable'); + expect(metaPrefixes).not.toContain('query'); + expect(metaPrefixes).not.toContain('stage'); + }); + + test('EXPRESSION_COMPLETION_META returns expr + bson + variable (no accumulators)', () => { + const results = getFilteredCompletions({ meta: EXPRESSION_COMPLETION_META }); + const metaPrefixes = new Set(results.map((r) => r.meta.split(':')[0])); + expect(metaPrefixes).toContain('expr'); + expect(metaPrefixes).toContain('bson'); + expect(metaPrefixes).toContain('variable'); + expect(metaPrefixes).not.toContain('accumulator'); + }); + + test('WINDOW_COMPLETION_META returns window + accumulator + expr + bson + variable', () => { + const results = getFilteredCompletions({ meta: WINDOW_COMPLETION_META }); + const metaPrefixes = new Set(results.map((r) => r.meta.split(':')[0])); + expect(metaPrefixes).toContain('window'); + expect(metaPrefixes).toContain('accumulator'); + expect(metaPrefixes).toContain('expr'); + expect(metaPrefixes).toContain('bson'); + expect(metaPrefixes).toContain('variable'); + }); + + test('PROJECTION_COMPLETION_META looks for field:identifier (empty since runtime-injected)', () => { + const results = getFilteredCompletions({ meta: PROJECTION_COMPLETION_META }); + // field:identifier entries are injected at runtime, not statically registered + expect(results.length).toBe(0); + }); +}); diff --git a/packages/documentdb-constants/src/operatorReference.test.ts b/packages/documentdb-constants/src/operatorReference.test.ts new file mode 100644 index 000000000..0d25db771 --- /dev/null +++ b/packages/documentdb-constants/src/operatorReference.test.ts @@ -0,0 +1,164 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Dump-vs-implementation verification test. + * + * Ensures the TypeScript operator implementation always matches the + * resource dump (operator-reference-scraped.md). This test is the + * enforcing contract between "what does DocumentDB support?" (the dump) + * and "what does our code provide?" (the implementation). + * + * See §2.3.3 of docs/plan/03-documentdb-constants.md for design rationale. + */ + +import * as fs from 'fs'; +import * as path from 'path'; +import { getAllCompletions } from './index'; +import { parseOperatorReference } from './parseOperatorReference'; + +const dumpPath = path.join(__dirname, '..', 'resources', 'operator-reference-scraped.md'); +const dumpContent = fs.readFileSync(dumpPath, 'utf-8'); +const parsed = parseOperatorReference(dumpContent); +const referenceOperators = parsed.operators; +const notListedOperators = parsed.notListed; +const implementedOperators = getAllCompletions(); + +/** + * Category-to-meta mapping. Maps dump category names to the meta tags + * used in the implementation. Some dump categories map to the same meta + * tag (e.g., both accumulator categories map to 'accumulator'). + */ +const CATEGORY_TO_META: Record = { + 'Comparison Query Operators': 'query:comparison', + 'Logical Query Operators': 'query:logical', + 'Element Query Operators': 'query:element', + 'Evaluation Query Operators': 'query:evaluation', + 'Geospatial Operators': 'query:geospatial', + 'Array Query Operators': 'query:array', + 'Bitwise Query Operators': 'query:bitwise', + 'Projection Operators': 'query:projection', + 'Miscellaneous Query Operators': 'query:misc', + 'Field Update Operators': 'update:field', + 'Array Update Operators': 'update:array', + 'Bitwise Update Operators': 'update:bitwise', + 'Arithmetic Expression Operators': 'expr:arith', + 'Array Expression Operators': 'expr:array', + 'Bitwise Operators': 'expr:bitwise', + 'Boolean Expression Operators': 'expr:bool', + 'Comparison Expression Operators': 'expr:comparison', + 'Data Size Operators': 'expr:datasize', + 'Date Expression Operators': 'expr:date', + 'Literal Expression Operator': 'expr:literal', + 'Miscellaneous Operators': 'expr:misc', + 'Object Expression Operators': 'expr:object', + 'Set Expression Operators': 'expr:set', + 'String Expression Operators': 'expr:string', + 'Timestamp Expression Operators': 'expr:timestamp', + 'Trigonometry Expression Operators': 'expr:trig', + 'Type Expression Operators': 'expr:type', + 'Accumulators ($group, $bucket, $bucketAuto, $setWindowFields)': 'accumulator', + 'Accumulators (in Other Stages)': 'accumulator', + 'Variable Expression Operators': 'expr:variable', + 'Window Operators': 'window', + 'Conditional Expression Operators': 'expr:conditional', + 'Aggregation Pipeline Stages': 'stage', + 'Variables in Aggregation Expressions': 'variable', +}; + +describe('operator reference verification', () => { + test('dump file exists and is parseable', () => { + expect(dumpContent.length).toBeGreaterThan(1000); + expect(referenceOperators.length).toBeGreaterThan(250); + }); + + test('every listed operator in the dump has an implementation entry', () => { + const implementedValues = new Set(implementedOperators.map((op) => op.value)); + const missing: string[] = []; + + for (const ref of referenceOperators) { + // Some operators appear in multiple dump categories (e.g., $objectToArray + // in both "Array Expression" and "Object Expression"). The implementation + // only needs one entry per (value, meta) pair — check by value. + if (!implementedValues.has(ref.operator)) { + missing.push(`${ref.operator} (${ref.category})`); + } + } + + expect(missing).toEqual([]); + }); + + test('no extra operators in implementation beyond the dump (excluding BSON/variables)', () => { + // Build a set of all operator values from the dump + const dumpValues = new Set(referenceOperators.map((r) => r.operator)); + + // Filter implementation entries: exclude BSON constructors and system variables + // (these are hand-authored, not from the compatibility page dump) + const extras = implementedOperators.filter( + (op) => !op.meta.startsWith('bson') && !op.meta.startsWith('variable') && !dumpValues.has(op.value), + ); + + expect(extras.map((e) => `${e.value} (${e.meta})`)).toEqual([]); + }); + + test('descriptions match the dump (detect drift)', () => { + const mismatches: string[] = []; + + for (const ref of referenceOperators) { + if (!ref.description) { + continue; // some operators have empty descriptions (missing upstream docs) + } + + // Find implementation entry matching this operator + category's meta + const expectedMeta = CATEGORY_TO_META[ref.category]; + if (!expectedMeta) { + continue; // unknown category + } + + const impl = implementedOperators.find((op) => op.value === ref.operator && op.meta === expectedMeta); + + if (impl && impl.description !== ref.description) { + mismatches.push( + `${ref.operator} (${ref.category}): expected "${ref.description}", got "${impl.description}"`, + ); + } + } + + expect(mismatches).toEqual([]); + }); + + test('not-listed operators are NOT in the implementation', () => { + const implementedValues = new Set(implementedOperators.map((op) => op.value)); + const leaked: string[] = []; + + for (const nl of notListedOperators) { + // Check the exact meta category from the dump + const expectedMeta = CATEGORY_TO_META[nl.category]; + if (!expectedMeta) { + continue; + } + + const found = implementedOperators.find((op) => op.value === nl.operator && op.meta === expectedMeta); + + if (found) { + leaked.push(`${nl.operator} (${nl.category}) — ${nl.reason}`); + } + } + + expect(leaked).toEqual([]); + }); + + test('all dump categories have a known meta mapping', () => { + const categories = new Set(referenceOperators.map((r) => r.category)); + const unmapped = [...categories].filter((c) => !CATEGORY_TO_META[c]); + expect(unmapped).toEqual([]); + }); + + test('reference parser found the expected number of not-listed operators', () => { + // The plan lists 16 not-listed operators (§2.1) + expect(notListedOperators.length).toBeGreaterThanOrEqual(14); + expect(notListedOperators.length).toBeLessThanOrEqual(20); + }); +}); diff --git a/packages/documentdb-constants/src/parseOperatorReference.test.ts b/packages/documentdb-constants/src/parseOperatorReference.test.ts new file mode 100644 index 000000000..4ebf5138a --- /dev/null +++ b/packages/documentdb-constants/src/parseOperatorReference.test.ts @@ -0,0 +1,156 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Unit tests for the parseOperatorReference helper. + */ + +import { parseOperatorReference } from './parseOperatorReference'; + +describe('parseOperatorReference', () => { + test('parses a minimal dump with one category and one operator', () => { + const content = `# DocumentDB Operator Reference + +## Summary + +| Category | Listed | Total | +| --- | --- | --- | +| Test Category | 1 | 1 | + +## Test Category + +### $testOp + +- **Description:** A test operator +- **Doc Link:** https://example.com/test + +## Not Listed + +- **$excluded** (Test Category) — Not supported +`; + const result = parseOperatorReference(content); + expect(result.operators).toHaveLength(1); + expect(result.operators[0]).toEqual({ + operator: '$testOp', + category: 'Test Category', + description: 'A test operator', + docLink: 'https://example.com/test', + }); + expect(result.notListed).toHaveLength(1); + expect(result.notListed[0]).toEqual({ + operator: '$excluded', + category: 'Test Category', + reason: 'Not supported', + }); + }); + + test('handles operators with empty description and doc link', () => { + const content = `## Variables + +### $$NOW + +### $$ROOT +`; + const result = parseOperatorReference(content); + expect(result.operators).toHaveLength(2); + expect(result.operators[0]).toEqual({ + operator: '$$NOW', + category: 'Variables', + description: '', + docLink: '', + }); + expect(result.operators[1]).toEqual({ + operator: '$$ROOT', + category: 'Variables', + description: '', + docLink: '', + }); + }); + + test('handles operators with syntax blocks (ignores syntax)', () => { + const content = `## Comparison Query Operators + +### $eq + +- **Description:** Matches values equal to a specified value +- **Syntax:** + +\`\`\`javascript +{ field: { $eq: value } } +\`\`\` + +- **Doc Link:** https://example.com/$eq + +### $gt + +- **Description:** Matches values greater than a specified value +- **Doc Link:** https://example.com/$gt +`; + const result = parseOperatorReference(content); + expect(result.operators).toHaveLength(2); + expect(result.operators[0].operator).toBe('$eq'); + expect(result.operators[0].description).toBe('Matches values equal to a specified value'); + expect(result.operators[1].operator).toBe('$gt'); + }); + + test('skips operators in the Summary section', () => { + const content = `## Summary + +| Category | Listed | Total | +| --- | --- | --- | +| Test | 2 | 3 | + +## Test Category + +### $realOp + +- **Description:** I am real +`; + const result = parseOperatorReference(content); + expect(result.operators).toHaveLength(1); + expect(result.operators[0].operator).toBe('$realOp'); + }); + + test('multiple not-listed entries are parsed correctly', () => { + const content = `## Not Listed + +Operators below are not in scope. + +- **$where** (Evaluation Query) — Deprecated in Mongo version 8.0 +- **$meta** (Projection) — Not in scope +- **$accumulator** (Custom Aggregation) — Deprecated in Mongo version 8.0 +`; + const result = parseOperatorReference(content); + expect(result.notListed).toHaveLength(3); + expect(result.notListed[0].operator).toBe('$where'); + expect(result.notListed[0].reason).toBe('Deprecated in Mongo version 8.0'); + expect(result.notListed[1].operator).toBe('$meta'); + expect(result.notListed[2].operator).toBe('$accumulator'); + }); + + test('handles multiple categories', () => { + const content = `## Cat A + +### $a1 + +- **Description:** Operator a1 + +### $a2 + +- **Description:** Operator a2 + +## Cat B + +### $b1 + +- **Description:** Operator b1 +`; + const result = parseOperatorReference(content); + expect(result.operators).toHaveLength(3); + expect(result.operators[0].category).toBe('Cat A'); + expect(result.operators[1].category).toBe('Cat A'); + expect(result.operators[2].category).toBe('Cat B'); + }); +}); diff --git a/packages/documentdb-constants/src/parseOperatorReference.ts b/packages/documentdb-constants/src/parseOperatorReference.ts new file mode 100644 index 000000000..42c08ba33 --- /dev/null +++ b/packages/documentdb-constants/src/parseOperatorReference.ts @@ -0,0 +1,159 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Parses the operator-reference-scraped.md dump file into structured data + * for use in the operatorReference verification test. + * + * The dump format uses structured headings: + * ## Category Name — category section + * ### $operatorName — operator heading + * - **Description:** text — operator description + * - **Doc Link:** url — documentation URL + * + * ## Not Listed — excluded operators section + * - **$operator** (Category) — Reason + */ + +/** + * Represents a single operator entry parsed from the reference dump. + */ +export interface ReferenceOperator { + /** Operator name, e.g. "$eq", "$$NOW" */ + readonly operator: string; + /** Category from the dump, e.g. "Comparison Query Operators" */ + readonly category: string; + /** Description from the dump (may be empty) */ + readonly description: string; + /** Documentation URL from the dump (may be empty) */ + readonly docLink: string; +} + +/** + * Represents an operator excluded from the package scope. + */ +export interface NotListedOperator { + /** Operator name, e.g. "$where", "$meta" */ + readonly operator: string; + /** Category from the dump */ + readonly category: string; + /** Reason for exclusion */ + readonly reason: string; +} + +/** + * Complete parsed result from the reference dump. + */ +export interface ParsedReference { + /** All listed (in-scope) operators */ + readonly operators: readonly ReferenceOperator[]; + /** All not-listed (excluded) operators */ + readonly notListed: readonly NotListedOperator[]; +} + +/** + * Parses the operator-reference-scraped.md content into structured data. + * + * @param content - the full Markdown content of the dump file + * @returns parsed reference data + */ +export function parseOperatorReference(content: string): ParsedReference { + const lines = content.split('\n'); + const operators: ReferenceOperator[] = []; + const notListed: NotListedOperator[] = []; + + let currentCategory = ''; + let inNotListed = false; + let inSummary = false; + + // Temp state for building current operator + let currentOperator = ''; + let currentDescription = ''; + let currentDocLink = ''; + + function flushOperator(): void { + if (currentOperator && currentCategory && !inNotListed && !inSummary) { + operators.push({ + operator: currentOperator, + category: currentCategory, + description: currentDescription, + docLink: currentDocLink, + }); + } + currentOperator = ''; + currentDescription = ''; + currentDocLink = ''; + } + + for (const line of lines) { + const trimmed = line.trim(); + + // Detect ## headings (category sections) + const h2Match = trimmed.match(/^## (.+)$/); + if (h2Match) { + flushOperator(); + const heading = h2Match[1].trim(); + if (heading === 'Summary') { + inSummary = true; + inNotListed = false; + currentCategory = ''; + } else if (heading === 'Not Listed') { + inNotListed = true; + inSummary = false; + currentCategory = ''; + } else { + currentCategory = heading; + inNotListed = false; + inSummary = false; + } + continue; + } + + // Skip summary section + if (inSummary) { + continue; + } + + // Parse "Not Listed" entries: - **$operator** (Category) — Reason + if (inNotListed) { + const notListedMatch = trimmed.match(/^- \*\*(.+?)\*\* \((.+?)\) — (.+)$/); + if (notListedMatch) { + notListed.push({ + operator: notListedMatch[1], + category: notListedMatch[2], + reason: notListedMatch[3], + }); + } + continue; + } + + // Detect ### headings (operator entries) + const h3Match = trimmed.match(/^### (.+)$/); + if (h3Match) { + flushOperator(); + currentOperator = h3Match[1].trim(); + continue; + } + + // Parse description: - **Description:** text + const descMatch = trimmed.match(/^- \*\*Description:\*\* (.+)$/); + if (descMatch && currentOperator) { + currentDescription = descMatch[1].trim(); + continue; + } + + // Parse doc link: - **Doc Link:** url + const linkMatch = trimmed.match(/^- \*\*Doc Link:\*\* (.+)$/); + if (linkMatch && currentOperator) { + currentDocLink = linkMatch[1].trim(); + continue; + } + } + + // Flush last operator + flushOperator(); + + return { operators, notListed }; +} diff --git a/packages/documentdb-constants/src/structuralInvariants.test.ts b/packages/documentdb-constants/src/structuralInvariants.test.ts new file mode 100644 index 000000000..953fc7831 --- /dev/null +++ b/packages/documentdb-constants/src/structuralInvariants.test.ts @@ -0,0 +1,242 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Structural invariant tests for all operator entries. + * + * Validates that every entry in getAllCompletions() has the correct shape, + * consistent meta tags, and reasonable values. + */ + +import { ALL_META_TAGS, getAllCompletions, type OperatorEntry } from './index'; + +const allOperators = getAllCompletions(); + +describe('structural invariants', () => { + test('total operator count is in the expected range', () => { + // 308 total (298 from dump + 10 BSON constructors) + expect(allOperators.length).toBeGreaterThanOrEqual(290); + expect(allOperators.length).toBeLessThanOrEqual(320); + }); + + test('every entry has required fields', () => { + const invalid: string[] = []; + for (const op of allOperators) { + if (!op.value) { + invalid.push('entry missing value'); + } + if (!op.meta) { + invalid.push(`${op.value} missing meta`); + } + if (!op.description) { + invalid.push(`${op.value} missing description`); + } + } + expect(invalid).toEqual([]); + }); + + test('operator values start with $ or $$ (except BSON constructors)', () => { + const invalid: string[] = []; + for (const op of allOperators) { + if (op.meta === 'bson') { + // BSON constructors: ObjectId, ISODate, etc. — no $ prefix + expect(op.value).toMatch(/^[A-Z]/); + } else if (op.meta === 'variable') { + // System variables start with $$ + if (!op.value.startsWith('$$')) { + invalid.push(`${op.value} (variable) should start with $$`); + } + } else { + // All other operators start with $ + if (!op.value.startsWith('$')) { + invalid.push(`${op.value} (${op.meta}) should start with $`); + } + } + } + expect(invalid).toEqual([]); + }); + + test('every entry has a valid meta tag', () => { + const validMetas = new Set(ALL_META_TAGS); + const invalid: string[] = []; + for (const op of allOperators) { + if (!validMetas.has(op.meta)) { + invalid.push(`${op.value} has unknown meta: ${op.meta}`); + } + } + expect(invalid).toEqual([]); + }); + + test('descriptions are non-empty strings', () => { + const empty: string[] = []; + for (const op of allOperators) { + if (typeof op.description !== 'string' || op.description.trim().length === 0) { + empty.push(`${op.value} (${op.meta}) has empty description`); + } + } + expect(empty).toEqual([]); + }); + + test('snippets are strings when present', () => { + const invalid: string[] = []; + for (const op of allOperators) { + if (op.snippet !== undefined && typeof op.snippet !== 'string') { + invalid.push(`${op.value} (${op.meta}) has non-string snippet`); + } + } + expect(invalid).toEqual([]); + }); + + test('links are valid URLs when present', () => { + const invalid: string[] = []; + for (const op of allOperators) { + if (op.link !== undefined) { + if (typeof op.link !== 'string' || !op.link.startsWith('https://')) { + invalid.push(`${op.value} (${op.meta}) has invalid link: ${op.link}`); + } + } + } + expect(invalid).toEqual([]); + }); + + test('applicableBsonTypes is a string array when present', () => { + const invalid: string[] = []; + for (const op of allOperators) { + if (op.applicableBsonTypes !== undefined) { + if (!Array.isArray(op.applicableBsonTypes)) { + invalid.push(`${op.value} (${op.meta}) applicableBsonTypes is not an array`); + } else { + for (const t of op.applicableBsonTypes) { + if (typeof t !== 'string' || t.trim().length === 0) { + invalid.push(`${op.value} (${op.meta}) has empty BSON type`); + } + } + } + } + } + expect(invalid).toEqual([]); + }); + + test('no duplicate (value, meta) pairs', () => { + const seen = new Set(); + const duplicates: string[] = []; + for (const op of allOperators) { + const key = `${op.value}|${op.meta}`; + if (seen.has(key)) { + duplicates.push(key); + } + seen.add(key); + } + expect(duplicates).toEqual([]); + }); + + test('BSON constructors have expected entries', () => { + const bsonOps = allOperators.filter((op) => op.meta === 'bson'); + const bsonValues = bsonOps.map((op) => op.value).sort(); + expect(bsonValues).toEqual( + expect.arrayContaining([ + 'BinData', + 'ISODate', + 'MaxKey', + 'MinKey', + 'NumberDecimal', + 'NumberInt', + 'NumberLong', + 'ObjectId', + 'Timestamp', + 'UUID', + ]), + ); + }); + + test('system variables have expected entries', () => { + const varOps = allOperators.filter((op) => op.meta === 'variable'); + const varValues = varOps.map((op) => op.value).sort(); + expect(varValues).toEqual( + expect.arrayContaining(['$$CURRENT', '$$DESCEND', '$$KEEP', '$$NOW', '$$PRUNE', '$$REMOVE', '$$ROOT']), + ); + }); + + test('key operators are present', () => { + const values = new Set(allOperators.map((op) => op.value)); + + // Query operators + expect(values.has('$eq')).toBe(true); + expect(values.has('$gt')).toBe(true); + expect(values.has('$and')).toBe(true); + expect(values.has('$regex')).toBe(true); + expect(values.has('$exists')).toBe(true); + + // Stages + expect(values.has('$match')).toBe(true); + expect(values.has('$group')).toBe(true); + expect(values.has('$lookup')).toBe(true); + expect(values.has('$project')).toBe(true); + expect(values.has('$sort')).toBe(true); + + // Update operators + expect(values.has('$set')).toBe(true); + expect(values.has('$unset')).toBe(true); + expect(values.has('$inc')).toBe(true); + + // Accumulators + expect(values.has('$sum')).toBe(true); + expect(values.has('$avg')).toBe(true); + + // Expressions + expect(values.has('$add')).toBe(true); + expect(values.has('$concat')).toBe(true); + expect(values.has('$cond')).toBe(true); + }); + + test('excluded operators are NOT present with unsupported meta tags', () => { + // These should not be present (deprecated or not supported) + const opsByValueMeta = new Map(); + for (const op of allOperators) { + opsByValueMeta.set(`${op.value}|${op.meta}`, op); + } + + // $where is deprecated and should not be present as evaluation query + expect(opsByValueMeta.has('$where|query:evaluation')).toBe(false); + }); +}); + +describe('meta tag coverage', () => { + test('every meta tag in ALL_META_TAGS has at least one operator (except parent-only and runtime tags)', () => { + const metasWithOps = new Set(allOperators.map((op) => op.meta)); + // Parent-only tags: operators use subcategories (query:comparison, update:field), + // not the bare 'query' or 'update' tags. 'field:identifier' is runtime-injected. + const parentOnlyTags = new Set(['query', 'update', 'field:identifier']); + const missing: string[] = []; + for (const tag of ALL_META_TAGS) { + if (parentOnlyTags.has(tag)) { + continue; + } + if (!metasWithOps.has(tag)) { + missing.push(tag); + } + } + expect(missing).toEqual([]); + }); + + test('top-level meta categories have expected operator counts', () => { + const countByPrefix: Record = {}; + for (const op of allOperators) { + const prefix = op.meta.includes(':') ? op.meta.split(':')[0] : op.meta; + countByPrefix[prefix] = (countByPrefix[prefix] || 0) + 1; + } + + expect(countByPrefix['query']).toBe(43); + expect(countByPrefix['update']).toBe(22); + expect(countByPrefix['stage']).toBe(35); + expect(countByPrefix['accumulator']).toBe(21); + expect(countByPrefix['window']).toBe(27); + expect(countByPrefix['bson']).toBe(10); + expect(countByPrefix['variable']).toBe(7); + // Expression operators: ~143-144 + expect(countByPrefix['expr']).toBeGreaterThanOrEqual(140); + expect(countByPrefix['expr']).toBeLessThanOrEqual(150); + }); +}); From cec372e72113866a2aa423a88cbffa5971747ca9 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Fri, 20 Feb 2026 14:48:23 +0000 Subject: [PATCH 033/128] Update documentation links for various operators in DocumentDB constants - Replaced dynamic documentation links with direct URLs for operators in accumulators, expression operators, query operators, update operators, window operators, and stages. - Updated metadata references in docLinks to reflect accurate categories for boolean and comparison expressions. - Enhanced test coverage for operator reference verification, ensuring merged dump and overrides are consistent with implementation. - Removed unused getDocLink imports from system variables. --- .../resources/operator-reference-scraped.md | 54 ++++- .../scripts/generate-from-reference.ts | 57 ++++- .../scripts/scrape-operator-docs.ts | 219 ++++++++++++++---- .../documentdb-constants/src/accumulators.ts | 6 +- packages/documentdb-constants/src/docLinks.ts | 4 +- .../src/expressionOperators.ts | 62 ++--- .../src/operatorReference.test.ts | 199 +++++++++++++++- .../src/queryOperators.ts | 6 +- packages/documentdb-constants/src/stages.ts | 12 +- .../src/systemVariables.ts | 8 - .../src/updateOperators.ts | 15 +- .../src/windowOperators.ts | 32 +-- 12 files changed, 517 insertions(+), 157 deletions(-) diff --git a/packages/documentdb-constants/resources/operator-reference-scraped.md b/packages/documentdb-constants/resources/operator-reference-scraped.md index 378839198..b87918205 100644 --- a/packages/documentdb-constants/resources/operator-reference-scraped.md +++ b/packages/documentdb-constants/resources/operator-reference-scraped.md @@ -1,7 +1,7 @@ # DocumentDB Operator Reference - + ## Summary @@ -704,6 +704,7 @@ db.collection.updateOne( ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$ +- **Scraper Comment:** Doc page not found in expected directory 'projection/'. Using verified URL from 'array-update/' instead. ### $elemMatch @@ -715,6 +716,7 @@ db.collection.find({ : { $elemMatch: { , , ... } } }) ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-query/$elemmatch +- **Scraper Comment:** Doc page not found in expected directory 'projection/'. Using verified URL from 'array-query/' instead. ### $slice @@ -728,6 +730,7 @@ db.collection.find({ : { $elemMatch: { , , ... } } }) ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$slice +- **Scraper Comment:** Doc page not found in expected directory 'projection/'. Using verified URL from 'array-expression/' instead. ## Miscellaneous Query Operators @@ -817,6 +820,7 @@ $min: ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$min +- **Scraper Comment:** Doc page not found in expected directory 'field-update/'. Using verified URL from 'accumulators/' instead. ### $max @@ -828,6 +832,7 @@ $max: ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$max +- **Scraper Comment:** Doc page not found in expected directory 'field-update/'. Using verified URL from 'accumulators/' instead. ### $mul @@ -877,6 +882,7 @@ $max: ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$set +- **Scraper Comment:** Doc page not found in expected directory 'field-update/'. Using verified URL from 'aggregation/' instead. ### $setOnInsert @@ -907,6 +913,7 @@ $max: ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$unset +- **Scraper Comment:** Doc page not found in expected directory 'field-update/'. Using verified URL from 'aggregation/' instead. ## Array Update Operators @@ -1034,6 +1041,7 @@ db.collection.update({ ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$slice +- **Scraper Comment:** Doc page not found in expected directory 'array-update/'. Using verified URL from 'array-expression/' instead. ### $sort @@ -1050,6 +1058,7 @@ db.collection.update({ ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$sort +- **Scraper Comment:** Doc page not found in expected directory 'array-update/'. Using verified URL from 'aggregation/' instead. ## Bitwise Update Operators @@ -1201,6 +1210,7 @@ db.collection.update({ ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/evaluation-query/$mod +- **Scraper Comment:** Doc page not found in expected directory 'arithmetic-expression/'. Using verified URL from 'evaluation-query/' instead. ### $multiply @@ -1356,6 +1366,7 @@ db.collection.update({ ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$firstn +- **Scraper Comment:** Doc page not found in expected directory 'array-expression/'. Using verified URL from 'accumulators/' instead. ### $in @@ -1371,6 +1382,7 @@ db.collection.update({ ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$in +- **Scraper Comment:** Doc page not found in expected directory 'array-expression/'. Using verified URL from 'comparison-query/' instead. ### $indexOfArray @@ -1418,6 +1430,7 @@ db.collection.update({ ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$lastn +- **Scraper Comment:** Doc page not found in expected directory 'array-expression/'. Using verified URL from 'accumulators/' instead. ### $map @@ -1449,6 +1462,7 @@ $maxN: { ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$maxn +- **Scraper Comment:** Doc page not found in expected directory 'array-expression/'. Using verified URL from 'accumulators/' instead. ### $minN @@ -1463,6 +1477,7 @@ $minN: { ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$minn +- **Scraper Comment:** Doc page not found in expected directory 'array-expression/'. Using verified URL from 'accumulators/' instead. ### $objectToArray @@ -1517,6 +1532,7 @@ db.collection.find({ : { $size: } }) ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-query/$size +- **Scraper Comment:** Doc page not found in expected directory 'array-expression/'. Using verified URL from 'array-query/' instead. ### $slice @@ -1638,6 +1654,7 @@ db.collection.find({ : { $size: } }) ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/logical-query/$and +- **Scraper Comment:** Doc page not found in expected directory 'boolean-expression/'. Using verified URL from 'logical-query/' instead. ### $not @@ -1655,6 +1672,7 @@ db.collection.find({ : { $size: } }) ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/logical-query/$not +- **Scraper Comment:** Doc page not found in expected directory 'boolean-expression/'. Using verified URL from 'logical-query/' instead. ### $or @@ -1674,6 +1692,7 @@ db.collection.find({ : { $size: } }) ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/logical-query/$or +- **Scraper Comment:** Doc page not found in expected directory 'boolean-expression/'. Using verified URL from 'logical-query/' instead. ## Comparison Expression Operators @@ -1689,6 +1708,7 @@ db.collection.find({ : { $size: } }) ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$cmp +- **Scraper Comment:** Doc page not found in expected directory 'comparison-expression/'. Using verified URL from 'comparison-query/' instead. ### $eq @@ -1704,6 +1724,7 @@ db.collection.find({ : { $size: } }) ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$eq +- **Scraper Comment:** Doc page not found in expected directory 'comparison-expression/'. Using verified URL from 'comparison-query/' instead. ### $gt @@ -1719,6 +1740,7 @@ db.collection.find({ : { $size: } }) ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$gt +- **Scraper Comment:** Doc page not found in expected directory 'comparison-expression/'. Using verified URL from 'comparison-query/' instead. ### $gte @@ -1734,6 +1756,7 @@ db.collection.find({ : { $size: } }) ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$gte +- **Scraper Comment:** Doc page not found in expected directory 'comparison-expression/'. Using verified URL from 'comparison-query/' instead. ### $lt @@ -1749,6 +1772,7 @@ db.collection.find({ : { $size: } }) ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$lt +- **Scraper Comment:** Doc page not found in expected directory 'comparison-expression/'. Using verified URL from 'comparison-query/' instead. ### $lte @@ -1764,6 +1788,7 @@ db.collection.find({ : { $size: } }) ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$lte +- **Scraper Comment:** Doc page not found in expected directory 'comparison-expression/'. Using verified URL from 'comparison-query/' instead. ### $ne @@ -1779,6 +1804,7 @@ db.collection.find({ : { $size: } }) ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$ne +- **Scraper Comment:** Doc page not found in expected directory 'comparison-expression/'. Using verified URL from 'comparison-query/' instead. ## Data Size Operators @@ -2107,6 +2133,7 @@ $dateTrunc: { ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/type-expression/$todate +- **Scraper Comment:** Doc page not found in expected directory 'date-expression/'. Using verified URL from 'aggregation/type-expression/' instead. ### $week @@ -2180,6 +2207,7 @@ $dateTrunc: { ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/miscellaneous-query/$rand +- **Scraper Comment:** Doc page not found in expected directory 'miscellaneous/'. Using verified URL from 'miscellaneous-query/' instead. ### $sampleRate @@ -2356,6 +2384,7 @@ $dateTrunc: { ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$datefromstring +- **Scraper Comment:** Doc page not found in expected directory 'string-expression/'. Using verified URL from 'date-expression/' instead. ### $dateToString @@ -2374,6 +2403,7 @@ $dateTrunc: { ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$datetostring +- **Scraper Comment:** Doc page not found in expected directory 'string-expression/'. Using verified URL from 'date-expression/' instead. ### $indexOfBytes @@ -2421,6 +2451,7 @@ $dateTrunc: { ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/type-expression/$tostring +- **Scraper Comment:** Doc page not found in expected directory 'string-expression/'. Using verified URL from 'aggregation/type-expression/' instead. ### $trim @@ -2636,6 +2667,7 @@ $dateTrunc: { ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/element-query/$type +- **Scraper Comment:** Doc page not found in expected directory 'aggregation/type-expression/'. Using verified URL from 'element-query/' instead. ## Accumulators ($group, $bucket, $bucketAuto, $setWindowFields) @@ -2651,6 +2683,7 @@ $dateTrunc: { ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$addtoset +- **Scraper Comment:** Doc page not found in expected directory 'accumulators/'. Using verified URL from 'array-update/' instead. ### $avg @@ -2837,6 +2870,7 @@ $maxN: { ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/object-expression/$mergeobjects +- **Scraper Comment:** Doc page not found in expected directory 'accumulators/'. Using verified URL from 'object-expression/' instead. ### $min @@ -2882,6 +2916,7 @@ db.collection.update({ ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$push +- **Scraper Comment:** Doc page not found in expected directory 'accumulators/'. Using verified URL from 'array-update/' instead. ### $stdDevPop @@ -3139,6 +3174,7 @@ $percentile: { ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$sum +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. ### $push @@ -3158,6 +3194,7 @@ db.collection.update({ ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$push +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'array-update/' instead. ### $addToSet @@ -3171,6 +3208,7 @@ db.collection.update({ ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$addtoset +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'array-update/' instead. ### $count @@ -3184,6 +3222,7 @@ db.collection.update({ ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$count +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. ### $max @@ -3195,6 +3234,7 @@ $max: ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$max +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. ### $min @@ -3206,6 +3246,7 @@ $min: ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$min +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. ### $avg @@ -3217,6 +3258,7 @@ $avg: ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$avg +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. ### $stdDevPop @@ -3232,6 +3274,7 @@ $avg: ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$stddevpop +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. ### $bottom @@ -3250,6 +3293,7 @@ $avg: ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$bottom +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. ### $bottomN @@ -3269,6 +3313,7 @@ $avg: ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$bottomn +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. ### $covariancePop @@ -3368,6 +3413,7 @@ $avg: ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$first +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. ### $integral @@ -3397,6 +3443,7 @@ $avg: ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$last +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. ### $linearFill @@ -3445,6 +3492,7 @@ $minN: { ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$minn +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. ### $rank @@ -3500,6 +3548,7 @@ $minN: { ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$stddevsamp +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. ### $top @@ -3518,6 +3567,7 @@ $minN: { ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$top +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. ### $topN @@ -3537,6 +3587,7 @@ $minN: { ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$topn +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. ## Conditional Expression Operators @@ -3681,6 +3732,7 @@ $minN: { ``` - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$count +- **Scraper Comment:** Doc page not found in expected directory 'aggregation/'. Using verified URL from 'accumulators/' instead. ### $densify diff --git a/packages/documentdb-constants/scripts/generate-from-reference.ts b/packages/documentdb-constants/scripts/generate-from-reference.ts index 244561003..77abe29d0 100644 --- a/packages/documentdb-constants/scripts/generate-from-reference.ts +++ b/packages/documentdb-constants/scripts/generate-from-reference.ts @@ -26,6 +26,8 @@ import * as fs from 'fs'; import * as path from 'path'; +import { getDocLink } from '../src/docLinks'; +import * as MetaTags from '../src/metaTags'; // --------------------------------------------------------------------------- // Types @@ -90,6 +92,17 @@ const CATEGORY_TO_META: Record = { 'Variables in Aggregation Expressions': 'META_VARIABLE', }; +/** + * Maps META constant names (like 'META_EXPR_STRING') to their string values + * (like 'expr:string') so we can call getDocLink() at generation time to + * compare the computed URL against the dump's verified URL. + */ +const META_CONST_TO_VALUE: Record = Object.fromEntries( + Object.entries(MetaTags) + .filter(([, v]) => typeof v === 'string') + .map(([k, v]) => [k, v as string]), +); + // Category → output file mapping const CATEGORY_TO_FILE: Record = { 'Comparison Query Operators': 'queryOperators', @@ -833,18 +846,25 @@ function generateFileContent(specs: FileSpec[]): string { const metaImportsList = [...allMetaImports].sort().join(',\n '); + // Pre-generate all sections so we can detect whether getDocLink is used + const sections: string[] = []; + for (const spec of specs) { + sections.push(generateSection(spec)); + } + const sectionsStr = sections.join('\n'); + + // Only import getDocLink if at least one operator uses it in this file + const needsDocLink = sectionsStr.includes('getDocLink('); + const docLinkImport = needsDocLink ? `\nimport { getDocLink } from './docLinks';` : ''; + let content = `${copyright} import { type OperatorEntry } from './types'; -import { ${metaImportsList} } from './metaTags'; -import { getDocLink } from './docLinks'; +import { ${metaImportsList} } from './metaTags';${docLinkImport} import { registerOperators } from './getFilteredCompletions'; `; - for (const spec of specs) { - content += generateSection(spec); - content += '\n'; - } + content += sectionsStr; // Registration call const allVarNames = specs.map((s) => `...${s.variableName}`).join(',\n '); @@ -863,10 +883,31 @@ function generateSection(spec: FileSpec): string { section += `const ${spec.variableName}: readonly OperatorEntry[] = [\n`; + // Resolve the meta tag's string value for runtime getDocLink comparison + const metaStringValue = META_CONST_TO_VALUE[spec.metaImport] || ''; + for (const op of spec.operators) { const snippet = op.snippetOverride || generateSnippet(op, spec.metaImport); const bsonTypes = getApplicableBsonTypes(op, spec.metaImport); + // Determine the correct link emission strategy: + // - If dump has a URL that matches what getDocLink() would produce → use getDocLink() (compact) + // - If dump has a URL that differs from getDocLink() → emit hardcoded string + // - If dump has no URL → omit the link property + const computedLink = getDocLink(op.value, metaStringValue); + const dumpLink = op.docLink || ''; + let linkLine: string; + if (!dumpLink) { + // No documentation page exists — omit the link + linkLine = ''; + } else if (dumpLink === computedLink) { + // The computed URL matches — use the compact getDocLink() call + linkLine = ` link: getDocLink('${escapeString(op.value)}', ${spec.metaImport}),\n`; + } else { + // The dump has a verified URL that differs from getDocLink() — emit hardcoded + linkLine = ` link: '${escapeString(dumpLink)}',\n`; + } + section += ` {\n`; section += ` value: '${escapeString(op.value)}',\n`; section += ` meta: ${spec.metaImport},\n`; @@ -874,7 +915,9 @@ function generateSection(spec: FileSpec): string { if (snippet) { section += ` snippet: '${escapeString(snippet)}',\n`; } - section += ` link: getDocLink('${escapeString(op.value)}', ${spec.metaImport}),\n`; + if (linkLine) { + section += linkLine; + } if (bsonTypes) { section += ` applicableBsonTypes: [${bsonTypes.map((t) => `'${t}'`).join(', ')}],\n`; } diff --git a/packages/documentdb-constants/scripts/scrape-operator-docs.ts b/packages/documentdb-constants/scripts/scrape-operator-docs.ts index 8f9a35d11..4fab8cf2b 100644 --- a/packages/documentdb-constants/scripts/scrape-operator-docs.ts +++ b/packages/documentdb-constants/scripts/scrape-operator-docs.ts @@ -38,8 +38,15 @@ interface OperatorInfo { description?: string; /** Syntax snippet from the per-operator doc page */ syntax?: string; - /** Documentation URL */ + /** Documentation URL (derived from the directory where the .md file was found) */ docLink?: string; + /** + * Human-readable note added when the scraper resolves a doc page from a + * different directory than the operator's primary category, or when other + * notable resolution decisions are made. Written to the dump as + * `- **Scraper Comment:**` for traceability. + */ + scraperComment?: string; } // --------------------------------------------------------------------------- @@ -112,6 +119,12 @@ const BATCH_DELAY_MS = 200; /** Number of concurrent requests per batch */ const BATCH_SIZE = 10; +/** Maximum number of retry attempts for transient HTTP errors */ +const MAX_RETRIES = 3; + +/** Base delay for exponential backoff (ms). Doubled on each retry. */ +const BACKOFF_BASE_MS = 1000; + // --------------------------------------------------------------------------- // Utilities // --------------------------------------------------------------------------- @@ -122,17 +135,130 @@ interface FetchResult { failReason?: string; } +/** + * Returns true for HTTP status codes that are transient and worth retrying: + * - 429 Too Many Requests + * - 5xx Server errors + */ +function isRetryableStatus(status: number): boolean { + return status === 429 || status >= 500; +} + +/** + * Fetches a URL as text with exponential backoff for transient errors. + * + * Retries on 429 (rate-limited) and 5xx (server errors). Respects + * Retry-After headers when present. Non-retryable failures (e.g., 404) + * are returned immediately without retry. + */ async function fetchText(url: string): Promise { - try { - const response = await fetch(url); - if (!response.ok) { - return { content: null, failReason: `${response.status} ${response.statusText}` }; + let lastError: string | undefined; + + for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) { + try { + const response = await fetch(url); + + if (response.ok) { + return { content: await response.text() }; + } + + const reason = `${response.status} ${response.statusText}`; + + if (!isRetryableStatus(response.status)) { + // Non-retryable (e.g., 404, 403) — fail immediately + return { content: null, failReason: reason }; + } + + lastError = reason; + + // Calculate backoff: honour Retry-After header if present, + // otherwise use exponential backoff + const retryAfter = response.headers.get('Retry-After'); + let delayMs: number; + if (retryAfter) { + const seconds = Number(retryAfter); + delayMs = Number.isNaN(seconds) ? BACKOFF_BASE_MS * 2 ** attempt : seconds * 1000; + } else { + delayMs = BACKOFF_BASE_MS * 2 ** attempt; + } + + if (attempt < MAX_RETRIES) { + console.log( + `\n ⏳ ${reason} for ${url} — retrying in ${delayMs}ms (attempt ${attempt + 1}/${MAX_RETRIES})`, + ); + await sleep(delayMs); + } + } catch (error) { + const msg = error instanceof Error ? error.message : String(error); + lastError = `NetworkError: ${msg}`; + + if (attempt < MAX_RETRIES) { + const delayMs = BACKOFF_BASE_MS * 2 ** attempt; + console.log(`\n ⏳ ${lastError} — retrying in ${delayMs}ms (attempt ${attempt + 1}/${MAX_RETRIES})`); + await sleep(delayMs); + } + } + } + + return { content: null, failReason: lastError }; +} + +interface FetchJsonResult { + data: T | null; + failReason?: string; +} + +/** + * Fetches a URL as JSON with exponential backoff for transient errors. + * Same retry semantics as {@link fetchText}. + */ +async function fetchJson(url: string): Promise> { + let lastError: string | undefined; + + for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) { + try { + const response = await fetch(url); + + if (response.ok) { + return { data: (await response.json()) as T }; + } + + const reason = `${response.status} ${response.statusText}`; + + if (!isRetryableStatus(response.status)) { + return { data: null, failReason: reason }; + } + + lastError = reason; + + const retryAfter = response.headers.get('Retry-After'); + let delayMs: number; + if (retryAfter) { + const seconds = Number(retryAfter); + delayMs = Number.isNaN(seconds) ? BACKOFF_BASE_MS * 2 ** attempt : seconds * 1000; + } else { + delayMs = BACKOFF_BASE_MS * 2 ** attempt; + } + + if (attempt < MAX_RETRIES) { + console.log( + `\n ⏳ ${reason} for ${url} — retrying in ${delayMs}ms (attempt ${attempt + 1}/${MAX_RETRIES})`, + ); + await sleep(delayMs); + } + } catch (error) { + const msg = error instanceof Error ? error.message : String(error); + lastError = `NetworkError: ${msg}`; + + if (attempt < MAX_RETRIES) { + const delayMs = BACKOFF_BASE_MS * 2 ** attempt; + console.log(`\n ⏳ ${lastError} — retrying in ${delayMs}ms (attempt ${attempt + 1}/${MAX_RETRIES})`); + await sleep(delayMs); + } } - return { content: await response.text() }; - } catch (error) { - const msg = error instanceof Error ? error.message : String(error); - return { content: null, failReason: `NetworkError: ${msg}` }; } + + return { data: null, failReason: lastError }; } function sleep(ms: number): Promise { @@ -477,53 +603,43 @@ async function buildGlobalFileIndex(): Promise> { const GITHUB_API_BASE = 'https://api.github.com/repos/MicrosoftDocs/azure-databases-docs/contents/articles/documentdb/operators'; + type GithubEntry = { name: string; type: string }; const index = new Map(); - try { - const response = await fetch(GITHUB_API_BASE); - if (!response.ok) { - console.log(' ⚠ Could not fetch directory listing from GitHub API — skipping global index'); - return index; - } + const rootResult = await fetchJson(GITHUB_API_BASE); + if (!rootResult.data) { + console.log( + ` ⚠ Could not fetch directory listing from GitHub API — skipping global index (${rootResult.failReason})`, + ); + return index; + } - const items = (await response.json()) as Array<{ name: string; type: string }>; - const dirs = items.filter((d) => d.type === 'dir' && d.name !== 'includes'); + const dirs = rootResult.data.filter((d) => d.type === 'dir' && d.name !== 'includes'); - for (const dir of dirs) { - await sleep(300); // Rate limit GitHub API - try { - const dirResponse = await fetch(`${GITHUB_API_BASE}/${dir.name}`); - if (!dirResponse.ok) continue; + for (const dir of dirs) { + await sleep(300); // Rate limit GitHub API - const dirItems = (await dirResponse.json()) as Array<{ name: string; type: string }>; - const files = dirItems.filter((f) => f.name.endsWith('.md')); - const subdirs = dirItems.filter((f) => f.type === 'dir'); + const dirResult = await fetchJson(`${GITHUB_API_BASE}/${dir.name}`); + if (!dirResult.data) continue; - for (const file of files) { - index.set(file.name.toLowerCase(), dir.name); - } + const files = dirResult.data.filter((f) => f.name.endsWith('.md')); + const subdirs = dirResult.data.filter((f) => f.type === 'dir'); - // Also check subdirectories (e.g., aggregation/type-expression/) - for (const sub of subdirs) { - await sleep(300); - try { - const subResponse = await fetch(`${GITHUB_API_BASE}/${dir.name}/${sub.name}`); - if (!subResponse.ok) continue; + for (const file of files) { + index.set(file.name.toLowerCase(), dir.name); + } - const subItems = (await subResponse.json()) as Array<{ name: string; type: string }>; - for (const file of subItems.filter((f) => f.name.endsWith('.md'))) { - index.set(file.name.toLowerCase(), `${dir.name}/${sub.name}`); - } - } catch { - // Ignore subdirectory fetch failures - } - } - } catch { - // Ignore individual directory fetch failures + // Also check subdirectories (e.g., aggregation/type-expression/) + for (const sub of subdirs) { + await sleep(300); + + const subResult = await fetchJson(`${GITHUB_API_BASE}/${dir.name}/${sub.name}`); + if (!subResult.data) continue; + + for (const file of subResult.data.filter((f) => f.name.endsWith('.md'))) { + index.set(file.name.toLowerCase(), `${dir.name}/${sub.name}`); } } - } catch { - console.log(' ⚠ GitHub API request failed — skipping global index'); } return index; @@ -613,6 +729,14 @@ async function fetchOperatorDocs(operators: OperatorInfo[]): Promise { op.description = extractDescription(content); op.syntax = extractSyntax(content); op.docLink = `${DOC_LINK_BASE}/${resolvedDir}/${opNameLower}`; + + // Record a scraper comment when the doc page was found in a + // different directory than the operator's primary category + if (primaryDir && resolvedDir !== primaryDir) { + op.scraperComment = + `Doc page not found in expected directory '${primaryDir}/'. ` + + `Using verified URL from '${resolvedDir}/' instead.`; + } succeeded++; } else { failureDetails.push({ @@ -734,6 +858,9 @@ function generateDump(operators: OperatorInfo[]): string { if (op.docLink) { lines.push(`- **Doc Link:** ${op.docLink}`); } + if (op.scraperComment) { + lines.push(`- **Scraper Comment:** ${op.scraperComment}`); + } lines.push(''); } } diff --git a/packages/documentdb-constants/src/accumulators.ts b/packages/documentdb-constants/src/accumulators.ts index 57fffd843..bce98554b 100644 --- a/packages/documentdb-constants/src/accumulators.ts +++ b/packages/documentdb-constants/src/accumulators.ts @@ -27,7 +27,7 @@ const groupAccumulators: readonly OperatorEntry[] = [ description: "The addToSet operator adds elements to an array if they don't already exist, while ensuring uniqueness of elements within the set.", snippet: '{ $addToSet: "${1:\\$field}" }', - link: getDocLink('$addToSet', META_ACCUMULATOR), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$addtoset', }, { value: '$avg', @@ -114,7 +114,7 @@ const groupAccumulators: readonly OperatorEntry[] = [ meta: META_ACCUMULATOR, description: 'The $mergeObjects operator merges multiple documents into a single document', snippet: '{ $mergeObjects: "${1:\\$field}" }', - link: getDocLink('$mergeObjects', META_ACCUMULATOR), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/object-expression/$mergeobjects', }, { value: '$min', @@ -136,7 +136,7 @@ const groupAccumulators: readonly OperatorEntry[] = [ meta: META_ACCUMULATOR, description: 'The $push operator adds a specified value to an array within a document.', snippet: '{ $push: "${1:\\$field}" }', - link: getDocLink('$push', META_ACCUMULATOR), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$push', }, { value: '$stdDevPop', diff --git a/packages/documentdb-constants/src/docLinks.ts b/packages/documentdb-constants/src/docLinks.ts index 460112548..0df2ca0cb 100644 --- a/packages/documentdb-constants/src/docLinks.ts +++ b/packages/documentdb-constants/src/docLinks.ts @@ -33,8 +33,8 @@ const META_TO_DOC_DIR: Record = { accumulator: 'accumulators', 'expr:arith': 'arithmetic-expression', 'expr:array': 'array-expression', - 'expr:bool': 'boolean-expression', - 'expr:comparison': 'comparison-expression', + 'expr:bool': 'logical-query', + 'expr:comparison': 'comparison-query', 'expr:conditional': 'conditional-expression', 'expr:date': 'date-expression', 'expr:object': 'object-expression', diff --git a/packages/documentdb-constants/src/expressionOperators.ts b/packages/documentdb-constants/src/expressionOperators.ts index 6761b0786..7e705e8ae 100644 --- a/packages/documentdb-constants/src/expressionOperators.ts +++ b/packages/documentdb-constants/src/expressionOperators.ts @@ -108,7 +108,7 @@ const arithmeticExpressionOperators: readonly OperatorEntry[] = [ description: 'The $mod operator performs a modulo operation on the value of a field and selects documents with a specified result.', snippet: '{ $mod: ["${1:\\$field1}", "${2:\\$field2}"] }', - link: getDocLink('$mod', META_EXPR_ARITH), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/evaluation-query/$mod', }, { value: '$multiply', @@ -194,14 +194,14 @@ const arrayExpressionOperators: readonly OperatorEntry[] = [ description: 'The $firstN operator sorts documents on one or more fields specified by the query and returns the first N document matching the filtering criteria', snippet: '{ $firstN: { input: "${1:\\$array}", n: ${2:number} } }', - link: getDocLink('$firstN', META_EXPR_ARRAY), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$firstn', }, { value: '$in', meta: META_EXPR_ARRAY, description: 'The $in operator matches value of a field against an array of specified values', snippet: '{ $in: ["${1:\\$field}", "${2:\\$array}"] }', - link: getDocLink('$in', META_EXPR_ARRAY), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$in', }, { value: '$indexOfArray', @@ -223,7 +223,7 @@ const arrayExpressionOperators: readonly OperatorEntry[] = [ meta: META_EXPR_ARRAY, description: 'The $lastN accumulator operator returns the last N values in a group of documents.', snippet: '{ $lastN: { input: "${1:\\$array}", n: ${2:number} } }', - link: getDocLink('$lastN', META_EXPR_ARRAY), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$lastn', }, { value: '$map', @@ -237,21 +237,20 @@ const arrayExpressionOperators: readonly OperatorEntry[] = [ meta: META_EXPR_ARRAY, description: 'Retrieves the top N values based on a specified filtering criteria', snippet: '{ $maxN: { input: "${1:\\$array}", n: ${2:number} } }', - link: getDocLink('$maxN', META_EXPR_ARRAY), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$maxn', }, { value: '$minN', meta: META_EXPR_ARRAY, description: 'Retrieves the bottom N values based on a specified filtering criteria', snippet: '{ $minN: { input: "${1:\\$array}", n: ${2:number} } }', - link: getDocLink('$minN', META_EXPR_ARRAY), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$minn', }, { value: '$objectToArray', meta: META_EXPR_ARRAY, description: 'Converts an object into an array of key-value pair documents.', snippet: '{ $objectToArray: "${1:\\$object}" }', - link: getDocLink('$objectToArray', META_EXPR_ARRAY), }, { value: '$range', @@ -281,7 +280,7 @@ const arrayExpressionOperators: readonly OperatorEntry[] = [ description: 'The $size operator is used to query documents where an array field has a specified number of elements.', snippet: '{ $size: "${1:\\$array}" }', - link: getDocLink('$size', META_EXPR_ARRAY), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-query/$size', }, { value: '$slice', @@ -603,7 +602,7 @@ const dateExpressionOperators: readonly OperatorEntry[] = [ meta: META_EXPR_DATE, description: 'The $toDate operator converts supported types to a proper Date object.', snippet: '{ $toDate: "${1:\\$field}" }', - link: getDocLink('$toDate', META_EXPR_DATE), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/type-expression/$todate', }, { value: '$week', @@ -653,7 +652,7 @@ const miscellaneousOperators: readonly OperatorEntry[] = [ meta: META_EXPR_MISC, description: 'The $rand operator generates a random float value between 0 and 1.', snippet: '{ $rand: {} }', - link: getDocLink('$rand', META_EXPR_MISC), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/miscellaneous-query/$rand', }, { value: '$sampleRate', @@ -763,112 +762,98 @@ const stringExpressionOperators: readonly OperatorEntry[] = [ meta: META_EXPR_STRING, description: 'Concatenates two or more strings and returns the resulting string.', snippet: '{ $concat: ["${1:\\$string1}", "${2:\\$string2}"] }', - link: getDocLink('$concat', META_EXPR_STRING), }, { value: '$dateFromString', meta: META_EXPR_STRING, description: 'The $dateDiff operator converts a date/time string to a date object.', snippet: '{ $dateFromString: "${1:\\$string}" }', - link: getDocLink('$dateFromString', META_EXPR_STRING), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$datefromstring', }, { value: '$dateToString', meta: META_EXPR_STRING, description: 'The $dateToString operator converts a date object into a formatted string.', snippet: '{ $dateToString: "${1:\\$string}" }', - link: getDocLink('$dateToString', META_EXPR_STRING), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$datetostring', }, { value: '$indexOfBytes', meta: META_EXPR_STRING, description: 'Returns the byte index of the first occurrence of a substring within a string.', snippet: '{ $indexOfBytes: ["${1:\\$string}", "${2:substring}"] }', - link: getDocLink('$indexOfBytes', META_EXPR_STRING), }, { value: '$indexOfCP', meta: META_EXPR_STRING, description: 'Returns the code point index of the first occurrence of a substring within a string.', snippet: '{ $indexOfCP: ["${1:\\$string}", "${2:substring}"] }', - link: getDocLink('$indexOfCP', META_EXPR_STRING), }, { value: '$ltrim', meta: META_EXPR_STRING, description: 'Removes whitespace or specified characters from the beginning of a string.', snippet: '{ $ltrim: { input: "${1:\\$string}" } }', - link: getDocLink('$ltrim', META_EXPR_STRING), }, { value: '$regexFind', meta: META_EXPR_STRING, description: 'Applies a regular expression to a string and returns the first match.', snippet: '{ $regexFind: { input: "${1:\\$string}", regex: "${2:pattern}" } }', - link: getDocLink('$regexFind', META_EXPR_STRING), }, { value: '$regexFindAll', meta: META_EXPR_STRING, description: 'Applies a regular expression to a string and returns all matches as an array.', snippet: '{ $regexFindAll: { input: "${1:\\$string}", regex: "${2:pattern}" } }', - link: getDocLink('$regexFindAll', META_EXPR_STRING), }, { value: '$regexMatch', meta: META_EXPR_STRING, description: 'Applies a regular expression to a string and returns a boolean indicating if a match was found.', snippet: '{ $regexMatch: { input: "${1:\\$string}", regex: "${2:pattern}" } }', - link: getDocLink('$regexMatch', META_EXPR_STRING), }, { value: '$replaceOne', meta: META_EXPR_STRING, description: 'Replaces the first occurrence of a search string with a replacement string.', snippet: '{ $replaceOne: { input: "${1:\\$string}", find: "${2:find}", replacement: "${3:replacement}" } }', - link: getDocLink('$replaceOne', META_EXPR_STRING), }, { value: '$replaceAll', meta: META_EXPR_STRING, description: 'Replaces all occurrences of a search string with a replacement string.', snippet: '{ $replaceAll: { input: "${1:\\$string}", find: "${2:find}", replacement: "${3:replacement}" } }', - link: getDocLink('$replaceAll', META_EXPR_STRING), }, { value: '$rtrim', meta: META_EXPR_STRING, description: 'Removes whitespace or specified characters from the end of a string.', snippet: '{ $rtrim: { input: "${1:\\$string}" } }', - link: getDocLink('$rtrim', META_EXPR_STRING), }, { value: '$split', meta: META_EXPR_STRING, description: 'Splits a string by a delimiter and returns an array of substrings.', snippet: '{ $split: ["${1:\\$string}", "${2:delimiter}"] }', - link: getDocLink('$split', META_EXPR_STRING), }, { value: '$strLenBytes', meta: META_EXPR_STRING, description: 'Returns the number of UTF-8 encoded bytes in the specified string.', snippet: '{ $strLenBytes: "${1:\\$string}" }', - link: getDocLink('$strLenBytes', META_EXPR_STRING), }, { value: '$strLenCP', meta: META_EXPR_STRING, description: 'Returns the number of UTF-8 code points in the specified string.', snippet: '{ $strLenCP: "${1:\\$string}" }', - link: getDocLink('$strLenCP', META_EXPR_STRING), }, { value: '$strcasecmp', meta: META_EXPR_STRING, description: 'Performs a case-insensitive comparison of two strings and returns an integer.', snippet: '{ $strcasecmp: ["${1:\\$string1}", "${2:\\$string2}"] }', - link: getDocLink('$strcasecmp', META_EXPR_STRING), }, { value: '$substr', @@ -876,7 +861,6 @@ const stringExpressionOperators: readonly OperatorEntry[] = [ description: 'Returns a substring of a string, starting at a specified index for a specified length. Deprecated — use $substrBytes or $substrCP.', snippet: '{ $substr: ["${1:\\$string}", ${2:start}, ${3:length}] }', - link: getDocLink('$substr', META_EXPR_STRING), }, { value: '$substrBytes', @@ -884,7 +868,6 @@ const stringExpressionOperators: readonly OperatorEntry[] = [ description: 'Returns a substring of a string by byte index, starting at a specified index for a specified number of bytes.', snippet: '{ $substrBytes: ["${1:\\$string}", ${2:start}, ${3:length}] }', - link: getDocLink('$substrBytes', META_EXPR_STRING), }, { value: '$substrCP', @@ -892,35 +875,31 @@ const stringExpressionOperators: readonly OperatorEntry[] = [ description: 'Returns a substring of a string by code point index, starting at a specified index for a specified number of code points.', snippet: '{ $substrCP: ["${1:\\$string}", ${2:start}, ${3:length}] }', - link: getDocLink('$substrCP', META_EXPR_STRING), }, { value: '$toLower', meta: META_EXPR_STRING, description: 'Converts a string to lowercase and returns the result.', snippet: '{ $toLower: "${1:\\$string}" }', - link: getDocLink('$toLower', META_EXPR_STRING), }, { value: '$toString', meta: META_EXPR_STRING, description: 'The $toString operator converts an expression into a String', snippet: '{ $toString: "${1:\\$string}" }', - link: getDocLink('$toString', META_EXPR_STRING), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/type-expression/$tostring', }, { value: '$trim', meta: META_EXPR_STRING, description: 'Removes whitespace or specified characters from both ends of a string.', snippet: '{ $trim: { input: "${1:\\$string}" } }', - link: getDocLink('$trim', META_EXPR_STRING), }, { value: '$toUpper', meta: META_EXPR_STRING, description: 'Converts a string to uppercase and returns the result.', snippet: '{ $toUpper: "${1:\\$string}" }', - link: getDocLink('$toUpper', META_EXPR_STRING), }, ]; @@ -955,105 +934,90 @@ const trigonometryExpressionOperators: readonly OperatorEntry[] = [ meta: META_EXPR_TRIG, description: 'Returns the sine of a value measured in radians.', snippet: '{ $sin: "${1:\\$value}" }', - link: getDocLink('$sin', META_EXPR_TRIG), }, { value: '$cos', meta: META_EXPR_TRIG, description: 'Returns the cosine of a value measured in radians.', snippet: '{ $cos: "${1:\\$value}" }', - link: getDocLink('$cos', META_EXPR_TRIG), }, { value: '$tan', meta: META_EXPR_TRIG, description: 'Returns the tangent of a value measured in radians.', snippet: '{ $tan: "${1:\\$value}" }', - link: getDocLink('$tan', META_EXPR_TRIG), }, { value: '$asin', meta: META_EXPR_TRIG, description: 'Returns the arcsine (inverse sine) of a value in radians.', snippet: '{ $asin: "${1:\\$value}" }', - link: getDocLink('$asin', META_EXPR_TRIG), }, { value: '$acos', meta: META_EXPR_TRIG, description: 'Returns the arccosine (inverse cosine) of a value in radians.', snippet: '{ $acos: "${1:\\$value}" }', - link: getDocLink('$acos', META_EXPR_TRIG), }, { value: '$atan', meta: META_EXPR_TRIG, description: 'Returns the arctangent (inverse tangent) of a value in radians.', snippet: '{ $atan: "${1:\\$value}" }', - link: getDocLink('$atan', META_EXPR_TRIG), }, { value: '$atan2', meta: META_EXPR_TRIG, description: 'Returns the arctangent of the quotient of two values, using the signs to determine the quadrant.', snippet: '{ $atan2: "${1:\\$value}" }', - link: getDocLink('$atan2', META_EXPR_TRIG), }, { value: '$asinh', meta: META_EXPR_TRIG, description: 'Returns the inverse hyperbolic sine of a value.', snippet: '{ $asinh: "${1:\\$value}" }', - link: getDocLink('$asinh', META_EXPR_TRIG), }, { value: '$acosh', meta: META_EXPR_TRIG, description: 'Returns the inverse hyperbolic cosine of a value.', snippet: '{ $acosh: "${1:\\$value}" }', - link: getDocLink('$acosh', META_EXPR_TRIG), }, { value: '$atanh', meta: META_EXPR_TRIG, description: 'Returns the inverse hyperbolic tangent of a value.', snippet: '{ $atanh: "${1:\\$value}" }', - link: getDocLink('$atanh', META_EXPR_TRIG), }, { value: '$sinh', meta: META_EXPR_TRIG, description: 'Returns the hyperbolic sine of a value.', snippet: '{ $sinh: "${1:\\$value}" }', - link: getDocLink('$sinh', META_EXPR_TRIG), }, { value: '$cosh', meta: META_EXPR_TRIG, description: 'Returns the hyperbolic cosine of a value.', snippet: '{ $cosh: "${1:\\$value}" }', - link: getDocLink('$cosh', META_EXPR_TRIG), }, { value: '$tanh', meta: META_EXPR_TRIG, description: 'Returns the hyperbolic tangent of a value.', snippet: '{ $tanh: "${1:\\$value}" }', - link: getDocLink('$tanh', META_EXPR_TRIG), }, { value: '$degreesToRadians', meta: META_EXPR_TRIG, description: 'Converts a value from degrees to radians.', snippet: '{ $degreesToRadians: "${1:\\$angle}" }', - link: getDocLink('$degreesToRadians', META_EXPR_TRIG), }, { value: '$radiansToDegrees', meta: META_EXPR_TRIG, description: 'Converts a value from radians to degrees.', snippet: '{ $radiansToDegrees: "${1:\\$angle}" }', - link: getDocLink('$radiansToDegrees', META_EXPR_TRIG), }, ]; @@ -1137,7 +1101,7 @@ const typeExpressionOperators: readonly OperatorEntry[] = [ meta: META_EXPR_TYPE, description: 'The $type operator retrieves documents if the chosen field is of the specified type.', snippet: '{ $type: "${1:\\$field}" }', - link: getDocLink('$type', META_EXPR_TYPE), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/element-query/$type', }, ]; diff --git a/packages/documentdb-constants/src/operatorReference.test.ts b/packages/documentdb-constants/src/operatorReference.test.ts index 0d25db771..7f7de7521 100644 --- a/packages/documentdb-constants/src/operatorReference.test.ts +++ b/packages/documentdb-constants/src/operatorReference.test.ts @@ -17,7 +17,7 @@ import * as fs from 'fs'; import * as path from 'path'; import { getAllCompletions } from './index'; -import { parseOperatorReference } from './parseOperatorReference'; +import { parseOperatorReference, type ReferenceOperator } from './parseOperatorReference'; const dumpPath = path.join(__dirname, '..', 'resources', 'operator-reference-scraped.md'); const dumpContent = fs.readFileSync(dumpPath, 'utf-8'); @@ -130,7 +130,6 @@ describe('operator reference verification', () => { }); test('not-listed operators are NOT in the implementation', () => { - const implementedValues = new Set(implementedOperators.map((op) => op.value)); const leaked: string[] = []; for (const nl of notListedOperators) { @@ -162,3 +161,199 @@ describe('operator reference verification', () => { expect(notListedOperators.length).toBeLessThanOrEqual(20); }); }); + +// --------------------------------------------------------------------------- +// Merged dump + overrides verification +// +// The generator (scripts/generate-from-reference.ts) merges the scraped dump +// with manual overrides. These tests verify the implementation matches the +// MERGED result — catching scenarios where: +// - Someone hand-edits a generated .ts file instead of using overrides +// - Someone adds an override but forgets to run `npm run generate` +// - Someone runs `npm run scrape` but forgets `npm run generate` +// - The override file is accidentally truncated +// --------------------------------------------------------------------------- + +const overridesPath = path.join(__dirname, '..', 'resources', 'operator-reference-overrides.md'); +const overridesContent = fs.readFileSync(overridesPath, 'utf-8'); +const parsedOverrides = parseOperatorReference(overridesContent); +const overrideOperators = parsedOverrides.operators; + +/** + * Merges dump and override operators. For each (operator, category) pair, + * the override description wins if non-empty; otherwise the dump description + * is used. This mirrors what the generator does. + */ +function getMergedOperators(): readonly ReferenceOperator[] { + // Build a lookup: "operator|category" → override entry + const overrideLookup = new Map(); + for (const ov of overrideOperators) { + overrideLookup.set(`${ov.operator}|${ov.category}`, ov); + } + + return referenceOperators.map((ref) => { + const override = overrideLookup.get(`${ref.operator}|${ref.category}`); + if (!override) { + return ref; + } + return { + operator: ref.operator, + category: ref.category, + description: override.description || ref.description, + docLink: override.docLink || ref.docLink, + }; + }); +} + +const mergedOperators = getMergedOperators(); + +describe('merged dump + overrides verification', () => { + test('overrides file exists and has entries', () => { + expect(overridesContent.length).toBeGreaterThan(100); + expect(overrideOperators.length).toBeGreaterThan(0); + }); + + test('override count is within expected range (detect truncation)', () => { + // Currently 56 overrides. Allow some flex for additions/removals, + // but catch catastrophic truncation (e.g., file emptied to <10). + expect(overrideOperators.length).toBeGreaterThanOrEqual(40); + expect(overrideOperators.length).toBeLessThanOrEqual(80); + }); + + test('every override targets an operator that exists in the dump', () => { + const dumpKeys = new Set(referenceOperators.map((r) => `${r.operator}|${r.category}`)); + const orphans: string[] = []; + + for (const ov of overrideOperators) { + if (!dumpKeys.has(`${ov.operator}|${ov.category}`)) { + orphans.push(`${ov.operator} (${ov.category})`); + } + } + + expect(orphans).toEqual([]); + }); + + test('descriptions match the merged dump+overrides (detect hand-edits and stale generates)', () => { + const mismatches: string[] = []; + + for (const merged of mergedOperators) { + if (!merged.description) { + continue; // operator with no description in either dump or override + } + + const expectedMeta = CATEGORY_TO_META[merged.category]; + if (!expectedMeta) { + continue; + } + + const impl = implementedOperators.find((op) => op.value === merged.operator && op.meta === expectedMeta); + + if (impl && impl.description !== merged.description) { + mismatches.push( + `${merged.operator} (${merged.category}): ` + + `expected "${merged.description}", got "${impl.description}"`, + ); + } + } + + expect(mismatches).toEqual([]); + }); + + test('doc links from dump match implementation links for single-category operators', () => { + // Many operators appear in multiple dump categories (e.g., $eq in both + // "Comparison Query" and "Comparison Expression"). The scraper finds the + // doc page under whichever category directory it tries first, while the + // implementation generates URLs from each operator's meta tag. For + // cross-category operators, the dump link and impl link will point to + // different (but both valid) doc directories. + // + // This test only compares links for operators where the dump category + // maps to a unique operator — no cross-category ambiguity. + + // Known scraper mismatches: the scraper's global index fallback found + // these operators' doc pages under a different directory than their + // category implies. The implementation link is correct; the dump link is + // a scraper artifact. Update this set when refreshing the dump. + // + // NOTE: After fixing META_TO_DOC_DIR in docLinks.ts (expr:bool → logical-query, + // expr:comparison → comparison-query) and adding smart link emission in the + // generator (hardcoded URLs for cross-category fallbacks), this set should + // remain empty unless new scraper mismatches are discovered. + const KNOWN_SCRAPER_MISMATCHES = new Set([]); + + // Build a set of operators that appear in more than one dump category + const operatorCategories = new Map>(); + for (const ref of referenceOperators) { + const cats = operatorCategories.get(ref.operator) ?? new Set(); + cats.add(ref.category); + operatorCategories.set(ref.operator, cats); + } + + const mismatches: string[] = []; + + for (const ref of referenceOperators) { + if (!ref.docLink) { + continue; + } + + // Skip cross-category operators — their dump link may come from + // a different category than the implementation's meta tag + const cats = operatorCategories.get(ref.operator); + if (cats && cats.size > 1) { + continue; + } + + // Skip known scraper mismatches (documented above) + if (KNOWN_SCRAPER_MISMATCHES.has(ref.operator)) { + continue; + } + + const expectedMeta = CATEGORY_TO_META[ref.category]; + if (!expectedMeta) { + continue; + } + + const impl = implementedOperators.find((op) => op.value === ref.operator && op.meta === expectedMeta); + + if (!impl || !impl.link) { + continue; + } + + const dumpLink = ref.docLink.toLowerCase(); + const implLink = impl.link.toLowerCase(); + + if (dumpLink !== implLink) { + mismatches.push(`${ref.operator} (${ref.category}): ` + `dump="${ref.docLink}", impl="${impl.link}"`); + } + } + + expect(mismatches).toEqual([]); + }); + + test('every override with a description was applied (not silently ignored)', () => { + const unapplied: string[] = []; + + for (const ov of overrideOperators) { + if (!ov.description) { + continue; + } + + const expectedMeta = CATEGORY_TO_META[ov.category]; + if (!expectedMeta) { + continue; + } + + const impl = implementedOperators.find((op) => op.value === ov.operator && op.meta === expectedMeta); + + if (!impl) { + unapplied.push(`${ov.operator} (${ov.category}): no implementation entry found`); + } else if (impl.description !== ov.description) { + unapplied.push( + `${ov.operator} (${ov.category}): override="${ov.description}", ` + `impl="${impl.description}"`, + ); + } + } + + expect(unapplied).toEqual([]); + }); +}); diff --git a/packages/documentdb-constants/src/queryOperators.ts b/packages/documentdb-constants/src/queryOperators.ts index 5c18a5973..7c4dc095d 100644 --- a/packages/documentdb-constants/src/queryOperators.ts +++ b/packages/documentdb-constants/src/queryOperators.ts @@ -380,7 +380,7 @@ const projectionOperators: readonly OperatorEntry[] = [ meta: META_QUERY_PROJECTION, description: 'The $ positional operator identifies an element in an array to update without explicitly specifying the position of the element in the array.', - link: getDocLink('$', META_QUERY_PROJECTION), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$', }, { value: '$elemMatch', @@ -388,14 +388,14 @@ const projectionOperators: readonly OperatorEntry[] = [ description: 'The $elemmatch operator returns complete array, qualifying criteria with at least one matching array element.', snippet: '{ $elemMatch: { ${1:query} } }', - link: getDocLink('$elemMatch', META_QUERY_PROJECTION), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-query/$elemmatch', }, { value: '$slice', meta: META_QUERY_PROJECTION, description: 'The $slice operator returns a subset of an array from any element onwards in the array.', snippet: '{ $slice: ${1:number} }', - link: getDocLink('$slice', META_QUERY_PROJECTION), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$slice', }, ]; diff --git a/packages/documentdb-constants/src/stages.ts b/packages/documentdb-constants/src/stages.ts index cbe1d9fd0..7fe267497 100644 --- a/packages/documentdb-constants/src/stages.ts +++ b/packages/documentdb-constants/src/stages.ts @@ -41,7 +41,6 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ description: 'Categorizes documents into a specified number of groups based on a given expression, automatically determining bucket boundaries.', snippet: '{ $bucketAuto: { groupBy: "${1:\\$field}", buckets: ${2:number} } }', - link: getDocLink('$bucketAuto', META_STAGE), }, { value: '$changeStream', @@ -64,7 +63,7 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ description: 'The `$count` operator is used to count the number of documents that match a query filtering criteria.', snippet: '{ $count: "${1:countField}" }', - link: getDocLink('$count', META_STAGE), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$count', }, { value: '$densify', @@ -112,7 +111,6 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ 'Performs a recursive search on a collection to return documents connected by a specified field relationship.', snippet: '{ $graphLookup: { from: "${1:collection}", startWith: "${2:\\$field}", connectFromField: "${3:field}", connectToField: "${4:field}", as: "${5:result}" } }', - link: getDocLink('$graphLookup', META_STAGE), }, { value: '$group', @@ -134,7 +132,6 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ meta: META_STAGE, description: 'Restricts the number of documents passed to the next stage in the pipeline.', snippet: '{ $limit: ${1:number} }', - link: getDocLink('$limit', META_STAGE), }, { value: '$lookup', @@ -174,7 +171,6 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ meta: META_STAGE, description: 'Reshapes documents by including, excluding, or computing new fields.', snippet: '{ $project: { ${1:field}: 1 } }', - link: getDocLink('$project', META_STAGE), }, { value: '$redact', @@ -189,7 +185,6 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ meta: META_STAGE, description: 'Replaces the input document with a specified embedded document, promoting it to the top level.', snippet: '{ $replaceRoot: { newRoot: "${1:\\$field}" } }', - link: getDocLink('$replaceRoot', META_STAGE), }, { value: '$replaceWith', @@ -211,14 +206,12 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ meta: META_STAGE, description: 'Performs full-text search on string fields using Atlas Search or compatible search indexes.', snippet: '{ $search: { ${1} } }', - link: getDocLink('$search', META_STAGE), }, { value: '$searchMeta', meta: META_STAGE, description: 'Returns metadata about an Atlas Search query without returning the matching documents.', snippet: '{ $searchMeta: { ${1} } }', - link: getDocLink('$searchMeta', META_STAGE), }, { value: '$set', @@ -234,7 +227,6 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ 'Adds computed fields to documents using window functions over a specified partition and sort order.', snippet: '{ $setWindowFields: { partitionBy: "${1:\\$field}", sortBy: { ${2:field}: ${3:1} }, output: { ${4:newField}: { ${5:windowFunc} } } } }', - link: getDocLink('$setWindowFields', META_STAGE), }, { value: '$skip', @@ -265,7 +257,6 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ meta: META_STAGE, description: 'Combines the results of two collections into a single result set, similar to SQL UNION ALL.', snippet: '{ $unionWith: { coll: "${1:collection}", pipeline: [${2}] } }', - link: getDocLink('$unionWith', META_STAGE), }, { value: '$unset', @@ -287,7 +278,6 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ meta: META_STAGE, description: 'Returns information on active and queued operations for the database instance.', snippet: '{ $currentOp: { allUsers: true } }', - link: getDocLink('$currentOp', META_STAGE), }, ]; diff --git a/packages/documentdb-constants/src/systemVariables.ts b/packages/documentdb-constants/src/systemVariables.ts index e8c9d3546..f8c3c932f 100644 --- a/packages/documentdb-constants/src/systemVariables.ts +++ b/packages/documentdb-constants/src/systemVariables.ts @@ -11,7 +11,6 @@ // // To change operator data, edit the overrides file and re-run the generator. -import { getDocLink } from './docLinks'; import { registerOperators } from './getFilteredCompletions'; import { META_VARIABLE } from './metaTags'; import { type OperatorEntry } from './types'; @@ -26,49 +25,42 @@ const systemVariables: readonly OperatorEntry[] = [ meta: META_VARIABLE, description: 'Returns the current datetime as a Date object. Constant throughout a single aggregation pipeline.', - link: getDocLink('$$NOW', META_VARIABLE), }, { value: '$$ROOT', meta: META_VARIABLE, description: 'References the root document — the top-level document currently being processed in the pipeline stage.', - link: getDocLink('$$ROOT', META_VARIABLE), }, { value: '$$REMOVE', meta: META_VARIABLE, description: 'Removes a field from the output document. Used with $project or $addFields to conditionally exclude fields.', - link: getDocLink('$$REMOVE', META_VARIABLE), }, { value: '$$CURRENT', meta: META_VARIABLE, description: 'References the current document in the pipeline stage. Equivalent to $$ROOT at the start of the pipeline.', - link: getDocLink('$$CURRENT', META_VARIABLE), }, { value: '$$DESCEND', meta: META_VARIABLE, description: 'Used with $redact. Returns the document fields at the current level and continues descending into subdocuments.', - link: getDocLink('$$DESCEND', META_VARIABLE), }, { value: '$$PRUNE', meta: META_VARIABLE, description: 'Used with $redact. Excludes all fields at the current document level and stops descending into subdocuments.', - link: getDocLink('$$PRUNE', META_VARIABLE), }, { value: '$$KEEP', meta: META_VARIABLE, description: 'Used with $redact. Keeps all fields at the current document level without further descending into subdocuments.', - link: getDocLink('$$KEEP', META_VARIABLE), }, ]; diff --git a/packages/documentdb-constants/src/updateOperators.ts b/packages/documentdb-constants/src/updateOperators.ts index 2f504de59..750cd8742 100644 --- a/packages/documentdb-constants/src/updateOperators.ts +++ b/packages/documentdb-constants/src/updateOperators.ts @@ -41,14 +41,14 @@ const fieldUpdateOperators: readonly OperatorEntry[] = [ meta: META_UPDATE_FIELD, description: 'Retrieves the minimum value for a specified field', snippet: '{ $min: { "${1:field}": ${2:value} } }', - link: getDocLink('$min', META_UPDATE_FIELD), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$min', }, { value: '$max', meta: META_UPDATE_FIELD, description: 'The $max operator returns the maximum value from a set of input values.', snippet: '{ $max: { "${1:field}": ${2:value} } }', - link: getDocLink('$max', META_UPDATE_FIELD), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$max', }, { value: '$mul', @@ -69,7 +69,7 @@ const fieldUpdateOperators: readonly OperatorEntry[] = [ meta: META_UPDATE_FIELD, description: 'The $set operator in Azure DocumentDB updates or creates a new field with a specified value', snippet: '{ $set: { "${1:field}": ${2:value} } }', - link: getDocLink('$set', META_UPDATE_FIELD), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$set', }, { value: '$setOnInsert', @@ -84,7 +84,7 @@ const fieldUpdateOperators: readonly OperatorEntry[] = [ meta: META_UPDATE_FIELD, description: 'The $unset stage in the aggregation pipeline is used to remove specified fields from documents.', snippet: '{ $unset: { "${1:field}": ${2:value} } }', - link: getDocLink('$unset', META_UPDATE_FIELD), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$unset', }, ]; @@ -104,14 +104,12 @@ const arrayUpdateOperators: readonly OperatorEntry[] = [ value: '$[]', meta: META_UPDATE_ARRAY, description: 'Positional all operator. Acts as a placeholder to update all elements in an array field.', - link: getDocLink('$[]', META_UPDATE_ARRAY), }, { value: '$[identifier]', meta: META_UPDATE_ARRAY, description: 'Filtered positional operator. Acts as a placeholder to update elements that match an arrayFilters condition.', - link: getDocLink('$[identifier]', META_UPDATE_ARRAY), }, { value: '$addToSet', @@ -163,14 +161,13 @@ const arrayUpdateOperators: readonly OperatorEntry[] = [ description: 'Specifies the position in the array at which the $push operator inserts elements. Used with $each.', snippet: '{ $position: ${1:index} }', - link: getDocLink('$position', META_UPDATE_ARRAY), }, { value: '$slice', meta: META_UPDATE_ARRAY, description: 'The $slice operator returns a subset of an array from any element onwards in the array.', snippet: '{ $slice: ${1:number} }', - link: getDocLink('$slice', META_UPDATE_ARRAY), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$slice', }, { value: '$sort', @@ -178,7 +175,7 @@ const arrayUpdateOperators: readonly OperatorEntry[] = [ description: 'The $sort stage in the aggregation pipeline is used to order the documents in the pipeline by a specified field or fields.', snippet: '{ $sort: { "${1:field}": ${2:1} } }', - link: getDocLink('$sort', META_UPDATE_ARRAY), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$sort', }, ]; diff --git a/packages/documentdb-constants/src/windowOperators.ts b/packages/documentdb-constants/src/windowOperators.ts index aafb8e465..701356c2a 100644 --- a/packages/documentdb-constants/src/windowOperators.ts +++ b/packages/documentdb-constants/src/windowOperators.ts @@ -26,14 +26,14 @@ const windowOperators: readonly OperatorEntry[] = [ meta: META_WINDOW, description: 'The $sum operator calculates the sum of the values of a field based on a filtering criteria', snippet: '{ $sum: "${1:\\$field}" }', - link: getDocLink('$sum', META_WINDOW), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$sum', }, { value: '$push', meta: META_WINDOW, description: 'The $push operator adds a specified value to an array within a document.', snippet: '{ $push: "${1:\\$field}" }', - link: getDocLink('$push', META_WINDOW), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$push', }, { value: '$addToSet', @@ -41,7 +41,7 @@ const windowOperators: readonly OperatorEntry[] = [ description: "The addToSet operator adds elements to an array if they don't already exist, while ensuring uniqueness of elements within the set.", snippet: '{ $addToSet: "${1:\\$field}" }', - link: getDocLink('$addToSet', META_WINDOW), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$addtoset', }, { value: '$count', @@ -49,35 +49,35 @@ const windowOperators: readonly OperatorEntry[] = [ description: 'The `$count` operator is used to count the number of documents that match a query filtering criteria.', snippet: '{ $count: "${1:\\$field}" }', - link: getDocLink('$count', META_WINDOW), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$count', }, { value: '$max', meta: META_WINDOW, description: 'The $max operator returns the maximum value from a set of input values.', snippet: '{ $max: "${1:\\$field}" }', - link: getDocLink('$max', META_WINDOW), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$max', }, { value: '$min', meta: META_WINDOW, description: 'Retrieves the minimum value for a specified field', snippet: '{ $min: "${1:\\$field}" }', - link: getDocLink('$min', META_WINDOW), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$min', }, { value: '$avg', meta: META_WINDOW, description: 'Computes the average of numeric values for documents in a group, bucket, or window.', snippet: '{ $avg: "${1:\\$field}" }', - link: getDocLink('$avg', META_WINDOW), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$avg', }, { value: '$stdDevPop', meta: META_WINDOW, description: 'The $stddevpop operator calculates the standard deviation of the specified values', snippet: '{ $stdDevPop: "${1:\\$field}" }', - link: getDocLink('$stdDevPop', META_WINDOW), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$stddevpop', }, { value: '$bottom', @@ -85,14 +85,14 @@ const windowOperators: readonly OperatorEntry[] = [ description: "The $bottom operator returns the last document from the query's result set sorted by one or more fields", snippet: '{ $bottom: "${1:\\$field}" }', - link: getDocLink('$bottom', META_WINDOW), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$bottom', }, { value: '$bottomN', meta: META_WINDOW, description: 'The $bottomN operator returns the last N documents from the result sorted by one or more fields', snippet: '{ $bottomN: "${1:\\$field}" }', - link: getDocLink('$bottomN', META_WINDOW), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$bottomn', }, { value: '$covariancePop', @@ -145,7 +145,7 @@ const windowOperators: readonly OperatorEntry[] = [ meta: META_WINDOW, description: "The $first operator returns the first value in a group according to the group's sorting order.", snippet: '{ $first: "${1:\\$field}" }', - link: getDocLink('$first', META_WINDOW), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$first', }, { value: '$integral', @@ -160,7 +160,7 @@ const windowOperators: readonly OperatorEntry[] = [ meta: META_WINDOW, description: 'The $last operator returns the last document from the result sorted by one or more fields', snippet: '{ $last: "${1:\\$field}" }', - link: getDocLink('$last', META_WINDOW), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$last', }, { value: '$linearFill', @@ -183,7 +183,7 @@ const windowOperators: readonly OperatorEntry[] = [ meta: META_WINDOW, description: 'Retrieves the bottom N values based on a specified filtering criteria', snippet: '{ $minN: "${1:\\$field}" }', - link: getDocLink('$minN', META_WINDOW), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$minn', }, { value: '$rank', @@ -205,21 +205,21 @@ const windowOperators: readonly OperatorEntry[] = [ description: 'The $stddevsamp operator calculates the standard deviation of a specified sample of values and not the entire population', snippet: '{ $stdDevSamp: "${1:\\$field}" }', - link: getDocLink('$stdDevSamp', META_WINDOW), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$stddevsamp', }, { value: '$top', meta: META_WINDOW, description: 'The $top operator returns the first document from the result set sorted by one or more fields', snippet: '{ $top: "${1:\\$field}" }', - link: getDocLink('$top', META_WINDOW), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$top', }, { value: '$topN', meta: META_WINDOW, description: 'The $topN operator returns the first N documents from the result sorted by one or more fields', snippet: '{ $topN: "${1:\\$field}" }', - link: getDocLink('$topN', META_WINDOW), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$topn', }, ]; From 9096463296d1a65d98f4965ade2ed893aaa58477 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Fri, 20 Feb 2026 15:23:24 +0000 Subject: [PATCH 034/128] Refactor operator documentation generation and update paths - Updated the paths for scraped operator data and overrides in the generate-from-reference script. - Introduced snippet templates for operators, enhancing the generation process. - Adjusted the parsing logic to accommodate new snippet structures. - Modified the output files to reflect the new resource paths. - Updated tests and documentation to align with the new file structure. --- packages/documentdb-constants/README.md | 24 +- packages/documentdb-constants/package.json | 2 +- .../operator-overrides.md} | 4 +- .../resources/overrides/operator-snippets.md | 810 ++++++++++++++++++ .../operator-reference.md} | 0 .../documentdb-constants/scripts/README.md | 28 +- .../scripts/evaluate-overrides.ts | 172 +++- .../scripts/generate-from-reference.ts | 513 +++-------- .../scripts/scrape-operator-docs.ts | 8 +- .../documentdb-constants/src/accumulators.ts | 7 +- .../src/expressionOperators.ts | 7 +- .../src/operatorReference.test.ts | 6 +- .../src/parseOperatorReference.ts | 4 +- .../src/queryOperators.ts | 7 +- packages/documentdb-constants/src/stages.ts | 7 +- .../src/systemVariables.ts | 7 +- .../src/updateOperators.ts | 7 +- .../src/windowOperators.ts | 7 +- 18 files changed, 1162 insertions(+), 458 deletions(-) rename packages/documentdb-constants/resources/{operator-reference-overrides.md => overrides/operator-overrides.md} (98%) create mode 100644 packages/documentdb-constants/resources/overrides/operator-snippets.md rename packages/documentdb-constants/resources/{operator-reference-scraped.md => scraped/operator-reference.md} (100%) diff --git a/packages/documentdb-constants/README.md b/packages/documentdb-constants/README.md index f4c04b4ff..94588bae2 100644 --- a/packages/documentdb-constants/README.md +++ b/packages/documentdb-constants/README.md @@ -19,7 +19,7 @@ All operator data is derived from the official DocumentDB documentation: - **Per-operator docs:** [DocumentDB Operators](https://learn.microsoft.com/en-us/azure/documentdb/operators/) — individual pages with descriptions and syntax for each operator. - **Source repository:** [MicrosoftDocs/azure-databases-docs](https://github.com/MicrosoftDocs/azure-databases-docs) — the GitHub repo containing the raw Markdown source for all documentation pages above (under `articles/documentdb/`). -The scraper (`scripts/scrape-operator-docs.ts`) fetches data from these sources and generates the `resources/operator-reference-scraped.md` dump file that serves as the contract between the documentation and the TypeScript implementation. +The scraper (`scripts/scrape-operator-docs.ts`) fetches data from these sources and generates the `resources/scraped/operator-reference.md` dump file that serves as the contract between the documentation and the TypeScript implementation. ## Usage @@ -57,18 +57,20 @@ This runs the scraper and then formats the output with Prettier. The scraper: 1. **Verifies** upstream doc structure (early fail-fast) 2. **Extracts** all operators from the [compatibility page](https://learn.microsoft.com/en-us/azure/documentdb/compatibility-query-language) 3. **Fetches** per-operator documentation (descriptions, syntax) with a global file index fallback for operators filed in unexpected directories -4. **Generates** `resources/operator-reference-scraped.md` in a structured heading format (`### $operator` with description, syntax, and doc link) +4. **Generates** `resources/scraped/operator-reference.md` in a structured heading format (`### $operator` with description, syntax, and doc link) The dump serves as the authoritative reference for the TypeScript implementation. A Jest test (`test/operatorReference.test.ts`) will validate that the implementation matches the dump. ## Structure -| File | Purpose | -| ----------------------------------------- | -------------------------------------------- | -| `src/types.ts` | `OperatorEntry` interface and `MetaTag` type | -| `src/metaTags.ts` | Meta tag constants and completion presets | -| `src/docLinks.ts` | Documentation URL generation | -| `src/getFilteredCompletions.ts` | Primary consumer API: filter by meta tags | -| `src/index.ts` | Barrel exports for all public API | -| `resources/operator-reference-scraped.md` | Auto-generated scraped operator dump | -| `scripts/scrape-operator-docs.ts` | Scraper script | +| File | Purpose | +| ------------------------------------------- | -------------------------------------------- | +| `src/types.ts` | `OperatorEntry` interface and `MetaTag` type | +| `src/metaTags.ts` | Meta tag constants and completion presets | +| `src/docLinks.ts` | Documentation URL generation | +| `src/getFilteredCompletions.ts` | Primary consumer API: filter by meta tags | +| `src/index.ts` | Barrel exports for all public API | +| `resources/scraped/operator-reference.md` | Auto-generated scraped operator dump | +| `resources/overrides/operator-overrides.md` | Hand-maintained overrides | +| `resources/overrides/operator-snippets.md` | Snippet templates per category | +| `scripts/scrape-operator-docs.ts` | Scraper script | diff --git a/packages/documentdb-constants/package.json b/packages/documentdb-constants/package.json index 1b78cae79..b9719e618 100644 --- a/packages/documentdb-constants/package.json +++ b/packages/documentdb-constants/package.json @@ -12,7 +12,7 @@ "clean": "rimraf dist tsconfig.tsbuildinfo", "test": "jest --config jest.config.js", "prettier-fix": "prettier -w \"(scripts|src)/**/*.@(js|ts|jsx|tsx|json|md)\" \"./*.@(js|ts|jsx|tsx|json|md)\"", - "scrape": "ts-node scripts/scrape-operator-docs.ts && prettier --write resources/operator-reference-scraped.md", + "scrape": "ts-node scripts/scrape-operator-docs.ts && prettier --write resources/scraped/operator-reference.md", "generate": "ts-node scripts/generate-from-reference.ts && prettier --write \"src/queryOperators.ts\" \"src/updateOperators.ts\" \"src/expressionOperators.ts\" \"src/accumulators.ts\" \"src/windowOperators.ts\" \"src/stages.ts\" \"src/systemVariables.ts\"", "evaluate": "ts-node scripts/evaluate-overrides.ts" }, diff --git a/packages/documentdb-constants/resources/operator-reference-overrides.md b/packages/documentdb-constants/resources/overrides/operator-overrides.md similarity index 98% rename from packages/documentdb-constants/resources/operator-reference-overrides.md rename to packages/documentdb-constants/resources/overrides/operator-overrides.md index 834c78259..521297c9d 100644 --- a/packages/documentdb-constants/resources/operator-reference-overrides.md +++ b/packages/documentdb-constants/resources/overrides/operator-overrides.md @@ -1,7 +1,7 @@ # DocumentDB Operator Reference — Overrides - + @@ -11,7 +11,7 @@ - + diff --git a/packages/documentdb-constants/resources/overrides/operator-snippets.md b/packages/documentdb-constants/resources/overrides/operator-snippets.md new file mode 100644 index 000000000..9b3adf63e --- /dev/null +++ b/packages/documentdb-constants/resources/overrides/operator-snippets.md @@ -0,0 +1,810 @@ +# Operator Snippets + + + +## Aggregation Pipeline Stages + +### DEFAULT + +- **Snippet:** `{ {{VALUE}}: { ${1} } }` + +### $match + +- **Snippet:** `{ $match: { ${1:query} } }` + +### $group + +- **Snippet:** `{ $group: { _id: "${1:\$field}", ${2:accumulator}: { ${3:\$sum}: 1 } } }` + +### $project + +- **Snippet:** `{ $project: { ${1:field}: 1 } }` + +### $sort + +- **Snippet:** `{ $sort: { ${1:field}: ${2:1} } }` + +### $limit + +- **Snippet:** `{ $limit: ${1:number} }` + +### $skip + +- **Snippet:** `{ $skip: ${1:number} }` + +### $unwind + +- **Snippet:** `{ $unwind: "${1:\$arrayField}" }` + +### $lookup + +- **Snippet:** `{ $lookup: { from: "${1:collection}", localField: "${2:field}", foreignField: "${3:field}", as: "${4:result}" } }` + +### $addFields + +- **Snippet:** `{ $addFields: { ${1:newField}: ${2:expression} } }` + +### $set + +- **Snippet:** `{ $set: { ${1:field}: ${2:expression} } }` + +### $unset + +- **Snippet:** `{ $unset: "${1:field}" }` + +### $replaceRoot + +- **Snippet:** `{ $replaceRoot: { newRoot: "${1:\$field}" } }` + +### $replaceWith + +- **Snippet:** `{ $replaceWith: "${1:\$field}" }` + +### $count + +- **Snippet:** `{ $count: "${1:countField}" }` + +### $out + +- **Snippet:** `{ $out: "${1:collection}" }` + +### $merge + +- **Snippet:** `{ $merge: { into: "${1:collection}" } }` + +### $bucket + +- **Snippet:** `{ $bucket: { groupBy: "${1:\$field}", boundaries: [${2:values}], default: "${3:Other}" } }` + +### $bucketAuto + +- **Snippet:** `{ $bucketAuto: { groupBy: "${1:\$field}", buckets: ${2:number} } }` + +### $facet + +- **Snippet:** `{ $facet: { ${1:outputField}: [{ ${2:stage} }] } }` + +### $graphLookup + +- **Snippet:** `{ $graphLookup: { from: "${1:collection}", startWith: "${2:\$field}", connectFromField: "${3:field}", connectToField: "${4:field}", as: "${5:result}" } }` + +### $sample + +- **Snippet:** `{ $sample: { size: ${1:number} } }` + +### $sortByCount + +- **Snippet:** `{ $sortByCount: "${1:\$field}" }` + +### $redact + +- **Snippet:** `{ $redact: { \$cond: { if: { ${1:expression} }, then: "${2:\$\$DESCEND}", else: "${3:\$\$PRUNE}" } } }` + +### $unionWith + +- **Snippet:** `{ $unionWith: { coll: "${1:collection}", pipeline: [${2}] } }` + +### $setWindowFields + +- **Snippet:** `{ $setWindowFields: { partitionBy: "${1:\$field}", sortBy: { ${2:field}: ${3:1} }, output: { ${4:newField}: { ${5:windowFunc} } } } }` + +### $densify + +- **Snippet:** `{ $densify: { field: "${1:field}", range: { step: ${2:1}, bounds: "full" } } }` + +### $fill + +- **Snippet:** `{ $fill: { output: { ${1:field}: { method: "${2:linear}" } } } }` + +### $documents + +- **Snippet:** `{ $documents: [${1:documents}] }` + +### $changeStream + +- **Snippet:** `{ $changeStream: {} }` + +### $collStats + +- **Snippet:** `{ $collStats: { storageStats: {} } }` + +### $currentOp + +- **Snippet:** `{ $currentOp: { allUsers: true } }` + +### $indexStats + +- **Snippet:** `{ $indexStats: {} }` + +### $listLocalSessions + +- **Snippet:** `{ $listLocalSessions: { allUsers: true } }` + +### $geoNear + +- **Snippet:** `{ $geoNear: { near: { type: "Point", coordinates: [${1:lng}, ${2:lat}] }, distanceField: "${3:distance}" } }` + +## Comparison Query Operators + +### DEFAULT + +- **Snippet:** `{ {{VALUE}}: ${1:value} }` + +### $in + +- **Snippet:** `{ $in: [${1:value}] }` + +### $nin + +- **Snippet:** `{ $nin: [${1:value}] }` + +## Logical Query Operators + +### DEFAULT + +- **Snippet:** `{ {{VALUE}}: [{ ${1:expression} }] }` + +### $not + +- **Snippet:** `{ $not: { ${1:expression} } }` + +## Element Query Operators + +### $exists + +- **Snippet:** `{ $exists: ${1:true} }` + +### $type + +- **Snippet:** `{ $type: "${1:type}" }` + +## Evaluation Query Operators + +### $expr + +- **Snippet:** `{ $expr: { ${1:expression} } }` + +### $regex + +- **Snippet:** `{ $regex: /${1:pattern}/ }` + +### $mod + +- **Snippet:** `{ $mod: [${1:divisor}, ${2:remainder}] }` + +### $text + +- **Snippet:** `{ $text: { \$search: "${1:text}" } }` + +### $jsonSchema + +- **Snippet:** `{ $jsonSchema: { bsonType: "${1:object}" } }` + +## Array Query Operators + +### $all + +- **Snippet:** `{ $all: [${1:value}] }` + +### $elemMatch + +- **Snippet:** `{ $elemMatch: { ${1:query} } }` + +### $size + +- **Snippet:** `{ $size: ${1:number} }` + +## Bitwise Query Operators + +### DEFAULT + +- **Snippet:** `{ {{VALUE}}: ${1:bitmask} }` + +## Geospatial Operators + +### $near + +- **Snippet:** `{ $near: { \$geometry: { type: "Point", coordinates: [${1:lng}, ${2:lat}] }, \$maxDistance: ${3:distance} } }` + +### $nearSphere + +- **Snippet:** `{ $nearSphere: { \$geometry: { type: "Point", coordinates: [${1:lng}, ${2:lat}] }, \$maxDistance: ${3:distance} } }` + +### $geoIntersects + +- **Snippet:** `{ $geoIntersects: { \$geometry: { type: "${1:GeoJSON type}", coordinates: ${2:coordinates} } } }` + +### $geoWithin + +- **Snippet:** `{ $geoWithin: { \$geometry: { type: "${1:GeoJSON type}", coordinates: ${2:coordinates} } } }` + +### $box + +- **Snippet:** `[[${1:bottomLeftX}, ${2:bottomLeftY}], [${3:upperRightX}, ${4:upperRightY}]]` + +### $center + +- **Snippet:** `[[${1:x}, ${2:y}], ${3:radius}]` + +### $centerSphere + +- **Snippet:** `[[${1:x}, ${2:y}], ${3:radiusInRadians}]` + +### $geometry + +- **Snippet:** `{ type: "${1:Point}", coordinates: [${2:coordinates}] }` + +### $maxDistance + +- **Snippet:** `${1:distance}` + +### $minDistance + +- **Snippet:** `${1:distance}` + +### $polygon + +- **Snippet:** `[[${1:x1}, ${2:y1}], [${3:x2}, ${4:y2}], [${5:x3}, ${6:y3}]]` + +## Projection Operators + +### $elemMatch + +- **Snippet:** `{ $elemMatch: { ${1:query} } }` + +### $slice + +- **Snippet:** `{ $slice: ${1:number} }` + +## Miscellaneous Query Operators + +### $comment + +- **Snippet:** `{ $comment: "${1:comment}" }` + +### $rand + +- **Snippet:** `{ $rand: {} }` + +### $natural + +- **Snippet:** `{ $natural: ${1:1} }` + +## Field Update Operators + +### DEFAULT + +- **Snippet:** `{ {{VALUE}}: { "${1:field}": ${2:value} } }` + +### $rename + +- **Snippet:** `{ $rename: { "${1:oldField}": "${2:newField}" } }` + +### $currentDate + +- **Snippet:** `{ $currentDate: { "${1:field}": true } }` + +## Array Update Operators + +### $addToSet + +- **Snippet:** `{ $addToSet: { "${1:field}": ${2:value} } }` + +### $pop + +- **Snippet:** `{ $pop: { "${1:field}": ${2:1} } }` + +### $pull + +- **Snippet:** `{ $pull: { "${1:field}": ${2:condition} } }` + +### $push + +- **Snippet:** `{ $push: { "${1:field}": ${2:value} } }` + +### $pullAll + +- **Snippet:** `{ $pullAll: { "${1:field}": [${2:values}] } }` + +### $each + +- **Snippet:** `{ $each: [${1:values}] }` + +### $position + +- **Snippet:** `{ $position: ${1:index} }` + +### $slice + +- **Snippet:** `{ $slice: ${1:number} }` + +### $sort + +- **Snippet:** `{ $sort: { "${1:field}": ${2:1} } }` + +## Bitwise Update Operators + +### DEFAULT + +- **Snippet:** `{ {{VALUE}}: { "${1:field}": { "${2:and|or|xor}": ${3:value} } } }` + +## Accumulators + +### DEFAULT + +- **Snippet:** `{ {{VALUE}}: "${1:\$field}" }` + +### $count + +- **Snippet:** `{ $count: {} }` + +### $bottom + +- **Snippet:** `{ $bottom: { sortBy: { ${1:field}: ${2:1} }, output: "${3:\$field}" } }` + +### $top + +- **Snippet:** `{ $top: { sortBy: { ${1:field}: ${2:1} }, output: "${3:\$field}" } }` + +### $bottomN + +- **Snippet:** `{ $bottomN: { n: ${1:number}, sortBy: { ${2:field}: ${3:1} }, output: "${4:\$field}" } }` + +### $topN + +- **Snippet:** `{ $topN: { n: ${1:number}, sortBy: { ${2:field}: ${3:1} }, output: "${4:\$field}" } }` + +### $firstN + +- **Snippet:** `{ $firstN: { input: "${1:\$field}", n: ${2:number} } }` + +### $lastN + +- **Snippet:** `{ $lastN: { input: "${1:\$field}", n: ${2:number} } }` + +### $maxN + +- **Snippet:** `{ $maxN: { input: "${1:\$field}", n: ${2:number} } }` + +### $minN + +- **Snippet:** `{ $minN: { input: "${1:\$field}", n: ${2:number} } }` + +### $percentile + +- **Snippet:** `{ $percentile: { input: "${1:\$field}", p: [${2:0.5}], method: "approximate" } }` + +### $median + +- **Snippet:** `{ $median: { input: "${1:\$field}", method: "approximate" } }` + +## Window Operators + +### DEFAULT + +- **Snippet:** `{ {{VALUE}}: "${1:\$field}" }` + +### $shift + +- **Snippet:** `{ $shift: { output: "${1:\$field}", by: ${2:1}, default: ${3:null} } }` + +### $rank + +- **Snippet:** `{ $rank: {} }` + +### $denseRank + +- **Snippet:** `{ $denseRank: {} }` + +### $documentNumber + +- **Snippet:** `{ $documentNumber: {} }` + +### $expMovingAvg + +- **Snippet:** `{ $expMovingAvg: { input: "${1:\$field}", N: ${2:number} } }` + +### $derivative + +- **Snippet:** `{ $derivative: { input: "${1:\$field}", unit: "${2:hour}" } }` + +### $integral + +- **Snippet:** `{ $integral: { input: "${1:\$field}", unit: "${2:hour}" } }` + +## Arithmetic Expression Operators + +### DEFAULT + +- **Snippet:** `{ {{VALUE}}: "${1:\$field}" }` + +### $add + +- **Snippet:** `{ $add: ["${1:\$field1}", "${2:\$field2}"] }` + +### $subtract + +- **Snippet:** `{ $subtract: ["${1:\$field1}", "${2:\$field2}"] }` + +### $multiply + +- **Snippet:** `{ $multiply: ["${1:\$field1}", "${2:\$field2}"] }` + +### $divide + +- **Snippet:** `{ $divide: ["${1:\$field1}", "${2:\$field2}"] }` + +### $mod + +- **Snippet:** `{ $mod: ["${1:\$field1}", "${2:\$field2}"] }` + +### $pow + +- **Snippet:** `{ $pow: ["${1:\$field1}", "${2:\$field2}"] }` + +### $log + +- **Snippet:** `{ $log: ["${1:\$number}", ${2:base}] }` + +### $round + +- **Snippet:** `{ $round: ["${1:\$field}", ${2:place}] }` + +## Array Expression Operators + +### DEFAULT + +- **Snippet:** `{ {{VALUE}}: "${1:\$array}" }` + +### $arrayElemAt + +- **Snippet:** `{ $arrayElemAt: ["${1:\$array}", ${2:index}] }` + +### $concatArrays + +- **Snippet:** `{ $concatArrays: ["${1:\$array1}", "${2:\$array2}"] }` + +### $filter + +- **Snippet:** `{ $filter: { input: "${1:\$array}", as: "${2:item}", cond: { ${3:expression} } } }` + +### $in + +- **Snippet:** `{ $in: ["${1:\$field}", "${2:\$array}"] }` + +### $indexOfArray + +- **Snippet:** `{ $indexOfArray: ["${1:\$array}", "${2:value}"] }` + +### $isArray + +- **Snippet:** `{ $isArray: "${1:\$field}" }` + +### $map + +- **Snippet:** `{ $map: { input: "${1:\$array}", as: "${2:item}", in: { ${3:expression} } } }` + +### $objectToArray + +- **Snippet:** `{ $objectToArray: "${1:\$object}" }` + +### $range + +- **Snippet:** `{ $range: [${1:start}, ${2:end}, ${3:step}] }` + +### $reduce + +- **Snippet:** `{ $reduce: { input: "${1:\$array}", initialValue: ${2:0}, in: { ${3:expression} } } }` + +### $slice + +- **Snippet:** `{ $slice: ["${1:\$array}", ${2:n}] }` + +### $sortArray + +- **Snippet:** `{ $sortArray: { input: "${1:\$array}", sortBy: { ${2:field}: ${3:1} } } }` + +### $zip + +- **Snippet:** `{ $zip: { inputs: ["${1:\$array1}", "${2:\$array2}"] } }` + +### $maxN + +- **Snippet:** `{ $maxN: { input: "${1:\$array}", n: ${2:number} } }` + +### $minN + +- **Snippet:** `{ $minN: { input: "${1:\$array}", n: ${2:number} } }` + +### $firstN + +- **Snippet:** `{ $firstN: { input: "${1:\$array}", n: ${2:number} } }` + +### $lastN + +- **Snippet:** `{ $lastN: { input: "${1:\$array}", n: ${2:number} } }` + +## Boolean Expression Operators + +### DEFAULT + +- **Snippet:** `{ {{VALUE}}: ["${1:expression1}", "${2:expression2}"] }` + +### $not + +- **Snippet:** `{ $not: ["${1:expression}"] }` + +## Comparison Expression Operators + +### DEFAULT + +- **Snippet:** `{ {{VALUE}}: ["${1:\$field1}", "${2:\$field2}"] }` + +## Conditional Expression Operators + +### $cond + +- **Snippet:** `{ $cond: { if: { ${1:expression} }, then: ${2:trueValue}, else: ${3:falseValue} } }` + +### $ifNull + +- **Snippet:** `{ $ifNull: ["${1:\$field}", ${2:replacement}] }` + +### $switch + +- **Snippet:** `{ $switch: { branches: [{ case: { ${1:expression} }, then: ${2:value} }], default: ${3:defaultValue} } }` + +## Date Expression Operators + +### DEFAULT + +- **Snippet:** `{ {{VALUE}}: "${1:\$dateField}" }` + +### $dateAdd + +- **Snippet:** `{ $dateAdd: { startDate: "${1:\$dateField}", unit: "${2:day}", amount: ${3:1} } }` + +### $dateSubtract + +- **Snippet:** `{ $dateSubtract: { startDate: "${1:\$dateField}", unit: "${2:day}", amount: ${3:1} } }` + +### $dateDiff + +- **Snippet:** `{ $dateDiff: { startDate: "${1:\$startDate}", endDate: "${2:\$endDate}", unit: "${3:day}" } }` + +### $dateFromParts + +- **Snippet:** `{ $dateFromParts: { year: ${1:2024}, month: ${2:1}, day: ${3:1} } }` + +### $dateToParts + +- **Snippet:** `{ $dateToParts: { date: "${1:\$dateField}" } }` + +### $dateFromString + +- **Snippet:** `{ $dateFromString: { dateString: "${1:dateString}" } }` + +### $dateToString + +- **Snippet:** `{ $dateToString: { format: "${1:%Y-%m-%d}", date: "${2:\$dateField}" } }` + +### $dateTrunc + +- **Snippet:** `{ $dateTrunc: { date: "${1:\$dateField}", unit: "${2:day}" } }` + +### $toDate + +- **Snippet:** `{ $toDate: "${1:\$field}" }` + +## Object Expression Operators + +### DEFAULT + +- **Snippet:** `{ {{VALUE}}: "${1:\$object}" }` + +### $mergeObjects + +- **Snippet:** `{ $mergeObjects: ["${1:\$object1}", "${2:\$object2}"] }` + +### $setField + +- **Snippet:** `{ $setField: { field: "${1:fieldName}", input: "${2:\$object}", value: ${3:value} } }` + +## Set Expression Operators + +### DEFAULT + +- **Snippet:** `{ {{VALUE}}: ["${1:\$set1}", "${2:\$set2}"] }` + +### $anyElementTrue + +- **Snippet:** `{ $anyElementTrue: ["${1:\$array}"] }` + +### $allElementsTrue + +- **Snippet:** `{ $allElementsTrue: ["${1:\$array}"] }` + +## String Expression Operators + +### DEFAULT + +- **Snippet:** `{ {{VALUE}}: "${1:\$string}" }` + +### $concat + +- **Snippet:** `{ $concat: ["${1:\$string1}", "${2:\$string2}"] }` + +### $indexOfBytes + +- **Snippet:** `{ $indexOfBytes: ["${1:\$string}", "${2:substring}"] }` + +### $indexOfCP + +- **Snippet:** `{ $indexOfCP: ["${1:\$string}", "${2:substring}"] }` + +### $regexFind + +- **Snippet:** `{ $regexFind: { input: "${1:\$string}", regex: "${2:pattern}" } }` + +### $regexFindAll + +- **Snippet:** `{ $regexFindAll: { input: "${1:\$string}", regex: "${2:pattern}" } }` + +### $regexMatch + +- **Snippet:** `{ $regexMatch: { input: "${1:\$string}", regex: "${2:pattern}" } }` + +### $replaceOne + +- **Snippet:** `{ $replaceOne: { input: "${1:\$string}", find: "${2:find}", replacement: "${3:replacement}" } }` + +### $replaceAll + +- **Snippet:** `{ $replaceAll: { input: "${1:\$string}", find: "${2:find}", replacement: "${3:replacement}" } }` + +### $split + +- **Snippet:** `{ $split: ["${1:\$string}", "${2:delimiter}"] }` + +### $substr + +- **Snippet:** `{ $substr: ["${1:\$string}", ${2:start}, ${3:length}] }` + +### $substrBytes + +- **Snippet:** `{ $substrBytes: ["${1:\$string}", ${2:start}, ${3:length}] }` + +### $substrCP + +- **Snippet:** `{ $substrCP: ["${1:\$string}", ${2:start}, ${3:length}] }` + +### $strcasecmp + +- **Snippet:** `{ $strcasecmp: ["${1:\$string1}", "${2:\$string2}"] }` + +### $trim + +- **Snippet:** `{ $trim: { input: "${1:\$string}" } }` + +### $ltrim + +- **Snippet:** `{ $ltrim: { input: "${1:\$string}" } }` + +### $rtrim + +- **Snippet:** `{ $rtrim: { input: "${1:\$string}" } }` + +## Trigonometry Expression Operators + +### DEFAULT + +- **Snippet:** `{ {{VALUE}}: "${1:\$value}" }` + +### $degreesToRadians + +- **Snippet:** `{ $degreesToRadians: "${1:\$angle}" }` + +### $radiansToDegrees + +- **Snippet:** `{ $radiansToDegrees: "${1:\$angle}" }` + +## Type Expression Operators + +### DEFAULT + +- **Snippet:** `{ {{VALUE}}: "${1:\$field}" }` + +### $convert + +- **Snippet:** `{ $convert: { input: "${1:\$field}", to: "${2:type}" } }` + +## Data Size Operators + +### DEFAULT + +- **Snippet:** `{ {{VALUE}}: "${1:\$field}" }` + +## Literal Expression Operator + +### DEFAULT + +- **Snippet:** `{ {{VALUE}}: ${1:value} }` + +## Miscellaneous Operators + +### DEFAULT + +- **Snippet:** `{ {{VALUE}}: ${1:value} }` + +### $getField + +- **Snippet:** `{ $getField: { field: "${1:fieldName}", input: "${2:\$object}" } }` + +### $rand + +- **Snippet:** `{ $rand: {} }` + +### $sampleRate + +- **Snippet:** `{ $sampleRate: ${1:0.5} }` + +## Bitwise Operators + +### DEFAULT + +- **Snippet:** `{ {{VALUE}}: [${1:value1}, ${2:value2}] }` + +### $bitNot + +- **Snippet:** `{ $bitNot: "${1:\$field}" }` + +## Timestamp Expression Operators + +### DEFAULT + +- **Snippet:** `{ {{VALUE}}: "${1:\$timestampField}" }` + +## Variable Expression Operators + +### $let + +- **Snippet:** `{ $let: { vars: { ${1:var}: ${2:expression} }, in: ${3:expression} } }` diff --git a/packages/documentdb-constants/resources/operator-reference-scraped.md b/packages/documentdb-constants/resources/scraped/operator-reference.md similarity index 100% rename from packages/documentdb-constants/resources/operator-reference-scraped.md rename to packages/documentdb-constants/resources/scraped/operator-reference.md diff --git a/packages/documentdb-constants/scripts/README.md b/packages/documentdb-constants/scripts/README.md index fb30afbe8..d642ecb08 100644 --- a/packages/documentdb-constants/scripts/README.md +++ b/packages/documentdb-constants/scripts/README.md @@ -4,7 +4,7 @@ Helper scripts for maintaining the `@vscode-documentdb/documentdb-constants` pac ## scrape-operator-docs.ts -Scrapes the DocumentDB compatibility page and per-operator documentation to produce `resources/operator-reference-scraped.md`. +Scrapes the DocumentDB compatibility page and per-operator documentation to produce `resources/scraped/operator-reference.md`. ```bash npm run scrape @@ -12,11 +12,11 @@ npm run scrape **When to run:** When the upstream DocumentDB documentation changes (new operators, updated descriptions, etc.). This is infrequent — typically once per DocumentDB release. -**Output:** `resources/operator-reference-scraped.md` — a machine-generated Markdown dump of all supported operators, their descriptions, syntax blocks, and doc links. +**Output:** `resources/scraped/operator-reference.md` — a machine-generated Markdown dump of all supported operators, their descriptions, syntax blocks, and doc links. ## generate-from-reference.ts -Reads the scraped dump and the hand-maintained overrides file, then generates the TypeScript operator data files in `src/`. +Reads the scraped dump, hand-maintained overrides file, and snippet templates, then generates the TypeScript operator data files in `src/`. ```bash npm run generate @@ -25,14 +25,16 @@ npm run generate **When to run:** - After running the scraper (`npm run scrape`) -- After editing `resources/operator-reference-overrides.md` +- After editing `resources/overrides/operator-overrides.md` +- After editing `resources/overrides/operator-snippets.md` **Inputs:** | File | Purpose | | ------------------------------------------- | ---------------------------------- | -| `resources/operator-reference-scraped.md` | Primary data (machine-generated) | -| `resources/operator-reference-overrides.md` | Manual overrides (hand-maintained) | +| `resources/scraped/operator-reference.md` | Primary data (machine-generated) | +| `resources/overrides/operator-overrides.md` | Manual overrides (hand-maintained) | +| `resources/overrides/operator-snippets.md` | Snippet templates per category | **Outputs:** Seven TypeScript files in `src/`: @@ -44,11 +46,11 @@ npm run generate - `stages.ts` — aggregation pipeline stages - `systemVariables.ts` — system variables (`$$NOW`, `$$ROOT`, etc.) -> **Do not edit the generated `src/` files by hand.** Put corrections in `resources/operator-reference-overrides.md` instead. The generated files contain a header warning to this effect. +> **Do not edit the generated `src/` files by hand.** Put corrections in the overrides or snippets files instead. The generated files contain a header warning to this effect. ## evaluate-overrides.ts -Evaluates the relationship between scraped data and manual overrides. Produces a color-coded report. +Evaluates the relationship between scraped data, manual overrides, and snippet coverage. Produces a color-coded report. ```bash npm run evaluate @@ -64,7 +66,8 @@ npm run evaluate 1. **GAPS** — operators with empty scraped descriptions and no override (need attention) 2. **POTENTIALLY REDUNDANT** — operators that have **both** a scraped description and an override description; the override may no longer be needed 3. **ACTIVE OVERRIDES** — overrides filling real gaps, with both override and scraped values shown -4. **SUMMARY** — total counts and coverage percentage +4. **SNIPPET COVERAGE** — operators with/without snippet templates per category +5. **SUMMARY** — total counts and coverage percentage ## Workflow @@ -76,11 +79,12 @@ npm run evaluate npm run scrape │ ▼ - operator-reference-scraped.md + scraped/operator-reference.md │ - ├──── npm run evaluate (check gaps & redundant overrides) + ├──── npm run evaluate (check gaps, redundant overrides & snippet coverage) │ - ├──── operator-reference-overrides.md (manual) + ├──── overrides/operator-overrides.md (manual) + ├──── overrides/operator-snippets.md (manual) │ ▼ npm run generate diff --git a/packages/documentdb-constants/scripts/evaluate-overrides.ts b/packages/documentdb-constants/scripts/evaluate-overrides.ts index 671a9ddae..bf9bfb532 100644 --- a/packages/documentdb-constants/scripts/evaluate-overrides.ts +++ b/packages/documentdb-constants/scripts/evaluate-overrides.ts @@ -157,7 +157,11 @@ function parseOverrides(content: string): Map currentOp.entry.docLink = line.replace('- **Doc Link:**', '').trim(); } if (line.startsWith('- **Snippet:**')) { - currentOp.entry.snippet = line.replace('- **Snippet:**', '').trim(); + let snippet = line.replace('- **Snippet:**', '').trim(); + if (snippet.startsWith('`') && snippet.endsWith('`')) { + snippet = snippet.slice(1, -1); + } + currentOp.entry.snippet = snippet; } } } @@ -236,13 +240,126 @@ const DIM = '\x1b[2m'; const BOLD = '\x1b[1m'; const RESET = '\x1b[0m'; +// --------------------------------------------------------------------------- +// Category → meta tag mapping (mirrors generator's CATEGORY_TO_META) +// --------------------------------------------------------------------------- + +const CATEGORY_TO_META: Record = { + 'Comparison Query Operators': 'META_QUERY_COMPARISON', + 'Logical Query Operators': 'META_QUERY_LOGICAL', + 'Element Query Operators': 'META_QUERY_ELEMENT', + 'Evaluation Query Operators': 'META_QUERY_EVALUATION', + 'Geospatial Operators': 'META_QUERY_GEOSPATIAL', + 'Array Query Operators': 'META_QUERY_ARRAY', + 'Bitwise Query Operators': 'META_QUERY_BITWISE', + 'Projection Operators': 'META_QUERY_PROJECTION', + 'Miscellaneous Query Operators': 'META_QUERY_MISC', + 'Field Update Operators': 'META_UPDATE_FIELD', + 'Array Update Operators': 'META_UPDATE_ARRAY', + 'Bitwise Update Operators': 'META_UPDATE_BITWISE', + 'Arithmetic Expression Operators': 'META_EXPR_ARITH', + 'Array Expression Operators': 'META_EXPR_ARRAY', + 'Bitwise Operators': 'META_EXPR_BITWISE', + 'Boolean Expression Operators': 'META_EXPR_BOOL', + 'Comparison Expression Operators': 'META_EXPR_COMPARISON', + 'Data Size Operators': 'META_EXPR_DATASIZE', + 'Date Expression Operators': 'META_EXPR_DATE', + 'Literal Expression Operator': 'META_EXPR_LITERAL', + 'Miscellaneous Operators': 'META_EXPR_MISC', + 'Object Expression Operators': 'META_EXPR_OBJECT', + 'Set Expression Operators': 'META_EXPR_SET', + 'String Expression Operators': 'META_EXPR_STRING', + 'Timestamp Expression Operators': 'META_EXPR_TIMESTAMP', + 'Trigonometry Expression Operators': 'META_EXPR_TRIG', + 'Type Expression Operators': 'META_EXPR_TYPE', + 'Accumulators ($group, $bucket, $bucketAuto, $setWindowFields)': 'META_ACCUMULATOR', + 'Accumulators (in Other Stages)': 'META_ACCUMULATOR', + Accumulators: 'META_ACCUMULATOR', + 'Variable Expression Operators': 'META_EXPR_VARIABLE', + 'Window Operators': 'META_WINDOW', + 'Conditional Expression Operators': 'META_EXPR_CONDITIONAL', + 'Aggregation Pipeline Stages': 'META_STAGE', + 'Variables in Aggregation Expressions': 'META_VARIABLE', +}; + +// --------------------------------------------------------------------------- +// Snippet file parser +// --------------------------------------------------------------------------- + +function parseSnippetsFile(content: string): Map> { + const lines = content.split('\n'); + const result = new Map>(); + + let currentMeta = ''; + let currentOp = ''; + let inCodeBlock = false; + + for (const line of lines) { + if (line.startsWith('```')) { + inCodeBlock = !inCodeBlock; + continue; + } + if (inCodeBlock) continue; + + const h2 = line.match(/^## (.+)$/); + if (h2) { + const cat = h2[1].trim(); + const meta = CATEGORY_TO_META[cat]; + if (meta) { + currentMeta = meta; + if (!result.has(currentMeta)) { + result.set(currentMeta, new Map()); + } + } else { + currentMeta = ''; + } + currentOp = ''; + continue; + } + + const h3 = line.match(/^### (.+)$/); + if (h3 && currentMeta) { + currentOp = h3[1].trim(); + continue; + } + + if (currentMeta && currentOp && line.startsWith('- **Snippet:**')) { + let snippet = line.replace('- **Snippet:**', '').trim(); + if (snippet.startsWith('`') && snippet.endsWith('`')) { + snippet = snippet.slice(1, -1); + } + if (snippet) { + result.get(currentMeta)!.set(currentOp, snippet); + } + continue; + } + } + + return result; +} + +function operatorHasSnippet( + snippets: Map>, + meta: string, + operatorValue: string, + overrideSnippet: string | undefined, +): boolean { + if (overrideSnippet) return true; + const catSnippets = snippets.get(meta); + if (!catSnippets) return false; + if (catSnippets.has(operatorValue)) return true; + if (catSnippets.has('DEFAULT')) return true; + return false; +} + // --------------------------------------------------------------------------- // Main // --------------------------------------------------------------------------- function main(): void { - const dumpPath = path.join(__dirname, '..', 'resources', 'operator-reference-scraped.md'); - const overridePath = path.join(__dirname, '..', 'resources', 'operator-reference-overrides.md'); + const dumpPath = path.join(__dirname, '..', 'resources', 'scraped', 'operator-reference.md'); + const overridePath = path.join(__dirname, '..', 'resources', 'overrides', 'operator-overrides.md'); + const snippetsPath = path.join(__dirname, '..', 'resources', 'overrides', 'operator-snippets.md'); if (!fs.existsSync(dumpPath)) { console.error(`❌ Scraped dump not found: ${dumpPath}`); @@ -361,7 +478,49 @@ function main(): void { } // ----------------------------------------------------------------------- - // Section 4: Summary + // Section 4: Snippet coverage + // ----------------------------------------------------------------------- + let snippets = new Map>(); + if (fs.existsSync(snippetsPath)) { + const snippetsContent = fs.readFileSync(snippetsPath, 'utf-8'); + snippets = parseSnippetsFile(snippetsContent); + } + + const withSnippet: ParsedEntry[] = []; + const withoutSnippet: ParsedEntry[] = []; + + for (const entry of dumpEntries) { + const meta = CATEGORY_TO_META[entry.category]; + if (!meta) { + withoutSnippet.push(entry); + continue; + } + const match = findOverride(overrides, entry.value, entry.category, dumpCategories); + const overrideSnippet = match?.override.snippet; + if (operatorHasSnippet(snippets, meta, entry.value, overrideSnippet)) { + withSnippet.push(entry); + } else { + withoutSnippet.push(entry); + } + } + + console.log(`${BOLD}${CYAN}═══ SNIPPET COVERAGE (${withSnippet.length}/${dumpEntries.length}) ═══${RESET}`); + if (withoutSnippet.length === 0) { + console.log(` ${GREEN}✅ All operators have snippet templates.${RESET}\n`); + } else { + console.log(` ${DIM}Operators without snippet templates (by category):${RESET}\n`); + const byCategory = groupByCategory(withoutSnippet); + for (const [cat, ops] of byCategory) { + console.log(` ${CYAN}${cat}${RESET}`); + for (const op of ops) { + console.log(` ${DIM}—${RESET} ${op.value}`); + } + } + console.log(''); + } + + // ----------------------------------------------------------------------- + // Section 5: Summary // ----------------------------------------------------------------------- console.log(`${BOLD}═══ SUMMARY ═══${RESET}`); console.log(` Total scraped operators: ${dumpEntries.length}`); @@ -370,7 +529,10 @@ function main(): void { console.log(` Potentially redundant: ${YELLOW}${redundantOverrides.length}${RESET}`); console.log(` ${RED}Gaps remaining:${RESET} ${gaps.length}`); console.log(` Total overrides in file: ${totalOverrideCount}`); - console.log(` Coverage: ${((1 - gaps.length / dumpEntries.length) * 100).toFixed(1)}%`); + console.log(` With snippet template: ${withSnippet.length}`); + console.log(` Without snippet: ${withoutSnippet.length}`); + console.log(` Description coverage: ${((1 - gaps.length / dumpEntries.length) * 100).toFixed(1)}%`); + console.log(` Snippet coverage: ${((withSnippet.length / dumpEntries.length) * 100).toFixed(1)}%`); } // --------------------------------------------------------------------------- diff --git a/packages/documentdb-constants/scripts/generate-from-reference.ts b/packages/documentdb-constants/scripts/generate-from-reference.ts index 77abe29d0..5afe45201 100644 --- a/packages/documentdb-constants/scripts/generate-from-reference.ts +++ b/packages/documentdb-constants/scripts/generate-from-reference.ts @@ -7,8 +7,9 @@ * Generates TypeScript operator data files from the scraped reference dump. * * Reads: - * resources/operator-reference-scraped.md — scraped operator data (primary) - * resources/operator-reference-overrides.md — hand-written overrides (wins) + * resources/scraped/operator-reference.md — scraped operator data (primary) + * resources/overrides/operator-overrides.md — hand-written overrides (wins) + * resources/overrides/operator-snippets.md — snippet templates per category * * Writes: * src/queryOperators.ts, src/updateOperators.ts, src/expressionOperators.ts, @@ -19,9 +20,16 @@ * specified in an override entry replaces the corresponding scraped value. * Omitted fields keep their scraped values. * + * Snippets are resolved in order: + * 1. Snippet override from operator-overrides.md (highest priority) + * 2. Per-operator snippet from operator-snippets.md + * 3. DEFAULT snippet from operator-snippets.md ({{VALUE}} → operator name) + * 4. No snippet + * * Usage: npm run generate * Note: This script overwrites the generated src/ files. Do NOT edit - * those files by hand — put corrections in the overrides file instead. + * those files by hand — put corrections in the overrides/snippets + * files instead. */ import * as fs from 'fs'; @@ -85,6 +93,7 @@ const CATEGORY_TO_META: Record = { 'Type Expression Operators': 'META_EXPR_TYPE', 'Accumulators ($group, $bucket, $bucketAuto, $setWindowFields)': 'META_ACCUMULATOR', 'Accumulators (in Other Stages)': 'META_ACCUMULATOR', + Accumulators: 'META_ACCUMULATOR', 'Variable Expression Operators': 'META_EXPR_VARIABLE', 'Window Operators': 'META_WINDOW', 'Conditional Expression Operators': 'META_EXPR_CONDITIONAL', @@ -316,7 +325,11 @@ function parseOverrides(content: string): Map currentOp.entry.docLink = line.replace('- **Doc Link:**', '').trim(); } if (currentOp && line.startsWith('- **Snippet:**')) { - currentOp.entry.snippet = line.replace('- **Snippet:**', '').trim(); + let snippet = line.replace('- **Snippet:**', '').trim(); + if (snippet.startsWith('`') && snippet.endsWith('`')) { + snippet = snippet.slice(1, -1); + } + currentOp.entry.snippet = snippet; } } @@ -398,407 +411,96 @@ function mergeOverride(op: ParsedOperator, override: OverrideEntry): void { } // --------------------------------------------------------------------------- -// Snippet generation +// Snippet loading (from resources/overrides/operator-snippets.md) // --------------------------------------------------------------------------- -function generateSnippet(op: ParsedOperator, meta: string): string | undefined { - const v = op.value; - - // System variables don't need snippets - if (meta === 'META_VARIABLE') return undefined; +/** + * Parses the operator-snippets.md file into a map of meta-tag → (operator|DEFAULT → snippet). + * Uses the same heading conventions as the dump/overrides parsers. + */ +function parseSnippets(content: string): Map> { + const lines = content.split('\n'); + const result = new Map>(); - // Stages: wrap in { $stage: { ... } } - if (meta === 'META_STAGE') { - return getStageSinppet(v); - } + let currentMeta = ''; + let currentOp = ''; + let inCodeBlock = false; - // Query comparison operators: { $op: value } - if (meta === 'META_QUERY_COMPARISON') { - if (v === '$in' || v === '$nin') { - return `{ ${v}: [\${1:value}] }`; + for (const line of lines) { + if (line.startsWith('```')) { + inCodeBlock = !inCodeBlock; + continue; } - return `{ ${v}: \${1:value} }`; - } + if (inCodeBlock) continue; - // Logical query operators - if (meta === 'META_QUERY_LOGICAL') { - if (v === '$not') { - return `{ ${v}: { \${1:expression} } }`; + // H2 = category + const h2 = line.match(/^## (.+)$/); + if (h2) { + const cat = h2[1].trim(); + const meta = CATEGORY_TO_META[cat]; + if (meta) { + currentMeta = meta; + if (!result.has(currentMeta)) { + result.set(currentMeta, new Map()); + } + } else { + currentMeta = ''; + console.warn(`⚠️ Unknown snippet category: "${cat}"`); + } + currentOp = ''; + continue; } - return `{ ${v}: [{ \${1:expression} }] }`; - } - - // Element query operators - if (meta === 'META_QUERY_ELEMENT') { - if (v === '$exists') return `{ ${v}: \${1:true} }`; - if (v === '$type') return `{ ${v}: "\${1:type}" }`; - return undefined; - } - - // Evaluation query operators - if (meta === 'META_QUERY_EVALUATION') { - if (v === '$expr') return `{ ${v}: { \${1:expression} } }`; - if (v === '$regex') return `{ ${v}: /\${1:pattern}/ }`; - if (v === '$mod') return `{ ${v}: [\${1:divisor}, \${2:remainder}] }`; - if (v === '$text') return `{ ${v}: { \\$search: "\${1:text}" } }`; - if (v === '$jsonSchema') return `{ ${v}: { bsonType: "\${1:object}" } }`; - return undefined; - } - // Array query operators - if (meta === 'META_QUERY_ARRAY') { - if (v === '$all') return `{ ${v}: [\${1:value}] }`; - if (v === '$elemMatch') return `{ ${v}: { \${1:query} } }`; - if (v === '$size') return `{ ${v}: \${1:number} }`; - return undefined; - } - - // Bitwise query operators - if (meta === 'META_QUERY_BITWISE') { - return `{ ${v}: \${1:bitmask} }`; - } - - // Geospatial operators - if (meta === 'META_QUERY_GEOSPATIAL') { - if (v === '$near' || v === '$nearSphere') { - return `{ ${v}: { \\$geometry: { type: "Point", coordinates: [\${1:lng}, \${2:lat}] }, \\$maxDistance: \${3:distance} } }`; - } - if (v === '$geoIntersects' || v === '$geoWithin') { - return `{ ${v}: { \\$geometry: { type: "\${1:GeoJSON type}", coordinates: \${2:coordinates} } } }`; + // H3 = operator name or DEFAULT + const h3 = line.match(/^### (.+)$/); + if (h3 && currentMeta) { + currentOp = h3[1].trim(); + continue; } - if (v === '$box') return `[[\${1:bottomLeftX}, \${2:bottomLeftY}], [\${3:upperRightX}, \${4:upperRightY}]]`; - if (v === '$center') return `[[\${1:x}, \${2:y}], \${3:radius}]`; - if (v === '$centerSphere') return `[[\${1:x}, \${2:y}], \${3:radiusInRadians}]`; - if (v === '$geometry') return `{ type: "\${1:Point}", coordinates: [\${2:coordinates}] }`; - if (v === '$maxDistance' || v === '$minDistance') return `\${1:distance}`; - if (v === '$polygon') return `[[\${1:x1}, \${2:y1}], [\${3:x2}, \${4:y2}], [\${5:x3}, \${6:y3}]]`; - return undefined; - } - - // Projection operators - if (meta === 'META_QUERY_PROJECTION') { - if (v === '$') return undefined; // Positional, no snippet - if (v === '$elemMatch') return `{ ${v}: { \${1:query} } }`; - if (v === '$slice') return `{ ${v}: \${1:number} }`; - return undefined; - } - - // Misc query operators - if (meta === 'META_QUERY_MISC') { - if (v === '$comment') return `{ ${v}: "\${1:comment}" }`; - if (v === '$rand') return `{ ${v}: {} }`; - if (v === '$natural') return `{ ${v}: \${1:1} }`; - return undefined; - } - - // Update field operators - if (meta === 'META_UPDATE_FIELD') { - if (v === '$rename') return `{ ${v}: { "\${1:oldField}": "\${2:newField}" } }`; - if (v === '$currentDate') return `{ ${v}: { "\${1:field}": true } }`; - return `{ ${v}: { "\${1:field}": \${2:value} } }`; - } - - // Update array operators - if (meta === 'META_UPDATE_ARRAY') { - if (v === '$' || v === '$[]' || v === '$[identifier]') return undefined; // Positional, no snippet - if (v === '$addToSet') return `{ ${v}: { "\${1:field}": \${2:value} } }`; - if (v === '$pop') return `{ ${v}: { "\${1:field}": \${2:1} } }`; - if (v === '$pull') return `{ ${v}: { "\${1:field}": \${2:condition} } }`; - if (v === '$push') return `{ ${v}: { "\${1:field}": \${2:value} } }`; - if (v === '$pullAll') return `{ ${v}: { "\${1:field}": [\${2:values}] } }`; - if (v === '$each') return `{ ${v}: [\${1:values}] }`; - if (v === '$position') return `{ ${v}: \${1:index} }`; - if (v === '$slice') return `{ ${v}: \${1:number} }`; - if (v === '$sort') return `{ ${v}: { "\${1:field}": \${2:1} } }`; - return undefined; - } - - // Bitwise update operator - if (meta === 'META_UPDATE_BITWISE') { - return `{ ${v}: { "\${1:field}": { "\${2:and|or|xor}": \${3:value} } } }`; - } - - // Accumulators - if (meta === 'META_ACCUMULATOR') { - if (v === '$push' || v === '$addToSet') return `{ ${v}: "\${1:\\$field}" }`; - if (v === '$mergeObjects') return `{ ${v}: "\${1:\\$field}" }`; - if (v === '$count') return `{ ${v}: {} }`; - if (v === '$bottom' || v === '$top') - return `{ ${v}: { sortBy: { \${1:field}: \${2:1} }, output: "\${3:\\$field}" } }`; - if (v === '$bottomN' || v === '$topN') - return `{ ${v}: { n: \${1:number}, sortBy: { \${2:field}: \${3:1} }, output: "\${4:\\$field}" } }`; - if (v === '$firstN' || v === '$lastN' || v === '$maxN' || v === '$minN') - return `{ ${v}: { input: "\${1:\\$field}", n: \${2:number} } }`; - if (v === '$percentile') return `{ ${v}: { input: "\${1:\\$field}", p: [\${2:0.5}], method: "approximate" } }`; - if (v === '$median') return `{ ${v}: { input: "\${1:\\$field}", method: "approximate" } }`; - if (v === '$stdDevPop' || v === '$stdDevSamp') return `{ ${v}: "\${1:\\$field}" }`; - return `{ ${v}: "\${1:\\$field}" }`; - } - - // Window operators - if (meta === 'META_WINDOW') { - if (v === '$shift') return `{ ${v}: { output: "\${1:\\$field}", by: \${2:1}, default: \${3:null} } }`; - if (v === '$rank' || v === '$denseRank' || v === '$documentNumber') return `{ ${v}: {} }`; - if (v === '$linearFill' || v === '$locf') return `{ ${v}: "\${1:\\$field}" }`; - if (v === '$expMovingAvg') return `{ ${v}: { input: "\${1:\\$field}", N: \${2:number} } }`; - if (v === '$derivative' || v === '$integral') - return `{ ${v}: { input: "\${1:\\$field}", unit: "\${2:hour}" } }`; - // Window accumulators use accumulator-style snippets - return `{ ${v}: "\${1:\\$field}" }`; - } - - // Expression operators — general patterns - if (meta.startsWith('META_EXPR_')) { - return getExpressionSnippet(v, meta); - } - return undefined; -} - -function getExpressionSnippet(v: string, meta: string): string | undefined { - // Arithmetic - if (meta === 'META_EXPR_ARITH') { - if ( - v === '$abs' || - v === '$ceil' || - v === '$floor' || - v === '$exp' || - v === '$ln' || - v === '$log10' || - v === '$sqrt' || - v === '$trunc' - ) { - return `{ ${v}: "\${1:\\$field}" }`; - } - if (v === '$add' || v === '$subtract' || v === '$multiply' || v === '$divide' || v === '$mod' || v === '$pow') { - return `{ ${v}: ["\${1:\\$field1}", "\${2:\\$field2}"] }`; + // Snippet value (backticks are stripped if present: `...` → ...) + if (currentMeta && currentOp && line.startsWith('- **Snippet:**')) { + let snippet = line.replace('- **Snippet:**', '').trim(); + if (snippet.startsWith('`') && snippet.endsWith('`')) { + snippet = snippet.slice(1, -1); + } + if (snippet) { + result.get(currentMeta)!.set(currentOp, snippet); + } + continue; } - if (v === '$log') return `{ ${v}: ["\${1:\\$number}", \${2:base}] }`; - if (v === '$round') return `{ ${v}: ["\${1:\\$field}", \${2:place}] }`; - return `{ ${v}: "\${1:\\$field}" }`; - } - - // Array expressions - if (meta === 'META_EXPR_ARRAY') { - if (v === '$arrayElemAt') return `{ ${v}: ["\${1:\\$array}", \${2:index}] }`; - if (v === '$arrayToObject') return `{ ${v}: "\${1:\\$array}" }`; - if (v === '$concatArrays') return `{ ${v}: ["\${1:\\$array1}", "\${2:\\$array2}"] }`; - if (v === '$filter') - return `{ ${v}: { input: "\${1:\\$array}", as: "\${2:item}", cond: { \${3:expression} } } }`; - if (v === '$first' || v === '$last') return `{ ${v}: "\${1:\\$array}" }`; - if (v === '$in') return `{ ${v}: ["\${1:\\$field}", "\${2:\\$array}"] }`; - if (v === '$indexOfArray') return `{ ${v}: ["\${1:\\$array}", "\${2:value}"] }`; - if (v === '$isArray') return `{ ${v}: "\${1:\\$field}" }`; - if (v === '$map') return `{ ${v}: { input: "\${1:\\$array}", as: "\${2:item}", in: { \${3:expression} } } }`; - if (v === '$objectToArray') return `{ ${v}: "\${1:\\$object}" }`; - if (v === '$range') return `{ ${v}: [\${1:start}, \${2:end}, \${3:step}] }`; - if (v === '$reduce') - return `{ ${v}: { input: "\${1:\\$array}", initialValue: \${2:0}, in: { \${3:expression} } } }`; - if (v === '$reverseArray') return `{ ${v}: "\${1:\\$array}" }`; - if (v === '$size') return `{ ${v}: "\${1:\\$array}" }`; - if (v === '$slice') return `{ ${v}: ["\${1:\\$array}", \${2:n}] }`; - if (v === '$sortArray') return `{ ${v}: { input: "\${1:\\$array}", sortBy: { \${2:field}: \${3:1} } } }`; - if (v === '$zip') return `{ ${v}: { inputs: ["\${1:\\$array1}", "\${2:\\$array2}"] } }`; - if (v === '$maxN' || v === '$minN' || v === '$firstN' || v === '$lastN') - return `{ ${v}: { input: "\${1:\\$array}", n: \${2:number} } }`; - return `{ ${v}: "\${1:\\$array}" }`; - } - - // Boolean expressions - if (meta === 'META_EXPR_BOOL') { - if (v === '$not') return `{ ${v}: ["\${1:expression}"] }`; - return `{ ${v}: ["\${1:expression1}", "\${2:expression2}"] }`; - } - - // Comparison expressions - if (meta === 'META_EXPR_COMPARISON') { - return `{ ${v}: ["\${1:\\$field1}", "\${2:\\$field2}"] }`; - } - - // Conditional expressions - if (meta === 'META_EXPR_CONDITIONAL') { - if (v === '$cond') - return `{ ${v}: { if: { \${1:expression} }, then: \${2:trueValue}, else: \${3:falseValue} } }`; - if (v === '$ifNull') return `{ ${v}: ["\${1:\\$field}", \${2:replacement}] }`; - if (v === '$switch') - return `{ ${v}: { branches: [{ case: { \${1:expression} }, then: \${2:value} }], default: \${3:defaultValue} } }`; - return undefined; - } - - // Date expressions - if (meta === 'META_EXPR_DATE') { - if (v === '$dateAdd' || v === '$dateSubtract') - return `{ ${v}: { startDate: "\${1:\\$dateField}", unit: "\${2:day}", amount: \${3:1} } }`; - if (v === '$dateDiff') - return `{ ${v}: { startDate: "\${1:\\$startDate}", endDate: "\${2:\\$endDate}", unit: "\${3:day}" } }`; - if (v === '$dateFromParts') return `{ ${v}: { year: \${1:2024}, month: \${2:1}, day: \${3:1} } }`; - if (v === '$dateToParts') return `{ ${v}: { date: "\${1:\\$dateField}" } }`; - if (v === '$dateFromString') return `{ ${v}: { dateString: "\${1:dateString}" } }`; - if (v === '$dateToString') return `{ ${v}: { format: "\${1:%Y-%m-%d}", date: "\${2:\\$dateField}" } }`; - if (v === '$dateTrunc') return `{ ${v}: { date: "\${1:\\$dateField}", unit: "\${2:day}" } }`; - if (v === '$toDate') return `{ ${v}: "\${1:\\$field}" }`; - // Date part extractors: $year, $month, $dayOfMonth, etc. - return `{ ${v}: "\${1:\\$dateField}" }`; - } - - // Object expressions - if (meta === 'META_EXPR_OBJECT') { - if (v === '$mergeObjects') return `{ ${v}: ["\${1:\\$object1}", "\${2:\\$object2}"] }`; - if (v === '$objectToArray') return `{ ${v}: "\${1:\\$object}" }`; - if (v === '$setField') - return `{ ${v}: { field: "\${1:fieldName}", input: "\${2:\\$object}", value: \${3:value} } }`; - return `{ ${v}: "\${1:\\$object}" }`; - } - - // Set expressions - if (meta === 'META_EXPR_SET') { - if (v === '$setIsSubset') return `{ ${v}: ["\${1:\\$set1}", "\${2:\\$set2}"] }`; - if (v === '$anyElementTrue' || v === '$allElementsTrue') return `{ ${v}: ["\${1:\\$array}"] }`; - return `{ ${v}: ["\${1:\\$set1}", "\${2:\\$set2}"] }`; - } - - // String expressions - if (meta === 'META_EXPR_STRING') { - if (v === '$concat') return `{ ${v}: ["\${1:\\$string1}", "\${2:\\$string2}"] }`; - if (v === '$indexOfBytes' || v === '$indexOfCP') return `{ ${v}: ["\${1:\\$string}", "\${2:substring}"] }`; - if (v === '$regexFind' || v === '$regexFindAll' || v === '$regexMatch') - return `{ ${v}: { input: "\${1:\\$string}", regex: "\${2:pattern}" } }`; - if (v === '$replaceOne' || v === '$replaceAll') - return `{ ${v}: { input: "\${1:\\$string}", find: "\${2:find}", replacement: "\${3:replacement}" } }`; - if (v === '$split') return `{ ${v}: ["\${1:\\$string}", "\${2:delimiter}"] }`; - if (v === '$substr' || v === '$substrBytes' || v === '$substrCP') - return `{ ${v}: ["\${1:\\$string}", \${2:start}, \${3:length}] }`; - if (v === '$strcasecmp') return `{ ${v}: ["\${1:\\$string1}", "\${2:\\$string2}"] }`; - if (v === '$trim' || v === '$ltrim' || v === '$rtrim') return `{ ${v}: { input: "\${1:\\$string}" } }`; - return `{ ${v}: "\${1:\\$string}" }`; - } - - // Trig expressions - if (meta === 'META_EXPR_TRIG') { - if (v === '$degreesToRadians' || v === '$radiansToDegrees') return `{ ${v}: "\${1:\\$angle}" }`; - return `{ ${v}: "\${1:\\$value}" }`; } - // Type expressions - if (meta === 'META_EXPR_TYPE') { - if (v === '$convert') return `{ ${v}: { input: "\${1:\\$field}", to: "\${2:type}" } }`; - if (v === '$type') return `{ ${v}: "\${1:\\$field}" }`; - return `{ ${v}: "\${1:\\$field}" }`; - } - - // Data size - if (meta === 'META_EXPR_DATASIZE') { - return `{ ${v}: "\${1:\\$field}" }`; - } - - // Timestamp - if (meta === 'META_EXPR_TIMESTAMP') { - return `{ ${v}: "\${1:\\$timestampField}" }`; - } - - // Bitwise expressions - if (meta === 'META_EXPR_BITWISE') { - if (v === '$bitNot') return `{ ${v}: "\${1:\\$field}" }`; - return `{ ${v}: [\${1:value1}, \${2:value2}] }`; - } - - // Literal - if (meta === 'META_EXPR_LITERAL') { - return `{ ${v}: \${1:value} }`; - } - - // Misc expressions - if (meta === 'META_EXPR_MISC') { - if (v === '$getField') return `{ ${v}: { field: "\${1:fieldName}", input: "\${2:\\$object}" } }`; - if (v === '$rand') return `{ ${v}: {} }`; - if (v === '$sampleRate') return `{ ${v}: \${1:0.5} }`; - return `{ ${v}: \${1:value} }`; - } + return result; +} - // Variable expression - if (meta === 'META_EXPR_VARIABLE') { - if (v === '$let') return `{ ${v}: { vars: { \${1:var}: \${2:expression} }, in: \${3:expression} } }`; - return undefined; - } +/** + * Looks up a snippet for an operator from the parsed snippets map. + * + * Resolution order: + * 1. Exact operator match in the category + * 2. DEFAULT entry in the category (with {{VALUE}} replaced by operator name) + * 3. undefined (no snippet) + */ +function lookupSnippet( + snippets: Map>, + meta: string, + operatorValue: string, +): string | undefined { + const catSnippets = snippets.get(meta); + if (!catSnippets) return undefined; + + // Exact operator match + const exact = catSnippets.get(operatorValue); + if (exact !== undefined) return exact; + + // Fall back to category DEFAULT + const def = catSnippets.get('DEFAULT'); + if (def) return def.replace(/\{\{VALUE\}\}/g, operatorValue); return undefined; } -function getStageSinppet(v: string): string | undefined { - switch (v) { - case '$match': - return `{ ${v}: { \${1:query} } }`; - case '$group': - return `{ ${v}: { _id: "\${1:\\$field}", \${2:accumulator}: { \${3:\\$sum}: 1 } } }`; - case '$project': - return `{ ${v}: { \${1:field}: 1 } }`; - case '$sort': - return `{ ${v}: { \${1:field}: \${2:1} } }`; - case '$limit': - return `{ ${v}: \${1:number} }`; - case '$skip': - return `{ ${v}: \${1:number} }`; - case '$unwind': - return `{ ${v}: "\${1:\\$arrayField}" }`; - case '$lookup': - return `{ ${v}: { from: "\${1:collection}", localField: "\${2:field}", foreignField: "\${3:field}", as: "\${4:result}" } }`; - case '$addFields': - return `{ ${v}: { \${1:newField}: \${2:expression} } }`; - case '$set': - return `{ ${v}: { \${1:field}: \${2:expression} } }`; - case '$unset': - return `{ ${v}: "\${1:field}" }`; - case '$replaceRoot': - return `{ ${v}: { newRoot: "\${1:\\$field}" } }`; - case '$replaceWith': - return `{ ${v}: "\${1:\\$field}" }`; - case '$count': - return `{ ${v}: "\${1:countField}" }`; - case '$out': - return `{ ${v}: "\${1:collection}" }`; - case '$merge': - return `{ ${v}: { into: "\${1:collection}" } }`; - case '$bucket': - return `{ ${v}: { groupBy: "\${1:\\$field}", boundaries: [\${2:values}], default: "\${3:Other}" } }`; - case '$bucketAuto': - return `{ ${v}: { groupBy: "\${1:\\$field}", buckets: \${2:number} } }`; - case '$facet': - return `{ ${v}: { \${1:outputField}: [{ \${2:stage} }] } }`; - case '$graphLookup': - return `{ ${v}: { from: "\${1:collection}", startWith: "\${2:\\$field}", connectFromField: "\${3:field}", connectToField: "\${4:field}", as: "\${5:result}" } }`; - case '$sample': - return `{ ${v}: { size: \${1:number} } }`; - case '$sortByCount': - return `{ ${v}: "\${1:\\$field}" }`; - case '$redact': - return `{ ${v}: { \\$cond: { if: { \${1:expression} }, then: "\${2:\\$\\$DESCEND}", else: "\${3:\\$\\$PRUNE}" } } }`; - case '$unionWith': - return `{ ${v}: { coll: "\${1:collection}", pipeline: [\${2}] } }`; - case '$setWindowFields': - return `{ ${v}: { partitionBy: "\${1:\\$field}", sortBy: { \${2:field}: \${3:1} }, output: { \${4:newField}: { \${5:windowFunc} } } } }`; - case '$densify': - return `{ ${v}: { field: "\${1:field}", range: { step: \${2:1}, bounds: "full" } } }`; - case '$fill': - return `{ ${v}: { output: { \${1:field}: { method: "\${2:linear}" } } } }`; - case '$documents': - return `{ ${v}: [\${1:documents}] }`; - case '$changeStream': - return `{ ${v}: {} }`; - case '$collStats': - return `{ ${v}: { storageStats: {} } }`; - case '$currentOp': - return `{ ${v}: { allUsers: true } }`; - case '$indexStats': - return `{ ${v}: {} }`; - case '$listLocalSessions': - return `{ ${v}: { allUsers: true } }`; - case '$geoNear': - return `{ ${v}: { near: { type: "Point", coordinates: [\${1:lng}, \${2:lat}] }, distanceField: "\${3:distance}" } }`; - default: - return `{ ${v}: { \${1} } }`; - } -} - // --------------------------------------------------------------------------- // BSON type applicability // --------------------------------------------------------------------------- @@ -823,7 +525,7 @@ function getApplicableBsonTypes(op: ParsedOperator, meta: string): string[] | un // File generation // --------------------------------------------------------------------------- -function generateFileContent(specs: FileSpec[]): string { +function generateFileContent(specs: FileSpec[], snippets: Map>): string { const copyright = `/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. @@ -832,10 +534,11 @@ function generateFileContent(specs: FileSpec[]): string { // AUTO-GENERATED — DO NOT EDIT BY HAND // // Generated by: npm run generate (scripts/generate-from-reference.ts) -// Sources: resources/operator-reference-scraped.md -// resources/operator-reference-overrides.md +// Sources: resources/scraped/operator-reference.md +// resources/overrides/operator-overrides.md +// resources/overrides/operator-snippets.md // -// To change operator data, edit the overrides file and re-run the generator. +// To change operator data, edit the overrides/snippets files and re-run the generator. `; // Collect all unique meta imports @@ -849,7 +552,7 @@ function generateFileContent(specs: FileSpec[]): string { // Pre-generate all sections so we can detect whether getDocLink is used const sections: string[] = []; for (const spec of specs) { - sections.push(generateSection(spec)); + sections.push(generateSection(spec, snippets)); } const sectionsStr = sections.join('\n'); @@ -876,7 +579,7 @@ import { registerOperators } from './getFilteredCompletions'; return content; } -function generateSection(spec: FileSpec): string { +function generateSection(spec: FileSpec, snippets: Map>): string { let section = `// ---------------------------------------------------------------------------\n`; section += `// ${spec.operators[0]?.category || spec.variableName}\n`; section += `// ---------------------------------------------------------------------------\n\n`; @@ -887,7 +590,7 @@ function generateSection(spec: FileSpec): string { const metaStringValue = META_CONST_TO_VALUE[spec.metaImport] || ''; for (const op of spec.operators) { - const snippet = op.snippetOverride || generateSnippet(op, spec.metaImport); + const snippet = op.snippetOverride || lookupSnippet(snippets, spec.metaImport, op.value); const bsonTypes = getApplicableBsonTypes(op, spec.metaImport); // Determine the correct link emission strategy: @@ -1013,8 +716,9 @@ function categoryToVarName(category: string): string { // --------------------------------------------------------------------------- function main(): void { - const dumpPath = path.join(__dirname, '..', 'resources', 'operator-reference-scraped.md'); - const overridePath = path.join(__dirname, '..', 'resources', 'operator-reference-overrides.md'); + const dumpPath = path.join(__dirname, '..', 'resources', 'scraped', 'operator-reference.md'); + const overridePath = path.join(__dirname, '..', 'resources', 'overrides', 'operator-overrides.md'); + const snippetsPath = path.join(__dirname, '..', 'resources', 'overrides', 'operator-snippets.md'); const srcDir = path.join(__dirname, '..', 'src'); console.log('📖 Reading operator reference dump...'); @@ -1041,6 +745,21 @@ function main(): void { console.log('ℹ️ No overrides file found, skipping.\n'); } + // Load snippet templates + let snippetsMap = new Map>(); + if (fs.existsSync(snippetsPath)) { + console.log('📋 Reading snippet templates...'); + const snippetsContent = fs.readFileSync(snippetsPath, 'utf-8'); + snippetsMap = parseSnippets(snippetsContent); + let snippetCount = 0; + for (const [, catMap] of snippetsMap) { + snippetCount += catMap.size; + } + console.log(` Loaded ${snippetCount} snippet entries across ${snippetsMap.size} categories\n`); + } else { + console.log('ℹ️ No snippets file found, skipping.\n'); + } + console.log('📁 Building file specs...'); const fileGroups = buildFileSpecs(categorizedOps); @@ -1049,7 +768,7 @@ function main(): void { console.log( `✍️ Generating ${fileName}.ts (${specs.reduce((n, s) => n + s.operators.length, 0)} operators)...`, ); - const fileContent = generateFileContent(specs); + const fileContent = generateFileContent(specs, snippetsMap); fs.writeFileSync(filePath, fileContent, 'utf-8'); } diff --git a/packages/documentdb-constants/scripts/scrape-operator-docs.ts b/packages/documentdb-constants/scripts/scrape-operator-docs.ts index 4fab8cf2b..d51c3bc01 100644 --- a/packages/documentdb-constants/scripts/scrape-operator-docs.ts +++ b/packages/documentdb-constants/scripts/scrape-operator-docs.ts @@ -7,7 +7,7 @@ * scrape-operator-docs.ts * * Scrapes the DocumentDB compatibility page and per-operator documentation - * to generate the resources/operator-reference-scraped.md dump file. + * to generate the resources/scraped/operator-reference.md dump file. * * Usage: * npx ts-node packages/documentdb-constants/scripts/scrape-operator-docs.ts @@ -919,15 +919,15 @@ async function main(): Promise { console.log(''); // Phase 3: Generate dump - console.log(' Phase 3: Generating operator-reference-scraped.md...'); + console.log(' Phase 3: Generating scraped/operator-reference.md...'); const dump = generateDump(operators); - const outputDir = path.join(__dirname, '..', 'resources'); + const outputDir = path.join(__dirname, '..', 'resources', 'scraped'); if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); } - const outputPath = path.join(outputDir, 'operator-reference-scraped.md'); + const outputPath = path.join(outputDir, 'operator-reference.md'); fs.writeFileSync(outputPath, dump, 'utf-8'); console.log(` Written to: ${outputPath}`); diff --git a/packages/documentdb-constants/src/accumulators.ts b/packages/documentdb-constants/src/accumulators.ts index bce98554b..3f0f7120c 100644 --- a/packages/documentdb-constants/src/accumulators.ts +++ b/packages/documentdb-constants/src/accumulators.ts @@ -6,10 +6,11 @@ // AUTO-GENERATED — DO NOT EDIT BY HAND // // Generated by: npm run generate (scripts/generate-from-reference.ts) -// Sources: resources/operator-reference-scraped.md -// resources/operator-reference-overrides.md +// Sources: resources/scraped/operator-reference.md +// resources/overrides/operator-overrides.md +// resources/overrides/operator-snippets.md // -// To change operator data, edit the overrides file and re-run the generator. +// To change operator data, edit the overrides/snippets files and re-run the generator. import { getDocLink } from './docLinks'; import { registerOperators } from './getFilteredCompletions'; diff --git a/packages/documentdb-constants/src/expressionOperators.ts b/packages/documentdb-constants/src/expressionOperators.ts index 7e705e8ae..3fed68c32 100644 --- a/packages/documentdb-constants/src/expressionOperators.ts +++ b/packages/documentdb-constants/src/expressionOperators.ts @@ -6,10 +6,11 @@ // AUTO-GENERATED — DO NOT EDIT BY HAND // // Generated by: npm run generate (scripts/generate-from-reference.ts) -// Sources: resources/operator-reference-scraped.md -// resources/operator-reference-overrides.md +// Sources: resources/scraped/operator-reference.md +// resources/overrides/operator-overrides.md +// resources/overrides/operator-snippets.md // -// To change operator data, edit the overrides file and re-run the generator. +// To change operator data, edit the overrides/snippets files and re-run the generator. import { getDocLink } from './docLinks'; import { registerOperators } from './getFilteredCompletions'; diff --git a/packages/documentdb-constants/src/operatorReference.test.ts b/packages/documentdb-constants/src/operatorReference.test.ts index 7f7de7521..4d4a8d853 100644 --- a/packages/documentdb-constants/src/operatorReference.test.ts +++ b/packages/documentdb-constants/src/operatorReference.test.ts @@ -7,7 +7,7 @@ * Dump-vs-implementation verification test. * * Ensures the TypeScript operator implementation always matches the - * resource dump (operator-reference-scraped.md). This test is the + * resource dump (scraped/operator-reference.md). This test is the * enforcing contract between "what does DocumentDB support?" (the dump) * and "what does our code provide?" (the implementation). * @@ -19,7 +19,7 @@ import * as path from 'path'; import { getAllCompletions } from './index'; import { parseOperatorReference, type ReferenceOperator } from './parseOperatorReference'; -const dumpPath = path.join(__dirname, '..', 'resources', 'operator-reference-scraped.md'); +const dumpPath = path.join(__dirname, '..', 'resources', 'scraped', 'operator-reference.md'); const dumpContent = fs.readFileSync(dumpPath, 'utf-8'); const parsed = parseOperatorReference(dumpContent); const referenceOperators = parsed.operators; @@ -174,7 +174,7 @@ describe('operator reference verification', () => { // - The override file is accidentally truncated // --------------------------------------------------------------------------- -const overridesPath = path.join(__dirname, '..', 'resources', 'operator-reference-overrides.md'); +const overridesPath = path.join(__dirname, '..', 'resources', 'overrides', 'operator-overrides.md'); const overridesContent = fs.readFileSync(overridesPath, 'utf-8'); const parsedOverrides = parseOperatorReference(overridesContent); const overrideOperators = parsedOverrides.operators; diff --git a/packages/documentdb-constants/src/parseOperatorReference.ts b/packages/documentdb-constants/src/parseOperatorReference.ts index 42c08ba33..cb94e784d 100644 --- a/packages/documentdb-constants/src/parseOperatorReference.ts +++ b/packages/documentdb-constants/src/parseOperatorReference.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ /** - * Parses the operator-reference-scraped.md dump file into structured data + * Parses the scraped/operator-reference.md dump file into structured data * for use in the operatorReference verification test. * * The dump format uses structured headings: @@ -54,7 +54,7 @@ export interface ParsedReference { } /** - * Parses the operator-reference-scraped.md content into structured data. + * Parses the scraped/operator-reference.md content into structured data. * * @param content - the full Markdown content of the dump file * @returns parsed reference data diff --git a/packages/documentdb-constants/src/queryOperators.ts b/packages/documentdb-constants/src/queryOperators.ts index 7c4dc095d..95998b22d 100644 --- a/packages/documentdb-constants/src/queryOperators.ts +++ b/packages/documentdb-constants/src/queryOperators.ts @@ -6,10 +6,11 @@ // AUTO-GENERATED — DO NOT EDIT BY HAND // // Generated by: npm run generate (scripts/generate-from-reference.ts) -// Sources: resources/operator-reference-scraped.md -// resources/operator-reference-overrides.md +// Sources: resources/scraped/operator-reference.md +// resources/overrides/operator-overrides.md +// resources/overrides/operator-snippets.md // -// To change operator data, edit the overrides file and re-run the generator. +// To change operator data, edit the overrides/snippets files and re-run the generator. import { getDocLink } from './docLinks'; import { registerOperators } from './getFilteredCompletions'; diff --git a/packages/documentdb-constants/src/stages.ts b/packages/documentdb-constants/src/stages.ts index 7fe267497..68c937726 100644 --- a/packages/documentdb-constants/src/stages.ts +++ b/packages/documentdb-constants/src/stages.ts @@ -6,10 +6,11 @@ // AUTO-GENERATED — DO NOT EDIT BY HAND // // Generated by: npm run generate (scripts/generate-from-reference.ts) -// Sources: resources/operator-reference-scraped.md -// resources/operator-reference-overrides.md +// Sources: resources/scraped/operator-reference.md +// resources/overrides/operator-overrides.md +// resources/overrides/operator-snippets.md // -// To change operator data, edit the overrides file and re-run the generator. +// To change operator data, edit the overrides/snippets files and re-run the generator. import { getDocLink } from './docLinks'; import { registerOperators } from './getFilteredCompletions'; diff --git a/packages/documentdb-constants/src/systemVariables.ts b/packages/documentdb-constants/src/systemVariables.ts index f8c3c932f..4a404f7bb 100644 --- a/packages/documentdb-constants/src/systemVariables.ts +++ b/packages/documentdb-constants/src/systemVariables.ts @@ -6,10 +6,11 @@ // AUTO-GENERATED — DO NOT EDIT BY HAND // // Generated by: npm run generate (scripts/generate-from-reference.ts) -// Sources: resources/operator-reference-scraped.md -// resources/operator-reference-overrides.md +// Sources: resources/scraped/operator-reference.md +// resources/overrides/operator-overrides.md +// resources/overrides/operator-snippets.md // -// To change operator data, edit the overrides file and re-run the generator. +// To change operator data, edit the overrides/snippets files and re-run the generator. import { registerOperators } from './getFilteredCompletions'; import { META_VARIABLE } from './metaTags'; diff --git a/packages/documentdb-constants/src/updateOperators.ts b/packages/documentdb-constants/src/updateOperators.ts index 750cd8742..c02ef9ce7 100644 --- a/packages/documentdb-constants/src/updateOperators.ts +++ b/packages/documentdb-constants/src/updateOperators.ts @@ -6,10 +6,11 @@ // AUTO-GENERATED — DO NOT EDIT BY HAND // // Generated by: npm run generate (scripts/generate-from-reference.ts) -// Sources: resources/operator-reference-scraped.md -// resources/operator-reference-overrides.md +// Sources: resources/scraped/operator-reference.md +// resources/overrides/operator-overrides.md +// resources/overrides/operator-snippets.md // -// To change operator data, edit the overrides file and re-run the generator. +// To change operator data, edit the overrides/snippets files and re-run the generator. import { getDocLink } from './docLinks'; import { registerOperators } from './getFilteredCompletions'; diff --git a/packages/documentdb-constants/src/windowOperators.ts b/packages/documentdb-constants/src/windowOperators.ts index 701356c2a..05481809f 100644 --- a/packages/documentdb-constants/src/windowOperators.ts +++ b/packages/documentdb-constants/src/windowOperators.ts @@ -6,10 +6,11 @@ // AUTO-GENERATED — DO NOT EDIT BY HAND // // Generated by: npm run generate (scripts/generate-from-reference.ts) -// Sources: resources/operator-reference-scraped.md -// resources/operator-reference-overrides.md +// Sources: resources/scraped/operator-reference.md +// resources/overrides/operator-overrides.md +// resources/overrides/operator-snippets.md // -// To change operator data, edit the overrides file and re-run the generator. +// To change operator data, edit the overrides/snippets files and re-run the generator. import { getDocLink } from './docLinks'; import { registerOperators } from './getFilteredCompletions'; From 6938ccd4b1affba5cb1f360c63e2232189d12529 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Fri, 20 Feb 2026 16:02:11 +0000 Subject: [PATCH 035/128] Refactor import statements and improve descriptions in DocumentDB constants - Reordered import statements for consistency across files in `stages.ts`, `systemVariables.ts`, `updateOperators.ts`, and `windowOperators.ts`. - Consolidated multiline descriptions into single lines for clarity and consistency. - Updated registration of operators to use spread syntax for improved readability. - Ensured all links are marked as inferred from another category for better documentation. --- .../resources/overrides/operator-overrides.md | 18 ++ .../resources/scraped/operator-reference.md | 208 +++++++++--------- .../scripts/evaluate-overrides.ts | 55 ++++- .../scripts/generate-from-reference.ts | 57 ++++- .../scripts/scrape-operator-docs.ts | 11 +- .../documentdb-constants/src/accumulators.ts | 34 ++- .../src/expressionOperators.ts | 175 +++++++-------- .../src/parseOperatorReference.ts | 5 +- .../src/queryOperators.ts | 123 +++++------ packages/documentdb-constants/src/stages.ts | 79 +++---- .../src/systemVariables.ts | 29 +-- .../src/updateOperators.ts | 50 ++--- .../src/windowOperators.ts | 73 +++--- 13 files changed, 478 insertions(+), 439 deletions(-) diff --git a/packages/documentdb-constants/resources/overrides/operator-overrides.md b/packages/documentdb-constants/resources/overrides/operator-overrides.md index 521297c9d..ef144691c 100644 --- a/packages/documentdb-constants/resources/overrides/operator-overrides.md +++ b/packages/documentdb-constants/resources/overrides/operator-overrides.md @@ -258,3 +258,21 @@ ### $$KEEP - **Description:** Used with $redact. Keeps all fields at the current document level without further descending into subdocuments. + +## Array Expression Operators + +### $minN + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$minn + +## Comparison Expression Operators + +### $cmp + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$cmp + +## Window Operators + +### $minN + +- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$minn diff --git a/packages/documentdb-constants/resources/scraped/operator-reference.md b/packages/documentdb-constants/resources/scraped/operator-reference.md index b87918205..6ba385cfb 100644 --- a/packages/documentdb-constants/resources/scraped/operator-reference.md +++ b/packages/documentdb-constants/resources/scraped/operator-reference.md @@ -703,8 +703,8 @@ db.collection.updateOne( ) ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$ -- **Scraper Comment:** Doc page not found in expected directory 'projection/'. Using verified URL from 'array-update/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'projection/'. Content scraped from 'array-update/'. ### $elemMatch @@ -715,8 +715,8 @@ db.collection.updateOne( db.collection.find({ : { $elemMatch: { , , ... } } }) ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-query/$elemmatch -- **Scraper Comment:** Doc page not found in expected directory 'projection/'. Using verified URL from 'array-query/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'projection/'. Content scraped from 'array-query/'. ### $slice @@ -729,8 +729,8 @@ db.collection.find({ : { $elemMatch: { , , ... } } }) } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$slice -- **Scraper Comment:** Doc page not found in expected directory 'projection/'. Using verified URL from 'array-expression/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'projection/'. Content scraped from 'array-expression/'. ## Miscellaneous Query Operators @@ -819,8 +819,8 @@ db.collection.find({ : { $elemMatch: { , , ... } } }) $min: ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$min -- **Scraper Comment:** Doc page not found in expected directory 'field-update/'. Using verified URL from 'accumulators/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'field-update/'. Content scraped from 'accumulators/'. ### $max @@ -831,8 +831,8 @@ $min: $max: ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$max -- **Scraper Comment:** Doc page not found in expected directory 'field-update/'. Using verified URL from 'accumulators/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'field-update/'. Content scraped from 'accumulators/'. ### $mul @@ -881,8 +881,8 @@ $max: } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$set -- **Scraper Comment:** Doc page not found in expected directory 'field-update/'. Using verified URL from 'aggregation/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'field-update/'. Content scraped from 'aggregation/'. ### $setOnInsert @@ -912,8 +912,8 @@ $max: } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$unset -- **Scraper Comment:** Doc page not found in expected directory 'field-update/'. Using verified URL from 'aggregation/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'field-update/'. Content scraped from 'aggregation/'. ## Array Update Operators @@ -1040,8 +1040,8 @@ db.collection.update({ } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$slice -- **Scraper Comment:** Doc page not found in expected directory 'array-update/'. Using verified URL from 'array-expression/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'array-update/'. Content scraped from 'array-expression/'. ### $sort @@ -1057,8 +1057,8 @@ db.collection.update({ } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$sort -- **Scraper Comment:** Doc page not found in expected directory 'array-update/'. Using verified URL from 'aggregation/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'array-update/'. Content scraped from 'aggregation/'. ## Bitwise Update Operators @@ -1209,8 +1209,8 @@ db.collection.update({ } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/evaluation-query/$mod -- **Scraper Comment:** Doc page not found in expected directory 'arithmetic-expression/'. Using verified URL from 'evaluation-query/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'arithmetic-expression/'. Content scraped from 'evaluation-query/'. ### $multiply @@ -1365,8 +1365,8 @@ db.collection.update({ } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$firstn -- **Scraper Comment:** Doc page not found in expected directory 'array-expression/'. Using verified URL from 'accumulators/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'array-expression/'. Content scraped from 'accumulators/'. ### $in @@ -1381,8 +1381,8 @@ db.collection.update({ } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$in -- **Scraper Comment:** Doc page not found in expected directory 'array-expression/'. Using verified URL from 'comparison-query/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'array-expression/'. Content scraped from 'comparison-query/'. ### $indexOfArray @@ -1429,8 +1429,8 @@ db.collection.update({ } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$lastn -- **Scraper Comment:** Doc page not found in expected directory 'array-expression/'. Using verified URL from 'accumulators/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'array-expression/'. Content scraped from 'accumulators/'. ### $map @@ -1461,8 +1461,8 @@ $maxN: { } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$maxn -- **Scraper Comment:** Doc page not found in expected directory 'array-expression/'. Using verified URL from 'accumulators/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'array-expression/'. Content scraped from 'accumulators/'. ### $minN @@ -1476,8 +1476,8 @@ $minN: { } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$minn -- **Scraper Comment:** Doc page not found in expected directory 'array-expression/'. Using verified URL from 'accumulators/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'array-expression/'. Content scraped from 'accumulators/'. ### $objectToArray @@ -1531,8 +1531,8 @@ $reduce: { db.collection.find({ : { $size: } }) ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-query/$size -- **Scraper Comment:** Doc page not found in expected directory 'array-expression/'. Using verified URL from 'array-query/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'array-expression/'. Content scraped from 'array-query/'. ### $slice @@ -1653,8 +1653,8 @@ db.collection.find({ : { $size: } }) } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/logical-query/$and -- **Scraper Comment:** Doc page not found in expected directory 'boolean-expression/'. Using verified URL from 'logical-query/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'boolean-expression/'. Content scraped from 'logical-query/'. ### $not @@ -1671,8 +1671,8 @@ db.collection.find({ : { $size: } }) } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/logical-query/$not -- **Scraper Comment:** Doc page not found in expected directory 'boolean-expression/'. Using verified URL from 'logical-query/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'boolean-expression/'. Content scraped from 'logical-query/'. ### $or @@ -1691,8 +1691,8 @@ db.collection.find({ : { $size: } }) } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/logical-query/$or -- **Scraper Comment:** Doc page not found in expected directory 'boolean-expression/'. Using verified URL from 'logical-query/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'boolean-expression/'. Content scraped from 'logical-query/'. ## Comparison Expression Operators @@ -1707,8 +1707,8 @@ db.collection.find({ : { $size: } }) } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$cmp -- **Scraper Comment:** Doc page not found in expected directory 'comparison-expression/'. Using verified URL from 'comparison-query/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'comparison-expression/'. Content scraped from 'comparison-query/'. ### $eq @@ -1723,8 +1723,8 @@ db.collection.find({ : { $size: } }) } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$eq -- **Scraper Comment:** Doc page not found in expected directory 'comparison-expression/'. Using verified URL from 'comparison-query/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'comparison-expression/'. Content scraped from 'comparison-query/'. ### $gt @@ -1739,8 +1739,8 @@ db.collection.find({ : { $size: } }) } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$gt -- **Scraper Comment:** Doc page not found in expected directory 'comparison-expression/'. Using verified URL from 'comparison-query/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'comparison-expression/'. Content scraped from 'comparison-query/'. ### $gte @@ -1755,8 +1755,8 @@ db.collection.find({ : { $size: } }) } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$gte -- **Scraper Comment:** Doc page not found in expected directory 'comparison-expression/'. Using verified URL from 'comparison-query/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'comparison-expression/'. Content scraped from 'comparison-query/'. ### $lt @@ -1771,8 +1771,8 @@ db.collection.find({ : { $size: } }) } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$lt -- **Scraper Comment:** Doc page not found in expected directory 'comparison-expression/'. Using verified URL from 'comparison-query/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'comparison-expression/'. Content scraped from 'comparison-query/'. ### $lte @@ -1787,8 +1787,8 @@ db.collection.find({ : { $size: } }) } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$lte -- **Scraper Comment:** Doc page not found in expected directory 'comparison-expression/'. Using verified URL from 'comparison-query/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'comparison-expression/'. Content scraped from 'comparison-query/'. ### $ne @@ -1803,8 +1803,8 @@ db.collection.find({ : { $size: } }) } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$ne -- **Scraper Comment:** Doc page not found in expected directory 'comparison-expression/'. Using verified URL from 'comparison-query/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'comparison-expression/'. Content scraped from 'comparison-query/'. ## Data Size Operators @@ -2132,8 +2132,8 @@ $dateTrunc: { } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/type-expression/$todate -- **Scraper Comment:** Doc page not found in expected directory 'date-expression/'. Using verified URL from 'aggregation/type-expression/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'date-expression/'. Content scraped from 'aggregation/type-expression/'. ### $week @@ -2206,8 +2206,8 @@ $dateTrunc: { } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/miscellaneous-query/$rand -- **Scraper Comment:** Doc page not found in expected directory 'miscellaneous/'. Using verified URL from 'miscellaneous-query/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'miscellaneous/'. Content scraped from 'miscellaneous-query/'. ### $sampleRate @@ -2383,8 +2383,8 @@ $dateTrunc: { } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$datefromstring -- **Scraper Comment:** Doc page not found in expected directory 'string-expression/'. Using verified URL from 'date-expression/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'string-expression/'. Content scraped from 'date-expression/'. ### $dateToString @@ -2402,8 +2402,8 @@ $dateTrunc: { } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$datetostring -- **Scraper Comment:** Doc page not found in expected directory 'string-expression/'. Using verified URL from 'date-expression/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'string-expression/'. Content scraped from 'date-expression/'. ### $indexOfBytes @@ -2450,8 +2450,8 @@ $dateTrunc: { } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/type-expression/$tostring -- **Scraper Comment:** Doc page not found in expected directory 'string-expression/'. Using verified URL from 'aggregation/type-expression/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'string-expression/'. Content scraped from 'aggregation/type-expression/'. ### $trim @@ -2666,8 +2666,8 @@ $dateTrunc: { } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/element-query/$type -- **Scraper Comment:** Doc page not found in expected directory 'aggregation/type-expression/'. Using verified URL from 'element-query/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'aggregation/type-expression/'. Content scraped from 'element-query/'. ## Accumulators ($group, $bucket, $bucketAuto, $setWindowFields) @@ -2682,8 +2682,8 @@ $dateTrunc: { } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$addtoset -- **Scraper Comment:** Doc page not found in expected directory 'accumulators/'. Using verified URL from 'array-update/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'accumulators/'. Content scraped from 'array-update/'. ### $avg @@ -2869,8 +2869,8 @@ $maxN: { } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/object-expression/$mergeobjects -- **Scraper Comment:** Doc page not found in expected directory 'accumulators/'. Using verified URL from 'object-expression/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'accumulators/'. Content scraped from 'object-expression/'. ### $min @@ -2915,8 +2915,8 @@ db.collection.update({ }) ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$push -- **Scraper Comment:** Doc page not found in expected directory 'accumulators/'. Using verified URL from 'array-update/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'accumulators/'. Content scraped from 'array-update/'. ### $stdDevPop @@ -3173,8 +3173,8 @@ $percentile: { } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$sum -- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Content scraped from 'accumulators/'. ### $push @@ -3193,8 +3193,8 @@ db.collection.update({ }) ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$push -- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'array-update/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Content scraped from 'array-update/'. ### $addToSet @@ -3207,8 +3207,8 @@ db.collection.update({ } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$addtoset -- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'array-update/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Content scraped from 'array-update/'. ### $count @@ -3221,8 +3221,8 @@ db.collection.update({ } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$count -- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Content scraped from 'accumulators/'. ### $max @@ -3233,8 +3233,8 @@ db.collection.update({ $max: ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$max -- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Content scraped from 'accumulators/'. ### $min @@ -3245,8 +3245,8 @@ $max: $min: ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$min -- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Content scraped from 'accumulators/'. ### $avg @@ -3257,8 +3257,8 @@ $min: $avg: ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$avg -- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Content scraped from 'accumulators/'. ### $stdDevPop @@ -3273,8 +3273,8 @@ $avg: } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$stddevpop -- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Content scraped from 'accumulators/'. ### $bottom @@ -3292,8 +3292,8 @@ $avg: } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$bottom -- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Content scraped from 'accumulators/'. ### $bottomN @@ -3312,8 +3312,8 @@ $avg: } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$bottomn -- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Content scraped from 'accumulators/'. ### $covariancePop @@ -3412,8 +3412,8 @@ $avg: } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$first -- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Content scraped from 'accumulators/'. ### $integral @@ -3442,8 +3442,8 @@ $avg: } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$last -- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Content scraped from 'accumulators/'. ### $linearFill @@ -3491,8 +3491,8 @@ $minN: { } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$minn -- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Content scraped from 'accumulators/'. ### $rank @@ -3547,8 +3547,8 @@ $minN: { } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$stddevsamp -- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Content scraped from 'accumulators/'. ### $top @@ -3566,8 +3566,8 @@ $minN: { } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$top -- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Content scraped from 'accumulators/'. ### $topN @@ -3586,8 +3586,8 @@ $minN: { } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$topn -- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Using verified URL from 'accumulators/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'window-operators/'. Content scraped from 'accumulators/'. ## Conditional Expression Operators @@ -3731,8 +3731,8 @@ $minN: { } ``` -- **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$count -- **Scraper Comment:** Doc page not found in expected directory 'aggregation/'. Using verified URL from 'accumulators/' instead. +- **Doc Link:** none +- **Scraper Comment:** Doc page not found in expected directory 'aggregation/'. Content scraped from 'accumulators/'. ### $densify diff --git a/packages/documentdb-constants/scripts/evaluate-overrides.ts b/packages/documentdb-constants/scripts/evaluate-overrides.ts index bf9bfb532..366bfc608 100644 --- a/packages/documentdb-constants/scripts/evaluate-overrides.ts +++ b/packages/documentdb-constants/scripts/evaluate-overrides.ts @@ -30,6 +30,7 @@ interface ParsedEntry { value: string; description: string; category: string; + docLink: string; } interface OverrideEntry { @@ -65,6 +66,7 @@ function parseDump(content: string): ParsedEntry[] { value: currentOp.value!, description: currentOp.description || '', category: currentCategory, + docLink: currentOp.docLink || '', }); } currentOp = null; @@ -84,19 +86,31 @@ function parseDump(content: string): ParsedEntry[] { value: currentOp.value!, description: currentOp.description || '', category: currentCategory, + docLink: currentOp.docLink || '', }); } - currentOp = { value: h3[1].trim(), description: '', category: currentCategory }; + currentOp = { value: h3[1].trim(), description: '', docLink: '', category: currentCategory }; continue; } if (currentOp && line.startsWith('- **Description:**')) { currentOp.description = line.replace('- **Description:**', '').trim(); } + + // Parse doc link ('none' means scraper found no page at expected location) + if (currentOp && line.startsWith('- **Doc Link:**')) { + const rawLink = line.replace('- **Doc Link:**', '').trim(); + currentOp.docLink = rawLink === 'none' ? '' : rawLink; + } } if (currentOp && currentCategory) { - entries.push({ value: currentOp.value!, description: currentOp.description || '', category: currentCategory }); + entries.push({ + value: currentOp.value!, + description: currentOp.description || '', + category: currentCategory, + docLink: currentOp.docLink || '', + }); } return entries; @@ -386,6 +400,7 @@ function main(): void { const gaps: ParsedEntry[] = []; // empty description, no override const overridden: { entry: ParsedEntry; override: OverrideEntry; overrideCategory: string }[] = []; const redundantOverrides: { entry: ParsedEntry; override: OverrideEntry; overrideCategory: string }[] = []; + const docLinkOnlyOverrides: { entry: ParsedEntry; override: OverrideEntry; overrideCategory: string }[] = []; const descriptionsOk: ParsedEntry[] = []; // Collect all dump category names so findOverride can distinguish exact vs cross-category @@ -396,11 +411,22 @@ function main(): void { const hasScrapedDescription = entry.description.trim().length > 0; if (match) { - if (hasScrapedDescription && match.override.description) { + const hasDescOverride = !!match.override.description; + const hasDocLinkOverride = !!match.override.docLink; + const hasSnippetOverride = !!match.override.snippet; + + if (hasScrapedDescription && hasDescOverride) { // Has both scraped description AND an override description redundantOverrides.push({ entry, override: match.override, overrideCategory: match.overrideCategory }); + } else if (!hasDescOverride && hasDocLinkOverride && !hasSnippetOverride) { + // Override provides only a doc link (no description, no snippet) + docLinkOnlyOverrides.push({ + entry, + override: match.override, + overrideCategory: match.overrideCategory, + }); } else { - // Override is filling a gap (or overriding something else) + // Override is filling a description gap (or overriding snippet) overridden.push({ entry, override: match.override, overrideCategory: match.overrideCategory }); } } else if (!hasScrapedDescription) { @@ -477,6 +503,26 @@ function main(): void { console.log(''); } + // ----------------------------------------------------------------------- + // Section 3b: Doc link overrides (operators with 'none' in dump, link provided via override) + // ----------------------------------------------------------------------- + console.log(`${BOLD}${GREEN}═══ DOC LINK OVERRIDES (${docLinkOnlyOverrides.length}) ═══${RESET}`); + if (docLinkOnlyOverrides.length === 0) { + console.log(` ${DIM}No doc-link-only overrides.${RESET}\n`); + } else { + console.log(` ${DIM}These operators have 'none' in the dump (doc page not at expected directory).${RESET}`); + console.log( + ` ${DIM}The override provides a doc link that the generator can't infer via cross-reference.${RESET}\n`, + ); + for (const { entry, override, overrideCategory } of docLinkOnlyOverrides) { + const dumpLink = entry.docLink || 'none'; + console.log(` ${CYAN}${entry.value}${RESET} ${DIM}(${entry.category})${RESET}`); + console.log(` ${DIM}Override (${overrideCategory}):${RESET} ${override.docLink}`); + console.log(` ${DIM}Dump link:${RESET} ${dumpLink}`); + console.log(''); + } + } + // ----------------------------------------------------------------------- // Section 4: Snippet coverage // ----------------------------------------------------------------------- @@ -526,6 +572,7 @@ function main(): void { console.log(` Total scraped operators: ${dumpEntries.length}`); console.log(` With scraped description: ${descriptionsOk.length + redundantOverrides.length}`); console.log(` Filled by override: ${overridden.length}`); + console.log(` Doc-link-only overrides: ${docLinkOnlyOverrides.length}`); console.log(` Potentially redundant: ${YELLOW}${redundantOverrides.length}${RESET}`); console.log(` ${RED}Gaps remaining:${RESET} ${gaps.length}`); console.log(` Total overrides in file: ${totalOverrideCount}`); diff --git a/packages/documentdb-constants/scripts/generate-from-reference.ts b/packages/documentdb-constants/scripts/generate-from-reference.ts index 5afe45201..df28ad924 100644 --- a/packages/documentdb-constants/scripts/generate-from-reference.ts +++ b/packages/documentdb-constants/scripts/generate-from-reference.ts @@ -231,9 +231,10 @@ function parseDump(content: string): Map { continue; } - // Doc link line + // Doc link line ('none' means the scraper found no page at the expected location) if (currentOp && line.startsWith('- **Doc Link:**')) { - currentOp.docLink = line.replace('- **Doc Link:**', '').trim(); + const rawLink = line.replace('- **Doc Link:**', '').trim(); + currentOp.docLink = rawLink === 'none' ? '' : rawLink; continue; } } @@ -521,6 +522,48 @@ function getApplicableBsonTypes(op: ParsedOperator, meta: string): string[] | un return undefined; } +// --------------------------------------------------------------------------- +// Cross-reference: resolve missing doc links from other categories +// --------------------------------------------------------------------------- + +/** + * Builds a map of operator name → URL from all categories. + * For operators that appear with a URL in ANY category, we can use that URL + * when the same operator appears without one in a different category. + * + * Returns the number of operators whose links were inferred. + */ +function crossReferenceMissingLinks(categorizedOps: Map): number { + // Build global URL lookup: operator name → first known URL + const urlLookup = new Map(); + for (const ops of categorizedOps.values()) { + for (const op of ops) { + if (op.docLink && !urlLookup.has(op.value)) { + urlLookup.set(op.value, op.docLink); + } + } + } + + // Fill in missing links from the cross-reference + let inferred = 0; + for (const [category, ops] of categorizedOps.entries()) { + for (const op of ops) { + if (!op.docLink) { + const altUrl = urlLookup.get(op.value); + if (altUrl) { + op.docLink = altUrl; + // Mark as inferred so generateSection can annotate it + (op as ParsedOperator & { inferredLink?: boolean }).inferredLink = true; + inferred++; + console.log(` Inferred link: ${op.value} (${category}) → ${altUrl}`); + } + } + } + } + + return inferred; +} + // --------------------------------------------------------------------------- // File generation // --------------------------------------------------------------------------- @@ -595,14 +638,19 @@ function generateSection(spec: FileSpec, snippets: Map>(); if (fs.existsSync(snippetsPath)) { diff --git a/packages/documentdb-constants/scripts/scrape-operator-docs.ts b/packages/documentdb-constants/scripts/scrape-operator-docs.ts index d51c3bc01..c9a428f23 100644 --- a/packages/documentdb-constants/scripts/scrape-operator-docs.ts +++ b/packages/documentdb-constants/scripts/scrape-operator-docs.ts @@ -728,14 +728,17 @@ async function fetchOperatorDocs(operators: OperatorInfo[]): Promise { if (content) { op.description = extractDescription(content); op.syntax = extractSyntax(content); - op.docLink = `${DOC_LINK_BASE}/${resolvedDir}/${opNameLower}`; - // Record a scraper comment when the doc page was found in a - // different directory than the operator's primary category if (primaryDir && resolvedDir !== primaryDir) { + // Doc page found in a different directory — emit 'none' + // so the generator can cross-reference alternative URLs. + // Description/syntax were still scraped from the fallback page. + op.docLink = 'none'; op.scraperComment = `Doc page not found in expected directory '${primaryDir}/'. ` + - `Using verified URL from '${resolvedDir}/' instead.`; + `Content scraped from '${resolvedDir}/'.`; + } else { + op.docLink = `${DOC_LINK_BASE}/${resolvedDir}/${opNameLower}`; } succeeded++; } else { diff --git a/packages/documentdb-constants/src/accumulators.ts b/packages/documentdb-constants/src/accumulators.ts index 3f0f7120c..5a3db91fc 100644 --- a/packages/documentdb-constants/src/accumulators.ts +++ b/packages/documentdb-constants/src/accumulators.ts @@ -12,10 +12,10 @@ // // To change operator data, edit the overrides/snippets files and re-run the generator. +import { type OperatorEntry } from './types'; +import { META_ACCUMULATOR } from './metaTags'; import { getDocLink } from './docLinks'; import { registerOperators } from './getFilteredCompletions'; -import { META_ACCUMULATOR } from './metaTags'; -import { type OperatorEntry } from './types'; // --------------------------------------------------------------------------- // Accumulators ($group, $bucket, $bucketAuto, $setWindowFields) @@ -25,10 +25,9 @@ const groupAccumulators: readonly OperatorEntry[] = [ { value: '$addToSet', meta: META_ACCUMULATOR, - description: - "The addToSet operator adds elements to an array if they don't already exist, while ensuring uniqueness of elements within the set.", + description: 'The addToSet operator adds elements to an array if they don\'t already exist, while ensuring uniqueness of elements within the set.', snippet: '{ $addToSet: "${1:\\$field}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$addtoset', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$addtoset', // inferred from another category }, { value: '$avg', @@ -40,8 +39,7 @@ const groupAccumulators: readonly OperatorEntry[] = [ { value: '$bottom', meta: META_ACCUMULATOR, - description: - "The $bottom operator returns the last document from the query's result set sorted by one or more fields", + description: 'The $bottom operator returns the last document from the query\'s result set sorted by one or more fields', snippet: '{ $bottom: { sortBy: { ${1:field}: ${2:1} }, output: "${3:\\$field}" } }', link: getDocLink('$bottom', META_ACCUMULATOR), }, @@ -55,23 +53,21 @@ const groupAccumulators: readonly OperatorEntry[] = [ { value: '$count', meta: META_ACCUMULATOR, - description: - 'The `$count` operator is used to count the number of documents that match a query filtering criteria.', + description: 'The `$count` operator is used to count the number of documents that match a query filtering criteria.', snippet: '{ $count: {} }', link: getDocLink('$count', META_ACCUMULATOR), }, { value: '$first', meta: META_ACCUMULATOR, - description: "The $first operator returns the first value in a group according to the group's sorting order.", + description: 'The $first operator returns the first value in a group according to the group\'s sorting order.', snippet: '{ $first: "${1:\\$field}" }', link: getDocLink('$first', META_ACCUMULATOR), }, { value: '$firstN', meta: META_ACCUMULATOR, - description: - 'The $firstN operator sorts documents on one or more fields specified by the query and returns the first N document matching the filtering criteria', + description: 'The $firstN operator sorts documents on one or more fields specified by the query and returns the first N document matching the filtering criteria', snippet: '{ $firstN: { input: "${1:\\$field}", n: ${2:number} } }', link: getDocLink('$firstN', META_ACCUMULATOR), }, @@ -115,7 +111,7 @@ const groupAccumulators: readonly OperatorEntry[] = [ meta: META_ACCUMULATOR, description: 'The $mergeObjects operator merges multiple documents into a single document', snippet: '{ $mergeObjects: "${1:\\$field}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/object-expression/$mergeobjects', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/object-expression/$mergeobjects', // inferred from another category }, { value: '$min', @@ -127,8 +123,7 @@ const groupAccumulators: readonly OperatorEntry[] = [ { value: '$percentile', meta: META_ACCUMULATOR, - description: - 'The $percentile operator calculates the percentile of numerical values that match a filtering criteria', + description: 'The $percentile operator calculates the percentile of numerical values that match a filtering criteria', snippet: '{ $percentile: { input: "${1:\\$field}", p: [${2:0.5}], method: "approximate" } }', link: getDocLink('$percentile', META_ACCUMULATOR), }, @@ -137,7 +132,7 @@ const groupAccumulators: readonly OperatorEntry[] = [ meta: META_ACCUMULATOR, description: 'The $push operator adds a specified value to an array within a document.', snippet: '{ $push: "${1:\\$field}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$push', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$push', // inferred from another category }, { value: '$stdDevPop', @@ -149,8 +144,7 @@ const groupAccumulators: readonly OperatorEntry[] = [ { value: '$stdDevSamp', meta: META_ACCUMULATOR, - description: - 'The $stddevsamp operator calculates the standard deviation of a specified sample of values and not the entire population', + description: 'The $stddevsamp operator calculates the standard deviation of a specified sample of values and not the entire population', snippet: '{ $stdDevSamp: "${1:\\$field}" }', link: getDocLink('$stdDevSamp', META_ACCUMULATOR), }, @@ -181,4 +175,6 @@ const groupAccumulators: readonly OperatorEntry[] = [ // Registration // --------------------------------------------------------------------------- -registerOperators([...groupAccumulators]); +registerOperators([ + ...groupAccumulators, +]); diff --git a/packages/documentdb-constants/src/expressionOperators.ts b/packages/documentdb-constants/src/expressionOperators.ts index 3fed68c32..08c16f25a 100644 --- a/packages/documentdb-constants/src/expressionOperators.ts +++ b/packages/documentdb-constants/src/expressionOperators.ts @@ -12,10 +12,8 @@ // // To change operator data, edit the overrides/snippets files and re-run the generator. -import { getDocLink } from './docLinks'; -import { registerOperators } from './getFilteredCompletions'; -import { - META_EXPR_ARITH, +import { type OperatorEntry } from './types'; +import { META_EXPR_ARITH, META_EXPR_ARRAY, META_EXPR_BITWISE, META_EXPR_BOOL, @@ -31,9 +29,9 @@ import { META_EXPR_TIMESTAMP, META_EXPR_TRIG, META_EXPR_TYPE, - META_EXPR_VARIABLE, -} from './metaTags'; -import { type OperatorEntry } from './types'; + META_EXPR_VARIABLE } from './metaTags'; +import { getDocLink } from './docLinks'; +import { registerOperators } from './getFilteredCompletions'; // --------------------------------------------------------------------------- // Arithmetic Expression Operators @@ -106,10 +104,9 @@ const arithmeticExpressionOperators: readonly OperatorEntry[] = [ { value: '$mod', meta: META_EXPR_ARITH, - description: - 'The $mod operator performs a modulo operation on the value of a field and selects documents with a specified result.', + description: 'The $mod operator performs a modulo operation on the value of a field and selects documents with a specified result.', snippet: '{ $mod: ["${1:\\$field1}", "${2:\\$field2}"] }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/evaluation-query/$mod', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/evaluation-query/$mod', // inferred from another category }, { value: '$multiply', @@ -121,8 +118,7 @@ const arithmeticExpressionOperators: readonly OperatorEntry[] = [ { value: '$pow', meta: META_EXPR_ARITH, - description: - 'The `$pow` operator calculates the value of a numerical value raised to the power of a specified exponent.', + description: 'The `$pow` operator calculates the value of a numerical value raised to the power of a specified exponent.', snippet: '{ $pow: ["${1:\\$field1}", "${2:\\$field2}"] }', link: getDocLink('$pow', META_EXPR_ARITH), }, @@ -156,6 +152,7 @@ const arithmeticExpressionOperators: readonly OperatorEntry[] = [ }, ]; + // --------------------------------------------------------------------------- // Array Expression Operators // --------------------------------------------------------------------------- @@ -192,23 +189,21 @@ const arrayExpressionOperators: readonly OperatorEntry[] = [ { value: '$firstN', meta: META_EXPR_ARRAY, - description: - 'The $firstN operator sorts documents on one or more fields specified by the query and returns the first N document matching the filtering criteria', + description: 'The $firstN operator sorts documents on one or more fields specified by the query and returns the first N document matching the filtering criteria', snippet: '{ $firstN: { input: "${1:\\$array}", n: ${2:number} } }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$firstn', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$firstn', // inferred from another category }, { value: '$in', meta: META_EXPR_ARRAY, description: 'The $in operator matches value of a field against an array of specified values', snippet: '{ $in: ["${1:\\$field}", "${2:\\$array}"] }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$in', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$in', // inferred from another category }, { value: '$indexOfArray', meta: META_EXPR_ARRAY, - description: - 'The $indexOfArray operator is used to search for an element in an array and return the index of the first occurrence of the element.', + description: 'The $indexOfArray operator is used to search for an element in an array and return the index of the first occurrence of the element.', snippet: '{ $indexOfArray: ["${1:\\$array}", "${2:value}"] }', link: getDocLink('$indexOfArray', META_EXPR_ARRAY), }, @@ -224,7 +219,7 @@ const arrayExpressionOperators: readonly OperatorEntry[] = [ meta: META_EXPR_ARRAY, description: 'The $lastN accumulator operator returns the last N values in a group of documents.', snippet: '{ $lastN: { input: "${1:\\$array}", n: ${2:number} } }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$lastn', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$lastn', // inferred from another category }, { value: '$map', @@ -238,7 +233,7 @@ const arrayExpressionOperators: readonly OperatorEntry[] = [ meta: META_EXPR_ARRAY, description: 'Retrieves the top N values based on a specified filtering criteria', snippet: '{ $maxN: { input: "${1:\\$array}", n: ${2:number} } }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$maxn', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$maxn', // inferred from another category }, { value: '$minN', @@ -252,6 +247,7 @@ const arrayExpressionOperators: readonly OperatorEntry[] = [ meta: META_EXPR_ARRAY, description: 'Converts an object into an array of key-value pair documents.', snippet: '{ $objectToArray: "${1:\\$object}" }', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/object-expression/$objecttoarray', // inferred from another category }, { value: '$range', @@ -263,8 +259,7 @@ const arrayExpressionOperators: readonly OperatorEntry[] = [ { value: '$reduce', meta: META_EXPR_ARRAY, - description: - 'The $reduce operator applies an expression to each element in an array & accumulate result as single value.', + description: 'The $reduce operator applies an expression to each element in an array & accumulate result as single value.', snippet: '{ $reduce: { input: "${1:\\$array}", initialValue: ${2:0}, in: { ${3:expression} } } }', link: getDocLink('$reduce', META_EXPR_ARRAY), }, @@ -278,10 +273,9 @@ const arrayExpressionOperators: readonly OperatorEntry[] = [ { value: '$size', meta: META_EXPR_ARRAY, - description: - 'The $size operator is used to query documents where an array field has a specified number of elements.', + description: 'The $size operator is used to query documents where an array field has a specified number of elements.', snippet: '{ $size: "${1:\\$array}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-query/$size', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-query/$size', // inferred from another category }, { value: '$slice', @@ -306,6 +300,7 @@ const arrayExpressionOperators: readonly OperatorEntry[] = [ }, ]; + // --------------------------------------------------------------------------- // Bitwise Operators // --------------------------------------------------------------------------- @@ -314,24 +309,21 @@ const bitwiseOperators: readonly OperatorEntry[] = [ { value: '$bitAnd', meta: META_EXPR_BITWISE, - description: - 'The $bitAnd operator performs a bitwise AND operation on integer values and returns the result as an integer.', + description: 'The $bitAnd operator performs a bitwise AND operation on integer values and returns the result as an integer.', snippet: '{ $bitAnd: [${1:value1}, ${2:value2}] }', link: getDocLink('$bitAnd', META_EXPR_BITWISE), }, { value: '$bitNot', meta: META_EXPR_BITWISE, - description: - 'The $bitNot operator performs a bitwise NOT operation on integer values and returns the result as an integer.', + description: 'The $bitNot operator performs a bitwise NOT operation on integer values and returns the result as an integer.', snippet: '{ $bitNot: "${1:\\$field}" }', link: getDocLink('$bitNot', META_EXPR_BITWISE), }, { value: '$bitOr', meta: META_EXPR_BITWISE, - description: - 'The $bitOr operator performs a bitwise OR operation on integer values and returns the result as an integer.', + description: 'The $bitOr operator performs a bitwise OR operation on integer values and returns the result as an integer.', snippet: '{ $bitOr: [${1:value1}, ${2:value2}] }', link: getDocLink('$bitOr', META_EXPR_BITWISE), }, @@ -344,6 +336,7 @@ const bitwiseOperators: readonly OperatorEntry[] = [ }, ]; + // --------------------------------------------------------------------------- // Boolean Expression Operators // --------------------------------------------------------------------------- @@ -352,29 +345,27 @@ const booleanExpressionOperators: readonly OperatorEntry[] = [ { value: '$and', meta: META_EXPR_BOOL, - description: - 'The $and operator joins multiple query clauses and returns documents that match all specified conditions.', + description: 'The $and operator joins multiple query clauses and returns documents that match all specified conditions.', snippet: '{ $and: ["${1:expression1}", "${2:expression2}"] }', - link: getDocLink('$and', META_EXPR_BOOL), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/logical-query/$and', // inferred from another category }, { value: '$not', meta: META_EXPR_BOOL, - description: - "The $not operator performs a logical NOT operation on a specified expression, selecting documents that don't match the expression.", + description: 'The $not operator performs a logical NOT operation on a specified expression, selecting documents that don\'t match the expression.', snippet: '{ $not: ["${1:expression}"] }', - link: getDocLink('$not', META_EXPR_BOOL), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/logical-query/$not', // inferred from another category }, { value: '$or', meta: META_EXPR_BOOL, - description: - 'The $or operator joins query clauses with a logical OR and returns documents that match at least one of the specified conditions.', + description: 'The $or operator joins query clauses with a logical OR and returns documents that match at least one of the specified conditions.', snippet: '{ $or: ["${1:expression1}", "${2:expression2}"] }', - link: getDocLink('$or', META_EXPR_BOOL), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/logical-query/$or', // inferred from another category }, ]; + // --------------------------------------------------------------------------- // Comparison Expression Operators // --------------------------------------------------------------------------- @@ -392,48 +383,46 @@ const comparisonExpressionOperators: readonly OperatorEntry[] = [ meta: META_EXPR_COMPARISON, description: 'The $eq query operator compares the value of a field to a specified value', snippet: '{ $eq: ["${1:\\$field1}", "${2:\\$field2}"] }', - link: getDocLink('$eq', META_EXPR_COMPARISON), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$eq', // inferred from another category }, { value: '$gt', meta: META_EXPR_COMPARISON, - description: - 'The $gt query operator retrieves documents where the value of a field is greater than a specified value', + description: 'The $gt query operator retrieves documents where the value of a field is greater than a specified value', snippet: '{ $gt: ["${1:\\$field1}", "${2:\\$field2}"] }', - link: getDocLink('$gt', META_EXPR_COMPARISON), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$gt', // inferred from another category }, { value: '$gte', meta: META_EXPR_COMPARISON, - description: - 'The $gte operator retrieves documents where the value of a field is greater than or equal to a specified value', + description: 'The $gte operator retrieves documents where the value of a field is greater than or equal to a specified value', snippet: '{ $gte: ["${1:\\$field1}", "${2:\\$field2}"] }', - link: getDocLink('$gte', META_EXPR_COMPARISON), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$gte', // inferred from another category }, { value: '$lt', meta: META_EXPR_COMPARISON, description: 'The $lt operator retrieves documents where the value of field is less than a specified value', snippet: '{ $lt: ["${1:\\$field1}", "${2:\\$field2}"] }', - link: getDocLink('$lt', META_EXPR_COMPARISON), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$lt', // inferred from another category }, { value: '$lte', meta: META_EXPR_COMPARISON, - description: - 'The $lte operator retrieves documents where the value of a field is less than or equal to a specified value', + description: 'The $lte operator retrieves documents where the value of a field is less than or equal to a specified value', snippet: '{ $lte: ["${1:\\$field1}", "${2:\\$field2}"] }', - link: getDocLink('$lte', META_EXPR_COMPARISON), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$lte', // inferred from another category }, { value: '$ne', meta: META_EXPR_COMPARISON, - description: "The $ne operator retrieves documents where the value of a field doesn't equal a specified value", + description: 'The $ne operator retrieves documents where the value of a field doesn\'t equal a specified value', snippet: '{ $ne: ["${1:\\$field1}", "${2:\\$field2}"] }', - link: getDocLink('$ne', META_EXPR_COMPARISON), + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$ne', // inferred from another category }, ]; + // --------------------------------------------------------------------------- // Data Size Operators // --------------------------------------------------------------------------- @@ -455,6 +444,7 @@ const dataSizeOperators: readonly OperatorEntry[] = [ }, ]; + // --------------------------------------------------------------------------- // Date Expression Operators // --------------------------------------------------------------------------- @@ -470,8 +460,7 @@ const dateExpressionOperators: readonly OperatorEntry[] = [ { value: '$dateDiff', meta: META_EXPR_DATE, - description: - 'The $dateDiff operator calculates the difference between two dates in various units such as years, months, days, etc.', + description: 'The $dateDiff operator calculates the difference between two dates in various units such as years, months, days, etc.', snippet: '{ $dateDiff: { startDate: "${1:\\$startDate}", endDate: "${2:\\$endDate}", unit: "${3:day}" } }', link: getDocLink('$dateDiff', META_EXPR_DATE), }, @@ -499,8 +488,7 @@ const dateExpressionOperators: readonly OperatorEntry[] = [ { value: '$dateToParts', meta: META_EXPR_DATE, - description: - 'The $dateToParts operator decomposes a date into its individual parts such as year, month, day, and more.', + description: 'The $dateToParts operator decomposes a date into its individual parts such as year, month, day, and more.', snippet: '{ $dateToParts: { date: "${1:\\$dateField}" } }', link: getDocLink('$dateToParts', META_EXPR_DATE), }, @@ -549,24 +537,21 @@ const dateExpressionOperators: readonly OperatorEntry[] = [ { value: '$isoDayOfWeek', meta: META_EXPR_DATE, - description: - 'The $isoDayOfWeek operator returns the weekday number in ISO 8601 format, ranging from 1 (Monday) to 7 (Sunday).', + description: 'The $isoDayOfWeek operator returns the weekday number in ISO 8601 format, ranging from 1 (Monday) to 7 (Sunday).', snippet: '{ $isoDayOfWeek: "${1:\\$dateField}" }', link: getDocLink('$isoDayOfWeek', META_EXPR_DATE), }, { value: '$isoWeek', meta: META_EXPR_DATE, - description: - 'The $isoWeek operator returns the week number of the year in ISO 8601 format, ranging from 1 to 53.', + description: 'The $isoWeek operator returns the week number of the year in ISO 8601 format, ranging from 1 to 53.', snippet: '{ $isoWeek: "${1:\\$dateField}" }', link: getDocLink('$isoWeek', META_EXPR_DATE), }, { value: '$isoWeekYear', meta: META_EXPR_DATE, - description: - 'The $isoWeekYear operator returns the year number in ISO 8601 format, which can differ from the calendar year for dates at the beginning or end of the year.', + description: 'The $isoWeekYear operator returns the year number in ISO 8601 format, which can differ from the calendar year for dates at the beginning or end of the year.', snippet: '{ $isoWeekYear: "${1:\\$dateField}" }', link: getDocLink('$isoWeekYear', META_EXPR_DATE), }, @@ -603,7 +588,7 @@ const dateExpressionOperators: readonly OperatorEntry[] = [ meta: META_EXPR_DATE, description: 'The $toDate operator converts supported types to a proper Date object.', snippet: '{ $toDate: "${1:\\$field}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/type-expression/$todate', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/type-expression/$todate', // inferred from another category }, { value: '$week', @@ -621,6 +606,7 @@ const dateExpressionOperators: readonly OperatorEntry[] = [ }, ]; + // --------------------------------------------------------------------------- // Literal Expression Operator // --------------------------------------------------------------------------- @@ -629,13 +615,13 @@ const literalExpressionOperator: readonly OperatorEntry[] = [ { value: '$literal', meta: META_EXPR_LITERAL, - description: - 'The $literal operator returns the specified value without parsing it as an expression, allowing literal values to be used in aggregation pipelines.', + description: 'The $literal operator returns the specified value without parsing it as an expression, allowing literal values to be used in aggregation pipelines.', snippet: '{ $literal: ${1:value} }', link: getDocLink('$literal', META_EXPR_LITERAL), }, ]; + // --------------------------------------------------------------------------- // Miscellaneous Operators // --------------------------------------------------------------------------- @@ -653,18 +639,18 @@ const miscellaneousOperators: readonly OperatorEntry[] = [ meta: META_EXPR_MISC, description: 'The $rand operator generates a random float value between 0 and 1.', snippet: '{ $rand: {} }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/miscellaneous-query/$rand', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/miscellaneous-query/$rand', // inferred from another category }, { value: '$sampleRate', meta: META_EXPR_MISC, - description: - 'The $sampleRate operator randomly samples documents from a collection based on a specified probability rate, useful for statistical analysis and testing.', + description: 'The $sampleRate operator randomly samples documents from a collection based on a specified probability rate, useful for statistical analysis and testing.', snippet: '{ $sampleRate: ${1:0.5} }', link: getDocLink('$sampleRate', META_EXPR_MISC), }, ]; + // --------------------------------------------------------------------------- // Object Expression Operators // --------------------------------------------------------------------------- @@ -680,8 +666,7 @@ const objectExpressionOperators: readonly OperatorEntry[] = [ { value: '$objectToArray', meta: META_EXPR_OBJECT, - description: - 'The objectToArray command is used to transform a document (object) into an array of key-value pairs.', + description: 'The objectToArray command is used to transform a document (object) into an array of key-value pairs.', snippet: '{ $objectToArray: "${1:\\$object}" }', link: getDocLink('$objectToArray', META_EXPR_OBJECT), }, @@ -694,6 +679,7 @@ const objectExpressionOperators: readonly OperatorEntry[] = [ }, ]; + // --------------------------------------------------------------------------- // Set Expression Operators // --------------------------------------------------------------------------- @@ -709,16 +695,14 @@ const setExpressionOperators: readonly OperatorEntry[] = [ { value: '$anyElementTrue', meta: META_EXPR_SET, - description: - 'The $anyElementTrue operator returns true if any element in an array evaluates to a value of true.', + description: 'The $anyElementTrue operator returns true if any element in an array evaluates to a value of true.', snippet: '{ $anyElementTrue: ["${1:\\$array}"] }', link: getDocLink('$anyElementTrue', META_EXPR_SET), }, { value: '$setDifference', meta: META_EXPR_SET, - description: - 'The $setDifference operator returns a set with elements that exist in one set but not in a second set.', + description: 'The $setDifference operator returns a set with elements that exist in one set but not in a second set.', snippet: '{ $setDifference: ["${1:\\$set1}", "${2:\\$set2}"] }', link: getDocLink('$setDifference', META_EXPR_SET), }, @@ -746,13 +730,13 @@ const setExpressionOperators: readonly OperatorEntry[] = [ { value: '$setUnion', meta: META_EXPR_SET, - description: - 'The $setUnion operator returns an array that contains all the unique elements from the input arrays.', + description: 'The $setUnion operator returns an array that contains all the unique elements from the input arrays.', snippet: '{ $setUnion: ["${1:\\$set1}", "${2:\\$set2}"] }', link: getDocLink('$setUnion', META_EXPR_SET), }, ]; + // --------------------------------------------------------------------------- // String Expression Operators // --------------------------------------------------------------------------- @@ -769,14 +753,14 @@ const stringExpressionOperators: readonly OperatorEntry[] = [ meta: META_EXPR_STRING, description: 'The $dateDiff operator converts a date/time string to a date object.', snippet: '{ $dateFromString: "${1:\\$string}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$datefromstring', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$datefromstring', // inferred from another category }, { value: '$dateToString', meta: META_EXPR_STRING, description: 'The $dateToString operator converts a date object into a formatted string.', snippet: '{ $dateToString: "${1:\\$string}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$datetostring', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/date-expression/$datetostring', // inferred from another category }, { value: '$indexOfBytes', @@ -859,22 +843,19 @@ const stringExpressionOperators: readonly OperatorEntry[] = [ { value: '$substr', meta: META_EXPR_STRING, - description: - 'Returns a substring of a string, starting at a specified index for a specified length. Deprecated — use $substrBytes or $substrCP.', + description: 'Returns a substring of a string, starting at a specified index for a specified length. Deprecated — use $substrBytes or $substrCP.', snippet: '{ $substr: ["${1:\\$string}", ${2:start}, ${3:length}] }', }, { value: '$substrBytes', meta: META_EXPR_STRING, - description: - 'Returns a substring of a string by byte index, starting at a specified index for a specified number of bytes.', + description: 'Returns a substring of a string by byte index, starting at a specified index for a specified number of bytes.', snippet: '{ $substrBytes: ["${1:\\$string}", ${2:start}, ${3:length}] }', }, { value: '$substrCP', meta: META_EXPR_STRING, - description: - 'Returns a substring of a string by code point index, starting at a specified index for a specified number of code points.', + description: 'Returns a substring of a string by code point index, starting at a specified index for a specified number of code points.', snippet: '{ $substrCP: ["${1:\\$string}", ${2:start}, ${3:length}] }', }, { @@ -888,7 +869,7 @@ const stringExpressionOperators: readonly OperatorEntry[] = [ meta: META_EXPR_STRING, description: 'The $toString operator converts an expression into a String', snippet: '{ $toString: "${1:\\$string}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/type-expression/$tostring', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/type-expression/$tostring', // inferred from another category }, { value: '$trim', @@ -904,6 +885,7 @@ const stringExpressionOperators: readonly OperatorEntry[] = [ }, ]; + // --------------------------------------------------------------------------- // Timestamp Expression Operators // --------------------------------------------------------------------------- @@ -925,6 +907,7 @@ const timestampExpressionOperators: readonly OperatorEntry[] = [ }, ]; + // --------------------------------------------------------------------------- // Trigonometry Expression Operators // --------------------------------------------------------------------------- @@ -1022,6 +1005,7 @@ const trigonometryExpressionOperators: readonly OperatorEntry[] = [ }, ]; + // --------------------------------------------------------------------------- // Type Expression Operators // --------------------------------------------------------------------------- @@ -1102,10 +1086,11 @@ const typeExpressionOperators: readonly OperatorEntry[] = [ meta: META_EXPR_TYPE, description: 'The $type operator retrieves documents if the chosen field is of the specified type.', snippet: '{ $type: "${1:\\$field}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/element-query/$type', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/element-query/$type', // inferred from another category }, ]; + // --------------------------------------------------------------------------- // Variable Expression Operators // --------------------------------------------------------------------------- @@ -1114,13 +1099,13 @@ const variableExpressionOperators: readonly OperatorEntry[] = [ { value: '$let', meta: META_EXPR_VARIABLE, - description: - 'The $let operator allows defining variables for use in a specified expression, enabling complex calculations and reducing code repetition.', + description: 'The $let operator allows defining variables for use in a specified expression, enabling complex calculations and reducing code repetition.', snippet: '{ $let: { vars: { ${1:var}: ${2:expression} }, in: ${3:expression} } }', link: getDocLink('$let', META_EXPR_VARIABLE), }, ]; + // --------------------------------------------------------------------------- // Conditional Expression Operators // --------------------------------------------------------------------------- @@ -1129,26 +1114,22 @@ const conditionalExpressionOperators: readonly OperatorEntry[] = [ { value: '$cond', meta: META_EXPR_CONDITIONAL, - description: - 'The $cond operator is used to evaluate a condition and return one of two expressions based on the result.', + description: 'The $cond operator is used to evaluate a condition and return one of two expressions based on the result.', snippet: '{ $cond: { if: { ${1:expression} }, then: ${2:trueValue}, else: ${3:falseValue} } }', link: getDocLink('$cond', META_EXPR_CONDITIONAL), }, { value: '$ifNull', meta: META_EXPR_CONDITIONAL, - description: - 'The $ifNull operator is used to evaluate an expression and return a specified value if the expression resolves to null.', + description: 'The $ifNull operator is used to evaluate an expression and return a specified value if the expression resolves to null.', snippet: '{ $ifNull: ["${1:\\$field}", ${2:replacement}] }', link: getDocLink('$ifNull', META_EXPR_CONDITIONAL), }, { value: '$switch', meta: META_EXPR_CONDITIONAL, - description: - 'The $switch operator is used to evaluate a series of conditions and return a value based on the first condition that evaluates to true.', - snippet: - '{ $switch: { branches: [{ case: { ${1:expression} }, then: ${2:value} }], default: ${3:defaultValue} } }', + description: 'The $switch operator is used to evaluate a series of conditions and return a value based on the first condition that evaluates to true.', + snippet: '{ $switch: { branches: [{ case: { ${1:expression} }, then: ${2:value} }], default: ${3:defaultValue} } }', link: getDocLink('$switch', META_EXPR_CONDITIONAL), }, ]; diff --git a/packages/documentdb-constants/src/parseOperatorReference.ts b/packages/documentdb-constants/src/parseOperatorReference.ts index cb94e784d..e1179c336 100644 --- a/packages/documentdb-constants/src/parseOperatorReference.ts +++ b/packages/documentdb-constants/src/parseOperatorReference.ts @@ -144,10 +144,11 @@ export function parseOperatorReference(content: string): ParsedReference { continue; } - // Parse doc link: - **Doc Link:** url + // Parse doc link: - **Doc Link:** url ('none' means no page at expected location) const linkMatch = trimmed.match(/^- \*\*Doc Link:\*\* (.+)$/); if (linkMatch && currentOperator) { - currentDocLink = linkMatch[1].trim(); + const rawLink = linkMatch[1].trim(); + currentDocLink = rawLink === 'none' ? '' : rawLink; continue; } } diff --git a/packages/documentdb-constants/src/queryOperators.ts b/packages/documentdb-constants/src/queryOperators.ts index 95998b22d..e79f5b62d 100644 --- a/packages/documentdb-constants/src/queryOperators.ts +++ b/packages/documentdb-constants/src/queryOperators.ts @@ -12,10 +12,8 @@ // // To change operator data, edit the overrides/snippets files and re-run the generator. -import { getDocLink } from './docLinks'; -import { registerOperators } from './getFilteredCompletions'; -import { - META_QUERY_ARRAY, +import { type OperatorEntry } from './types'; +import { META_QUERY_ARRAY, META_QUERY_BITWISE, META_QUERY_COMPARISON, META_QUERY_ELEMENT, @@ -23,9 +21,9 @@ import { META_QUERY_GEOSPATIAL, META_QUERY_LOGICAL, META_QUERY_MISC, - META_QUERY_PROJECTION, -} from './metaTags'; -import { type OperatorEntry } from './types'; + META_QUERY_PROJECTION } from './metaTags'; +import { getDocLink } from './docLinks'; +import { registerOperators } from './getFilteredCompletions'; // --------------------------------------------------------------------------- // Comparison Query Operators @@ -42,16 +40,14 @@ const comparisonQueryOperators: readonly OperatorEntry[] = [ { value: '$gt', meta: META_QUERY_COMPARISON, - description: - 'The $gt query operator retrieves documents where the value of a field is greater than a specified value', + description: 'The $gt query operator retrieves documents where the value of a field is greater than a specified value', snippet: '{ $gt: ${1:value} }', link: getDocLink('$gt', META_QUERY_COMPARISON), }, { value: '$gte', meta: META_QUERY_COMPARISON, - description: - 'The $gte operator retrieves documents where the value of a field is greater than or equal to a specified value', + description: 'The $gte operator retrieves documents where the value of a field is greater than or equal to a specified value', snippet: '{ $gte: ${1:value} }', link: getDocLink('$gte', META_QUERY_COMPARISON), }, @@ -72,27 +68,27 @@ const comparisonQueryOperators: readonly OperatorEntry[] = [ { value: '$lte', meta: META_QUERY_COMPARISON, - description: - 'The $lte operator retrieves documents where the value of a field is less than or equal to a specified value', + description: 'The $lte operator retrieves documents where the value of a field is less than or equal to a specified value', snippet: '{ $lte: ${1:value} }', link: getDocLink('$lte', META_QUERY_COMPARISON), }, { value: '$ne', meta: META_QUERY_COMPARISON, - description: "The $ne operator retrieves documents where the value of a field doesn't equal a specified value", + description: 'The $ne operator retrieves documents where the value of a field doesn\'t equal a specified value', snippet: '{ $ne: ${1:value} }', link: getDocLink('$ne', META_QUERY_COMPARISON), }, { value: '$nin', meta: META_QUERY_COMPARISON, - description: "The $nin operator retrieves documents where the value of a field doesn't match a list of values", + description: 'The $nin operator retrieves documents where the value of a field doesn\'t match a list of values', snippet: '{ $nin: [${1:value}] }', link: getDocLink('$nin', META_QUERY_COMPARISON), }, ]; + // --------------------------------------------------------------------------- // Logical Query Operators // --------------------------------------------------------------------------- @@ -101,37 +97,34 @@ const logicalQueryOperators: readonly OperatorEntry[] = [ { value: '$and', meta: META_QUERY_LOGICAL, - description: - 'The $and operator joins multiple query clauses and returns documents that match all specified conditions.', + description: 'The $and operator joins multiple query clauses and returns documents that match all specified conditions.', snippet: '{ $and: [{ ${1:expression} }] }', link: getDocLink('$and', META_QUERY_LOGICAL), }, { value: '$not', meta: META_QUERY_LOGICAL, - description: - "The $not operator performs a logical NOT operation on a specified expression, selecting documents that don't match the expression.", + description: 'The $not operator performs a logical NOT operation on a specified expression, selecting documents that don\'t match the expression.', snippet: '{ $not: { ${1:expression} } }', link: getDocLink('$not', META_QUERY_LOGICAL), }, { value: '$nor', meta: META_QUERY_LOGICAL, - description: - 'The $nor operator performs a logical NOR on an array of expressions and retrieves documents that fail all the conditions.', + description: 'The $nor operator performs a logical NOR on an array of expressions and retrieves documents that fail all the conditions.', snippet: '{ $nor: [{ ${1:expression} }] }', link: getDocLink('$nor', META_QUERY_LOGICAL), }, { value: '$or', meta: META_QUERY_LOGICAL, - description: - 'The $or operator joins query clauses with a logical OR and returns documents that match at least one of the specified conditions.', + description: 'The $or operator joins query clauses with a logical OR and returns documents that match at least one of the specified conditions.', snippet: '{ $or: [{ ${1:expression} }] }', link: getDocLink('$or', META_QUERY_LOGICAL), }, ]; + // --------------------------------------------------------------------------- // Element Query Operators // --------------------------------------------------------------------------- @@ -140,8 +133,7 @@ const elementQueryOperators: readonly OperatorEntry[] = [ { value: '$exists', meta: META_QUERY_ELEMENT, - description: - 'The $exists operator retrieves documents that contain the specified field in their document structure.', + description: 'The $exists operator retrieves documents that contain the specified field in their document structure.', snippet: '{ $exists: ${1:true} }', link: getDocLink('$exists', META_QUERY_ELEMENT), }, @@ -154,6 +146,7 @@ const elementQueryOperators: readonly OperatorEntry[] = [ }, ]; + // --------------------------------------------------------------------------- // Evaluation Query Operators // --------------------------------------------------------------------------- @@ -162,32 +155,28 @@ const evaluationQueryOperators: readonly OperatorEntry[] = [ { value: '$expr', meta: META_QUERY_EVALUATION, - description: - 'The $expr operator allows the use of aggregation expressions within the query language, enabling complex field comparisons and calculations.', + description: 'The $expr operator allows the use of aggregation expressions within the query language, enabling complex field comparisons and calculations.', snippet: '{ $expr: { ${1:expression} } }', link: getDocLink('$expr', META_QUERY_EVALUATION), }, { value: '$jsonSchema', meta: META_QUERY_EVALUATION, - description: - 'The $jsonSchema operator validates documents against a JSON Schema definition for data validation and structure enforcement. Discover supported features and limitations.', + description: 'The $jsonSchema operator validates documents against a JSON Schema definition for data validation and structure enforcement. Discover supported features and limitations.', snippet: '{ $jsonSchema: { bsonType: "${1:object}" } }', link: getDocLink('$jsonSchema', META_QUERY_EVALUATION), }, { value: '$mod', meta: META_QUERY_EVALUATION, - description: - 'The $mod operator performs a modulo operation on the value of a field and selects documents with a specified result.', + description: 'The $mod operator performs a modulo operation on the value of a field and selects documents with a specified result.', snippet: '{ $mod: [${1:divisor}, ${2:remainder}] }', link: getDocLink('$mod', META_QUERY_EVALUATION), }, { value: '$regex', meta: META_QUERY_EVALUATION, - description: - 'The $regex operator provides regular expression capabilities for pattern matching in queries, allowing flexible string matching and searching.', + description: 'The $regex operator provides regular expression capabilities for pattern matching in queries, allowing flexible string matching and searching.', snippet: '{ $regex: /${1:pattern}/ }', link: getDocLink('$regex', META_QUERY_EVALUATION), applicableBsonTypes: ['string'], @@ -195,14 +184,14 @@ const evaluationQueryOperators: readonly OperatorEntry[] = [ { value: '$text', meta: META_QUERY_EVALUATION, - description: - 'The $text operator performs text search on the content of indexed string fields, enabling full-text search capabilities.', + description: 'The $text operator performs text search on the content of indexed string fields, enabling full-text search capabilities.', snippet: '{ $text: { \\$search: "${1:text}" } }', link: getDocLink('$text', META_QUERY_EVALUATION), applicableBsonTypes: ['string'], }, ]; + // --------------------------------------------------------------------------- // Geospatial Operators // --------------------------------------------------------------------------- @@ -211,16 +200,14 @@ const geospatialOperators: readonly OperatorEntry[] = [ { value: '$geoIntersects', meta: META_QUERY_GEOSPATIAL, - description: - 'The $geoIntersects operator selects documents whose location field intersects with a specified GeoJSON object.', + description: 'The $geoIntersects operator selects documents whose location field intersects with a specified GeoJSON object.', snippet: '{ $geoIntersects: { \\$geometry: { type: "${1:GeoJSON type}", coordinates: ${2:coordinates} } } }', link: getDocLink('$geoIntersects', META_QUERY_GEOSPATIAL), }, { value: '$geoWithin', meta: META_QUERY_GEOSPATIAL, - description: - 'The $geoWithin operator selects documents whose location field is completely within a specified geometry.', + description: 'The $geoWithin operator selects documents whose location field is completely within a specified geometry.', snippet: '{ $geoWithin: { \\$geometry: { type: "${1:GeoJSON type}", coordinates: ${2:coordinates} } } }', link: getDocLink('$geoWithin', META_QUERY_GEOSPATIAL), }, @@ -255,47 +242,41 @@ const geospatialOperators: readonly OperatorEntry[] = [ { value: '$maxDistance', meta: META_QUERY_GEOSPATIAL, - description: - 'The $maxDistance operator specifies the maximum distance that can exist between two points in a geospatial query.', + description: 'The $maxDistance operator specifies the maximum distance that can exist between two points in a geospatial query.', snippet: '${1:distance}', link: getDocLink('$maxDistance', META_QUERY_GEOSPATIAL), }, { value: '$minDistance', meta: META_QUERY_GEOSPATIAL, - description: - 'The $minDistance operator specifies the minimum distance that must exist between two points in a geospatial query.', + description: 'The $minDistance operator specifies the minimum distance that must exist between two points in a geospatial query.', snippet: '${1:distance}', link: getDocLink('$minDistance', META_QUERY_GEOSPATIAL), }, { value: '$polygon', meta: META_QUERY_GEOSPATIAL, - description: - 'The $polygon operator defines a polygon for geospatial queries, allowing you to find locations within an irregular shape.', + description: 'The $polygon operator defines a polygon for geospatial queries, allowing you to find locations within an irregular shape.', snippet: '[[${1:x1}, ${2:y1}], [${3:x2}, ${4:y2}], [${5:x3}, ${6:y3}]]', link: getDocLink('$polygon', META_QUERY_GEOSPATIAL), }, { value: '$near', meta: META_QUERY_GEOSPATIAL, - description: - 'The $near operator returns documents with location fields that are near a specified point, sorted by distance.', - snippet: - '{ $near: { \\$geometry: { type: "Point", coordinates: [${1:lng}, ${2:lat}] }, \\$maxDistance: ${3:distance} } }', + description: 'The $near operator returns documents with location fields that are near a specified point, sorted by distance.', + snippet: '{ $near: { \\$geometry: { type: "Point", coordinates: [${1:lng}, ${2:lat}] }, \\$maxDistance: ${3:distance} } }', link: getDocLink('$near', META_QUERY_GEOSPATIAL), }, { value: '$nearSphere', meta: META_QUERY_GEOSPATIAL, - description: - 'The $nearSphere operator returns documents whose location fields are near a specified point on a sphere, sorted by distance on a spherical surface.', - snippet: - '{ $nearSphere: { \\$geometry: { type: "Point", coordinates: [${1:lng}, ${2:lat}] }, \\$maxDistance: ${3:distance} } }', + description: 'The $nearSphere operator returns documents whose location fields are near a specified point on a sphere, sorted by distance on a spherical surface.', + snippet: '{ $nearSphere: { \\$geometry: { type: "Point", coordinates: [${1:lng}, ${2:lat}] }, \\$maxDistance: ${3:distance} } }', link: getDocLink('$nearSphere', META_QUERY_GEOSPATIAL), }, ]; + // --------------------------------------------------------------------------- // Array Query Operators // --------------------------------------------------------------------------- @@ -312,8 +293,7 @@ const arrayQueryOperators: readonly OperatorEntry[] = [ { value: '$elemMatch', meta: META_QUERY_ARRAY, - description: - 'The $elemmatch operator returns complete array, qualifying criteria with at least one matching array element.', + description: 'The $elemmatch operator returns complete array, qualifying criteria with at least one matching array element.', snippet: '{ $elemMatch: { ${1:query} } }', link: getDocLink('$elemMatch', META_QUERY_ARRAY), applicableBsonTypes: ['array'], @@ -321,14 +301,14 @@ const arrayQueryOperators: readonly OperatorEntry[] = [ { value: '$size', meta: META_QUERY_ARRAY, - description: - 'The $size operator is used to query documents where an array field has a specified number of elements.', + description: 'The $size operator is used to query documents where an array field has a specified number of elements.', snippet: '{ $size: ${1:number} }', link: getDocLink('$size', META_QUERY_ARRAY), applicableBsonTypes: ['array'], }, ]; + // --------------------------------------------------------------------------- // Bitwise Query Operators // --------------------------------------------------------------------------- @@ -337,8 +317,7 @@ const bitwiseQueryOperators: readonly OperatorEntry[] = [ { value: '$bitsAllClear', meta: META_QUERY_BITWISE, - description: - 'The $bitsAllClear operator is used to match documents where all the bit positions specified in a bitmask are clear.', + description: 'The $bitsAllClear operator is used to match documents where all the bit positions specified in a bitmask are clear.', snippet: '{ $bitsAllClear: ${1:bitmask} }', link: getDocLink('$bitsAllClear', META_QUERY_BITWISE), applicableBsonTypes: ['int', 'long'], @@ -354,8 +333,7 @@ const bitwiseQueryOperators: readonly OperatorEntry[] = [ { value: '$bitsAnyClear', meta: META_QUERY_BITWISE, - description: - 'The $bitsAnyClear operator matches documents where any of the specified bit positions in a bitmask are clear.', + description: 'The $bitsAnyClear operator matches documents where any of the specified bit positions in a bitmask are clear.', snippet: '{ $bitsAnyClear: ${1:bitmask} }', link: getDocLink('$bitsAnyClear', META_QUERY_BITWISE), applicableBsonTypes: ['int', 'long'], @@ -363,14 +341,14 @@ const bitwiseQueryOperators: readonly OperatorEntry[] = [ { value: '$bitsAnySet', meta: META_QUERY_BITWISE, - description: - 'The $bitsAnySet operator returns documents where any of the specified bit positions are set to 1.', + description: 'The $bitsAnySet operator returns documents where any of the specified bit positions are set to 1.', snippet: '{ $bitsAnySet: ${1:bitmask} }', link: getDocLink('$bitsAnySet', META_QUERY_BITWISE), applicableBsonTypes: ['int', 'long'], }, ]; + // --------------------------------------------------------------------------- // Projection Operators // --------------------------------------------------------------------------- @@ -379,27 +357,26 @@ const projectionOperators: readonly OperatorEntry[] = [ { value: '$', meta: META_QUERY_PROJECTION, - description: - 'The $ positional operator identifies an element in an array to update without explicitly specifying the position of the element in the array.', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$', + description: 'The $ positional operator identifies an element in an array to update without explicitly specifying the position of the element in the array.', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$', // inferred from another category }, { value: '$elemMatch', meta: META_QUERY_PROJECTION, - description: - 'The $elemmatch operator returns complete array, qualifying criteria with at least one matching array element.', + description: 'The $elemmatch operator returns complete array, qualifying criteria with at least one matching array element.', snippet: '{ $elemMatch: { ${1:query} } }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-query/$elemmatch', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-query/$elemmatch', // inferred from another category }, { value: '$slice', meta: META_QUERY_PROJECTION, description: 'The $slice operator returns a subset of an array from any element onwards in the array.', snippet: '{ $slice: ${1:number} }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$slice', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$slice', // inferred from another category }, ]; + // --------------------------------------------------------------------------- // Miscellaneous Query Operators // --------------------------------------------------------------------------- @@ -408,8 +385,7 @@ const miscellaneousQueryOperators: readonly OperatorEntry[] = [ { value: '$comment', meta: META_QUERY_MISC, - description: - 'The $comment operator adds a comment to a query to help identify the query in logs and profiler output.', + description: 'The $comment operator adds a comment to a query to help identify the query in logs and profiler output.', snippet: '{ $comment: "${1:comment}" }', link: getDocLink('$comment', META_QUERY_MISC), }, @@ -423,8 +399,7 @@ const miscellaneousQueryOperators: readonly OperatorEntry[] = [ { value: '$natural', meta: META_QUERY_MISC, - description: - 'The $natural operator forces the query to use the natural order of documents in a collection, providing control over document ordering and retrieval.', + description: 'The $natural operator forces the query to use the natural order of documents in a collection, providing control over document ordering and retrieval.', snippet: '{ $natural: ${1:1} }', link: getDocLink('$natural', META_QUERY_MISC), }, diff --git a/packages/documentdb-constants/src/stages.ts b/packages/documentdb-constants/src/stages.ts index 68c937726..975f07302 100644 --- a/packages/documentdb-constants/src/stages.ts +++ b/packages/documentdb-constants/src/stages.ts @@ -12,10 +12,10 @@ // // To change operator data, edit the overrides/snippets files and re-run the generator. +import { type OperatorEntry } from './types'; +import { META_STAGE } from './metaTags'; import { getDocLink } from './docLinks'; import { registerOperators } from './getFilteredCompletions'; -import { META_STAGE } from './metaTags'; -import { type OperatorEntry } from './types'; // --------------------------------------------------------------------------- // Aggregation Pipeline Stages @@ -39,8 +39,7 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ { value: '$bucketAuto', meta: META_STAGE, - description: - 'Categorizes documents into a specified number of groups based on a given expression, automatically determining bucket boundaries.', + description: 'Categorizes documents into a specified number of groups based on a given expression, automatically determining bucket boundaries.', snippet: '{ $bucketAuto: { groupBy: "${1:\\$field}", buckets: ${2:number} } }', }, { @@ -53,18 +52,16 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ { value: '$collStats', meta: META_STAGE, - description: - 'The $collStats stage in the aggregation pipeline is used to return statistics about a collection.', + description: 'The $collStats stage in the aggregation pipeline is used to return statistics about a collection.', snippet: '{ $collStats: { storageStats: {} } }', link: getDocLink('$collStats', META_STAGE), }, { value: '$count', meta: META_STAGE, - description: - 'The `$count` operator is used to count the number of documents that match a query filtering criteria.', + description: 'The `$count` operator is used to count the number of documents that match a query filtering criteria.', snippet: '{ $count: "${1:countField}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$count', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$count', // inferred from another category }, { value: '$densify', @@ -83,41 +80,34 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ { value: '$facet', meta: META_STAGE, - description: - 'The $facet allows for multiple parallel aggregations to be executed within a single pipeline stage.', + description: 'The $facet allows for multiple parallel aggregations to be executed within a single pipeline stage.', snippet: '{ $facet: { ${1:outputField}: [{ ${2:stage} }] } }', link: getDocLink('$facet', META_STAGE), }, { value: '$fill', meta: META_STAGE, - description: - 'The $fill stage allows filling missing values in documents based on specified methods and criteria.', + description: 'The $fill stage allows filling missing values in documents based on specified methods and criteria.', snippet: '{ $fill: { output: { ${1:field}: { method: "${2:linear}" } } } }', link: getDocLink('$fill', META_STAGE), }, { value: '$geoNear', meta: META_STAGE, - description: - 'The $geoNear operator finds and sorts documents by their proximity to a geospatial point, returning distance information for each document.', - snippet: - '{ $geoNear: { near: { type: "Point", coordinates: [${1:lng}, ${2:lat}] }, distanceField: "${3:distance}" } }', + description: 'The $geoNear operator finds and sorts documents by their proximity to a geospatial point, returning distance information for each document.', + snippet: '{ $geoNear: { near: { type: "Point", coordinates: [${1:lng}, ${2:lat}] }, distanceField: "${3:distance}" } }', link: getDocLink('$geoNear', META_STAGE), }, { value: '$graphLookup', meta: META_STAGE, - description: - 'Performs a recursive search on a collection to return documents connected by a specified field relationship.', - snippet: - '{ $graphLookup: { from: "${1:collection}", startWith: "${2:\\$field}", connectFromField: "${3:field}", connectToField: "${4:field}", as: "${5:result}" } }', + description: 'Performs a recursive search on a collection to return documents connected by a specified field relationship.', + snippet: '{ $graphLookup: { from: "${1:collection}", startWith: "${2:\\$field}", connectFromField: "${3:field}", connectToField: "${4:field}", as: "${5:result}" } }', }, { value: '$group', meta: META_STAGE, - description: - 'The $group stage groups documents by specified identifier expressions and applies accumulator expressions.', + description: 'The $group stage groups documents by specified identifier expressions and applies accumulator expressions.', snippet: '{ $group: { _id: "${1:\\$field}", ${2:accumulator}: { ${3:\\$sum}: 1 } } }', link: getDocLink('$group', META_STAGE), }, @@ -137,33 +127,28 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ { value: '$lookup', meta: META_STAGE, - description: - 'The $lookup stage in the Aggregation Framework is used to perform left outer joins with other collections.', - snippet: - '{ $lookup: { from: "${1:collection}", localField: "${2:field}", foreignField: "${3:field}", as: "${4:result}" } }', + description: 'The $lookup stage in the Aggregation Framework is used to perform left outer joins with other collections.', + snippet: '{ $lookup: { from: "${1:collection}", localField: "${2:field}", foreignField: "${3:field}", as: "${4:result}" } }', link: getDocLink('$lookup', META_STAGE), }, { value: '$match', meta: META_STAGE, - description: - 'The $match stage in the aggregation pipeline is used to filter documents that match a specified condition.', + description: 'The $match stage in the aggregation pipeline is used to filter documents that match a specified condition.', snippet: '{ $match: { ${1:query} } }', link: getDocLink('$match', META_STAGE), }, { value: '$merge', meta: META_STAGE, - description: - 'The $merge stage in an aggregation pipeline writes the results of the aggregation to a specified collection.', + description: 'The $merge stage in an aggregation pipeline writes the results of the aggregation to a specified collection.', snippet: '{ $merge: { into: "${1:collection}" } }', link: getDocLink('$merge', META_STAGE), }, { value: '$out', meta: META_STAGE, - description: - 'The `$out` stage in an aggregation pipeline writes the resulting documents to a specified collection.', + description: 'The `$out` stage in an aggregation pipeline writes the resulting documents to a specified collection.', snippet: '{ $out: "${1:collection}" }', link: getDocLink('$out', META_STAGE), }, @@ -177,8 +162,7 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ value: '$redact', meta: META_STAGE, description: 'Filters the content of the documents based on access rights.', - snippet: - '{ $redact: { \\$cond: { if: { ${1:expression} }, then: "${2:\\$\\$DESCEND}", else: "${3:\\$\\$PRUNE}" } } }', + snippet: '{ $redact: { \\$cond: { if: { ${1:expression} }, then: "${2:\\$\\$DESCEND}", else: "${3:\\$\\$PRUNE}" } } }', link: getDocLink('$redact', META_STAGE), }, { @@ -190,8 +174,7 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ { value: '$replaceWith', meta: META_STAGE, - description: - 'The $replaceWith operator in Azure DocumentDB returns a document after replacing a document with the specified document', + description: 'The $replaceWith operator in Azure DocumentDB returns a document after replacing a document with the specified document', snippet: '{ $replaceWith: "${1:\\$field}" }', link: getDocLink('$replaceWith', META_STAGE), }, @@ -224,32 +207,27 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ { value: '$setWindowFields', meta: META_STAGE, - description: - 'Adds computed fields to documents using window functions over a specified partition and sort order.', - snippet: - '{ $setWindowFields: { partitionBy: "${1:\\$field}", sortBy: { ${2:field}: ${3:1} }, output: { ${4:newField}: { ${5:windowFunc} } } } }', + description: 'Adds computed fields to documents using window functions over a specified partition and sort order.', + snippet: '{ $setWindowFields: { partitionBy: "${1:\\$field}", sortBy: { ${2:field}: ${3:1} }, output: { ${4:newField}: { ${5:windowFunc} } } } }', }, { value: '$skip', meta: META_STAGE, - description: - 'The $skip stage in the aggregation pipeline is used to skip a specified number of documents from the input and pass the remaining documents to the next stage in the pipeline.', + description: 'The $skip stage in the aggregation pipeline is used to skip a specified number of documents from the input and pass the remaining documents to the next stage in the pipeline.', snippet: '{ $skip: ${1:number} }', link: getDocLink('$skip', META_STAGE), }, { value: '$sort', meta: META_STAGE, - description: - 'The $sort stage in the aggregation pipeline is used to order the documents in the pipeline by a specified field or fields.', + description: 'The $sort stage in the aggregation pipeline is used to order the documents in the pipeline by a specified field or fields.', snippet: '{ $sort: { ${1:field}: ${2:1} } }', link: getDocLink('$sort', META_STAGE), }, { value: '$sortByCount', meta: META_STAGE, - description: - 'The $sortByCount stage in the aggregation pipeline is used to group documents by a specified expression and then sort the count of documents in each group in descending order.', + description: 'The $sortByCount stage in the aggregation pipeline is used to group documents by a specified expression and then sort the count of documents in each group in descending order.', snippet: '{ $sortByCount: "${1:\\$field}" }', link: getDocLink('$sortByCount', META_STAGE), }, @@ -269,8 +247,7 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ { value: '$unwind', meta: META_STAGE, - description: - 'The $unwind stage in the aggregation framework is used to deconstruct an array field from the input documents to output a document for each element.', + description: 'The $unwind stage in the aggregation framework is used to deconstruct an array field from the input documents to output a document for each element.', snippet: '{ $unwind: "${1:\\$arrayField}" }', link: getDocLink('$unwind', META_STAGE), }, @@ -286,4 +263,6 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ // Registration // --------------------------------------------------------------------------- -registerOperators([...aggregationPipelineStages]); +registerOperators([ + ...aggregationPipelineStages, +]); diff --git a/packages/documentdb-constants/src/systemVariables.ts b/packages/documentdb-constants/src/systemVariables.ts index 4a404f7bb..68fc8e6e5 100644 --- a/packages/documentdb-constants/src/systemVariables.ts +++ b/packages/documentdb-constants/src/systemVariables.ts @@ -12,9 +12,9 @@ // // To change operator data, edit the overrides/snippets files and re-run the generator. -import { registerOperators } from './getFilteredCompletions'; -import { META_VARIABLE } from './metaTags'; import { type OperatorEntry } from './types'; +import { META_VARIABLE } from './metaTags'; +import { registerOperators } from './getFilteredCompletions'; // --------------------------------------------------------------------------- // Variables in Aggregation Expressions @@ -24,44 +24,37 @@ const systemVariables: readonly OperatorEntry[] = [ { value: '$$NOW', meta: META_VARIABLE, - description: - 'Returns the current datetime as a Date object. Constant throughout a single aggregation pipeline.', + description: 'Returns the current datetime as a Date object. Constant throughout a single aggregation pipeline.', }, { value: '$$ROOT', meta: META_VARIABLE, - description: - 'References the root document — the top-level document currently being processed in the pipeline stage.', + description: 'References the root document — the top-level document currently being processed in the pipeline stage.', }, { value: '$$REMOVE', meta: META_VARIABLE, - description: - 'Removes a field from the output document. Used with $project or $addFields to conditionally exclude fields.', + description: 'Removes a field from the output document. Used with $project or $addFields to conditionally exclude fields.', }, { value: '$$CURRENT', meta: META_VARIABLE, - description: - 'References the current document in the pipeline stage. Equivalent to $$ROOT at the start of the pipeline.', + description: 'References the current document in the pipeline stage. Equivalent to $$ROOT at the start of the pipeline.', }, { value: '$$DESCEND', meta: META_VARIABLE, - description: - 'Used with $redact. Returns the document fields at the current level and continues descending into subdocuments.', + description: 'Used with $redact. Returns the document fields at the current level and continues descending into subdocuments.', }, { value: '$$PRUNE', meta: META_VARIABLE, - description: - 'Used with $redact. Excludes all fields at the current document level and stops descending into subdocuments.', + description: 'Used with $redact. Excludes all fields at the current document level and stops descending into subdocuments.', }, { value: '$$KEEP', meta: META_VARIABLE, - description: - 'Used with $redact. Keeps all fields at the current document level without further descending into subdocuments.', + description: 'Used with $redact. Keeps all fields at the current document level without further descending into subdocuments.', }, ]; @@ -69,4 +62,6 @@ const systemVariables: readonly OperatorEntry[] = [ // Registration // --------------------------------------------------------------------------- -registerOperators([...systemVariables]); +registerOperators([ + ...systemVariables, +]); diff --git a/packages/documentdb-constants/src/updateOperators.ts b/packages/documentdb-constants/src/updateOperators.ts index c02ef9ce7..883b3f2a0 100644 --- a/packages/documentdb-constants/src/updateOperators.ts +++ b/packages/documentdb-constants/src/updateOperators.ts @@ -12,10 +12,12 @@ // // To change operator data, edit the overrides/snippets files and re-run the generator. +import { type OperatorEntry } from './types'; +import { META_UPDATE_ARRAY, + META_UPDATE_BITWISE, + META_UPDATE_FIELD } from './metaTags'; import { getDocLink } from './docLinks'; import { registerOperators } from './getFilteredCompletions'; -import { META_UPDATE_ARRAY, META_UPDATE_BITWISE, META_UPDATE_FIELD } from './metaTags'; -import { type OperatorEntry } from './types'; // --------------------------------------------------------------------------- // Field Update Operators @@ -25,8 +27,7 @@ const fieldUpdateOperators: readonly OperatorEntry[] = [ { value: '$currentDate', meta: META_UPDATE_FIELD, - description: - 'The $currentDate operator sets the value of a field to the current date, either as a Date or a timestamp.', + description: 'The $currentDate operator sets the value of a field to the current date, either as a Date or a timestamp.', snippet: '{ $currentDate: { "${1:field}": true } }', link: getDocLink('$currentDate', META_UPDATE_FIELD), }, @@ -42,14 +43,14 @@ const fieldUpdateOperators: readonly OperatorEntry[] = [ meta: META_UPDATE_FIELD, description: 'Retrieves the minimum value for a specified field', snippet: '{ $min: { "${1:field}": ${2:value} } }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$min', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$min', // inferred from another category }, { value: '$max', meta: META_UPDATE_FIELD, description: 'The $max operator returns the maximum value from a set of input values.', snippet: '{ $max: { "${1:field}": ${2:value} } }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$max', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$max', // inferred from another category }, { value: '$mul', @@ -70,13 +71,12 @@ const fieldUpdateOperators: readonly OperatorEntry[] = [ meta: META_UPDATE_FIELD, description: 'The $set operator in Azure DocumentDB updates or creates a new field with a specified value', snippet: '{ $set: { "${1:field}": ${2:value} } }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$set', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$set', // inferred from another category }, { value: '$setOnInsert', meta: META_UPDATE_FIELD, - description: - 'The $setOnInsert operator sets field values only when an upsert operation results in an insert of a new document.', + description: 'The $setOnInsert operator sets field values only when an upsert operation results in an insert of a new document.', snippet: '{ $setOnInsert: { "${1:field}": ${2:value} } }', link: getDocLink('$setOnInsert', META_UPDATE_FIELD), }, @@ -85,10 +85,11 @@ const fieldUpdateOperators: readonly OperatorEntry[] = [ meta: META_UPDATE_FIELD, description: 'The $unset stage in the aggregation pipeline is used to remove specified fields from documents.', snippet: '{ $unset: { "${1:field}": ${2:value} } }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$unset', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$unset', // inferred from another category }, ]; + // --------------------------------------------------------------------------- // Array Update Operators // --------------------------------------------------------------------------- @@ -97,8 +98,7 @@ const arrayUpdateOperators: readonly OperatorEntry[] = [ { value: '$', meta: META_UPDATE_ARRAY, - description: - 'The $ positional operator identifies an element in an array to update without explicitly specifying the position of the element in the array.', + description: 'The $ positional operator identifies an element in an array to update without explicitly specifying the position of the element in the array.', link: getDocLink('$', META_UPDATE_ARRAY), }, { @@ -109,14 +109,12 @@ const arrayUpdateOperators: readonly OperatorEntry[] = [ { value: '$[identifier]', meta: META_UPDATE_ARRAY, - description: - 'Filtered positional operator. Acts as a placeholder to update elements that match an arrayFilters condition.', + description: 'Filtered positional operator. Acts as a placeholder to update elements that match an arrayFilters condition.', }, { value: '$addToSet', meta: META_UPDATE_ARRAY, - description: - "The addToSet operator adds elements to an array if they don't already exist, while ensuring uniqueness of elements within the set.", + description: 'The addToSet operator adds elements to an array if they don\'t already exist, while ensuring uniqueness of elements within the set.', snippet: '{ $addToSet: { "${1:field}": ${2:value} } }', link: getDocLink('$addToSet', META_UPDATE_ARRAY), }, @@ -151,16 +149,14 @@ const arrayUpdateOperators: readonly OperatorEntry[] = [ { value: '$each', meta: META_UPDATE_ARRAY, - description: - 'The $each operator is used within an `$addToSet`or`$push` operation to add multiple elements to an array field in a single update operation.', + description: 'The $each operator is used within an `$addToSet`or`$push` operation to add multiple elements to an array field in a single update operation.', snippet: '{ $each: [${1:values}] }', link: getDocLink('$each', META_UPDATE_ARRAY), }, { value: '$position', meta: META_UPDATE_ARRAY, - description: - 'Specifies the position in the array at which the $push operator inserts elements. Used with $each.', + description: 'Specifies the position in the array at which the $push operator inserts elements. Used with $each.', snippet: '{ $position: ${1:index} }', }, { @@ -168,18 +164,18 @@ const arrayUpdateOperators: readonly OperatorEntry[] = [ meta: META_UPDATE_ARRAY, description: 'The $slice operator returns a subset of an array from any element onwards in the array.', snippet: '{ $slice: ${1:number} }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$slice', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-expression/$slice', // inferred from another category }, { value: '$sort', meta: META_UPDATE_ARRAY, - description: - 'The $sort stage in the aggregation pipeline is used to order the documents in the pipeline by a specified field or fields.', + description: 'The $sort stage in the aggregation pipeline is used to order the documents in the pipeline by a specified field or fields.', snippet: '{ $sort: { "${1:field}": ${2:1} } }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$sort', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$sort', // inferred from another category }, ]; + // --------------------------------------------------------------------------- // Bitwise Update Operators // --------------------------------------------------------------------------- @@ -198,4 +194,8 @@ const bitwiseUpdateOperators: readonly OperatorEntry[] = [ // Registration // --------------------------------------------------------------------------- -registerOperators([...fieldUpdateOperators, ...arrayUpdateOperators, ...bitwiseUpdateOperators]); +registerOperators([ + ...fieldUpdateOperators, + ...arrayUpdateOperators, + ...bitwiseUpdateOperators, +]); diff --git a/packages/documentdb-constants/src/windowOperators.ts b/packages/documentdb-constants/src/windowOperators.ts index 05481809f..cb15c76af 100644 --- a/packages/documentdb-constants/src/windowOperators.ts +++ b/packages/documentdb-constants/src/windowOperators.ts @@ -12,10 +12,10 @@ // // To change operator data, edit the overrides/snippets files and re-run the generator. +import { type OperatorEntry } from './types'; +import { META_WINDOW } from './metaTags'; import { getDocLink } from './docLinks'; import { registerOperators } from './getFilteredCompletions'; -import { META_WINDOW } from './metaTags'; -import { type OperatorEntry } from './types'; // --------------------------------------------------------------------------- // Window Operators @@ -27,73 +27,70 @@ const windowOperators: readonly OperatorEntry[] = [ meta: META_WINDOW, description: 'The $sum operator calculates the sum of the values of a field based on a filtering criteria', snippet: '{ $sum: "${1:\\$field}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$sum', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$sum', // inferred from another category }, { value: '$push', meta: META_WINDOW, description: 'The $push operator adds a specified value to an array within a document.', snippet: '{ $push: "${1:\\$field}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$push', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$push', // inferred from another category }, { value: '$addToSet', meta: META_WINDOW, - description: - "The addToSet operator adds elements to an array if they don't already exist, while ensuring uniqueness of elements within the set.", + description: 'The addToSet operator adds elements to an array if they don\'t already exist, while ensuring uniqueness of elements within the set.', snippet: '{ $addToSet: "${1:\\$field}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$addtoset', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$addtoset', // inferred from another category }, { value: '$count', meta: META_WINDOW, - description: - 'The `$count` operator is used to count the number of documents that match a query filtering criteria.', + description: 'The `$count` operator is used to count the number of documents that match a query filtering criteria.', snippet: '{ $count: "${1:\\$field}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$count', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$count', // inferred from another category }, { value: '$max', meta: META_WINDOW, description: 'The $max operator returns the maximum value from a set of input values.', snippet: '{ $max: "${1:\\$field}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$max', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$max', // inferred from another category }, { value: '$min', meta: META_WINDOW, description: 'Retrieves the minimum value for a specified field', snippet: '{ $min: "${1:\\$field}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$min', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$min', // inferred from another category }, { value: '$avg', meta: META_WINDOW, description: 'Computes the average of numeric values for documents in a group, bucket, or window.', snippet: '{ $avg: "${1:\\$field}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$avg', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$avg', // inferred from another category }, { value: '$stdDevPop', meta: META_WINDOW, description: 'The $stddevpop operator calculates the standard deviation of the specified values', snippet: '{ $stdDevPop: "${1:\\$field}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$stddevpop', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$stddevpop', // inferred from another category }, { value: '$bottom', meta: META_WINDOW, - description: - "The $bottom operator returns the last document from the query's result set sorted by one or more fields", + description: 'The $bottom operator returns the last document from the query\'s result set sorted by one or more fields', snippet: '{ $bottom: "${1:\\$field}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$bottom', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$bottom', // inferred from another category }, { value: '$bottomN', meta: META_WINDOW, description: 'The $bottomN operator returns the last N documents from the result sorted by one or more fields', snippet: '{ $bottomN: "${1:\\$field}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$bottomn', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$bottomn', // inferred from another category }, { value: '$covariancePop', @@ -112,47 +109,42 @@ const windowOperators: readonly OperatorEntry[] = [ { value: '$denseRank', meta: META_WINDOW, - description: - 'The $denseRank operator assigns and returns a positional ranking for each document within a partition based on a specified sort order', + description: 'The $denseRank operator assigns and returns a positional ranking for each document within a partition based on a specified sort order', snippet: '{ $denseRank: {} }', link: getDocLink('$denseRank', META_WINDOW), }, { value: '$derivative', meta: META_WINDOW, - description: - 'The $derivative operator calculates the average rate of change of the value of a field within a specified window.', + description: 'The $derivative operator calculates the average rate of change of the value of a field within a specified window.', snippet: '{ $derivative: { input: "${1:\\$field}", unit: "${2:hour}" } }', link: getDocLink('$derivative', META_WINDOW), }, { value: '$documentNumber', meta: META_WINDOW, - description: - 'The $documentNumber operator assigns and returns a position for each document within a partition based on a specified sort order', + description: 'The $documentNumber operator assigns and returns a position for each document within a partition based on a specified sort order', snippet: '{ $documentNumber: {} }', link: getDocLink('$documentNumber', META_WINDOW), }, { value: '$expMovingAvg', meta: META_WINDOW, - description: - 'The $expMovingAvg operator calculates the moving average of a field based on the specified number of documents to hold the highest weight', + description: 'The $expMovingAvg operator calculates the moving average of a field based on the specified number of documents to hold the highest weight', snippet: '{ $expMovingAvg: { input: "${1:\\$field}", N: ${2:number} } }', link: getDocLink('$expMovingAvg', META_WINDOW), }, { value: '$first', meta: META_WINDOW, - description: "The $first operator returns the first value in a group according to the group's sorting order.", + description: 'The $first operator returns the first value in a group according to the group\'s sorting order.', snippet: '{ $first: "${1:\\$field}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$first', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$first', // inferred from another category }, { value: '$integral', meta: META_WINDOW, - description: - 'The $integral operator calculates the area under a curve with the specified range of documents forming the adjacent documents for the calculation.', + description: 'The $integral operator calculates the area under a curve with the specified range of documents forming the adjacent documents for the calculation.', snippet: '{ $integral: { input: "${1:\\$field}", unit: "${2:hour}" } }', link: getDocLink('$integral', META_WINDOW), }, @@ -161,21 +153,19 @@ const windowOperators: readonly OperatorEntry[] = [ meta: META_WINDOW, description: 'The $last operator returns the last document from the result sorted by one or more fields', snippet: '{ $last: "${1:\\$field}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$last', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$last', // inferred from another category }, { value: '$linearFill', meta: META_WINDOW, - description: - 'The $linearFill operator interpolates missing values in a sequence of documents using linear interpolation.', + description: 'The $linearFill operator interpolates missing values in a sequence of documents using linear interpolation.', snippet: '{ $linearFill: "${1:\\$field}" }', link: getDocLink('$linearFill', META_WINDOW), }, { value: '$locf', meta: META_WINDOW, - description: - 'The $locf operator propagates the last observed non-null value forward within a partition in a windowed query.', + description: 'The $locf operator propagates the last observed non-null value forward within a partition in a windowed query.', snippet: '{ $locf: "${1:\\$field}" }', link: getDocLink('$locf', META_WINDOW), }, @@ -203,24 +193,23 @@ const windowOperators: readonly OperatorEntry[] = [ { value: '$stdDevSamp', meta: META_WINDOW, - description: - 'The $stddevsamp operator calculates the standard deviation of a specified sample of values and not the entire population', + description: 'The $stddevsamp operator calculates the standard deviation of a specified sample of values and not the entire population', snippet: '{ $stdDevSamp: "${1:\\$field}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$stddevsamp', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$stddevsamp', // inferred from another category }, { value: '$top', meta: META_WINDOW, description: 'The $top operator returns the first document from the result set sorted by one or more fields', snippet: '{ $top: "${1:\\$field}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$top', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$top', // inferred from another category }, { value: '$topN', meta: META_WINDOW, description: 'The $topN operator returns the first N documents from the result sorted by one or more fields', snippet: '{ $topN: "${1:\\$field}" }', - link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$topn', + link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$topn', // inferred from another category }, ]; @@ -228,4 +217,6 @@ const windowOperators: readonly OperatorEntry[] = [ // Registration // --------------------------------------------------------------------------- -registerOperators([...windowOperators]); +registerOperators([ + ...windowOperators, +]); From 1b9da3e485d80c7633f8ce066a665d8d08af4d13 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Fri, 20 Feb 2026 16:08:28 +0000 Subject: [PATCH 036/128] Refactor query operators and stages for improved readability and consistency - Updated descriptions in query operators to ensure consistent formatting and clarity. - Reorganized imports in query operators, stages, system variables, update operators, and window operators for better structure. - Enhanced documentation links for various operators to provide clearer guidance. - Removed unnecessary whitespace and ensured consistent snippet formatting across all operator files. --- packages/documentdb-constants/package.json | 2 +- .../scripts/generate-from-reference.ts | 8 ++ .../documentdb-constants/src/accumulators.ts | 28 ++-- .../src/expressionOperators.ts | 132 ++++++++++-------- .../src/queryOperators.ts | 117 ++++++++++------ packages/documentdb-constants/src/stages.ts | 77 ++++++---- .../src/systemVariables.ts | 29 ++-- .../src/updateOperators.ts | 38 ++--- .../src/windowOperators.ts | 43 +++--- 9 files changed, 283 insertions(+), 191 deletions(-) diff --git a/packages/documentdb-constants/package.json b/packages/documentdb-constants/package.json index b9719e618..1d178e8c7 100644 --- a/packages/documentdb-constants/package.json +++ b/packages/documentdb-constants/package.json @@ -13,7 +13,7 @@ "test": "jest --config jest.config.js", "prettier-fix": "prettier -w \"(scripts|src)/**/*.@(js|ts|jsx|tsx|json|md)\" \"./*.@(js|ts|jsx|tsx|json|md)\"", "scrape": "ts-node scripts/scrape-operator-docs.ts && prettier --write resources/scraped/operator-reference.md", - "generate": "ts-node scripts/generate-from-reference.ts && prettier --write \"src/queryOperators.ts\" \"src/updateOperators.ts\" \"src/expressionOperators.ts\" \"src/accumulators.ts\" \"src/windowOperators.ts\" \"src/stages.ts\" \"src/systemVariables.ts\"", + "generate": "ts-node scripts/generate-from-reference.ts", "evaluate": "ts-node scripts/evaluate-overrides.ts" }, "repository": { diff --git a/packages/documentdb-constants/scripts/generate-from-reference.ts b/packages/documentdb-constants/scripts/generate-from-reference.ts index df28ad924..b1a9de6a9 100644 --- a/packages/documentdb-constants/scripts/generate-from-reference.ts +++ b/packages/documentdb-constants/scripts/generate-from-reference.ts @@ -32,6 +32,7 @@ * files instead. */ +import { execSync } from 'child_process'; import * as fs from 'fs'; import * as path from 'path'; import { getDocLink } from '../src/docLinks'; @@ -825,6 +826,13 @@ function main(): void { fs.writeFileSync(filePath, fileContent, 'utf-8'); } + // Format generated files with Prettier + const generatedFiles = [...fileGroups.keys()].map((f) => path.join(srcDir, `${f}.ts`)); + console.log('\n🎨 Formatting generated files with Prettier...'); + execSync(`npx prettier --write ${generatedFiles.map((f) => `"${f}"`).join(' ')}`, { + stdio: 'inherit', + }); + console.log('\n✅ Done! Generated files:'); for (const [fileName, specs] of fileGroups) { const count = specs.reduce((n, s) => n + s.operators.length, 0); diff --git a/packages/documentdb-constants/src/accumulators.ts b/packages/documentdb-constants/src/accumulators.ts index 5a3db91fc..4b7c6694a 100644 --- a/packages/documentdb-constants/src/accumulators.ts +++ b/packages/documentdb-constants/src/accumulators.ts @@ -12,10 +12,10 @@ // // To change operator data, edit the overrides/snippets files and re-run the generator. -import { type OperatorEntry } from './types'; -import { META_ACCUMULATOR } from './metaTags'; import { getDocLink } from './docLinks'; import { registerOperators } from './getFilteredCompletions'; +import { META_ACCUMULATOR } from './metaTags'; +import { type OperatorEntry } from './types'; // --------------------------------------------------------------------------- // Accumulators ($group, $bucket, $bucketAuto, $setWindowFields) @@ -25,7 +25,8 @@ const groupAccumulators: readonly OperatorEntry[] = [ { value: '$addToSet', meta: META_ACCUMULATOR, - description: 'The addToSet operator adds elements to an array if they don\'t already exist, while ensuring uniqueness of elements within the set.', + description: + "The addToSet operator adds elements to an array if they don't already exist, while ensuring uniqueness of elements within the set.", snippet: '{ $addToSet: "${1:\\$field}" }', link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$addtoset', // inferred from another category }, @@ -39,7 +40,8 @@ const groupAccumulators: readonly OperatorEntry[] = [ { value: '$bottom', meta: META_ACCUMULATOR, - description: 'The $bottom operator returns the last document from the query\'s result set sorted by one or more fields', + description: + "The $bottom operator returns the last document from the query's result set sorted by one or more fields", snippet: '{ $bottom: { sortBy: { ${1:field}: ${2:1} }, output: "${3:\\$field}" } }', link: getDocLink('$bottom', META_ACCUMULATOR), }, @@ -53,21 +55,23 @@ const groupAccumulators: readonly OperatorEntry[] = [ { value: '$count', meta: META_ACCUMULATOR, - description: 'The `$count` operator is used to count the number of documents that match a query filtering criteria.', + description: + 'The `$count` operator is used to count the number of documents that match a query filtering criteria.', snippet: '{ $count: {} }', link: getDocLink('$count', META_ACCUMULATOR), }, { value: '$first', meta: META_ACCUMULATOR, - description: 'The $first operator returns the first value in a group according to the group\'s sorting order.', + description: "The $first operator returns the first value in a group according to the group's sorting order.", snippet: '{ $first: "${1:\\$field}" }', link: getDocLink('$first', META_ACCUMULATOR), }, { value: '$firstN', meta: META_ACCUMULATOR, - description: 'The $firstN operator sorts documents on one or more fields specified by the query and returns the first N document matching the filtering criteria', + description: + 'The $firstN operator sorts documents on one or more fields specified by the query and returns the first N document matching the filtering criteria', snippet: '{ $firstN: { input: "${1:\\$field}", n: ${2:number} } }', link: getDocLink('$firstN', META_ACCUMULATOR), }, @@ -123,7 +127,8 @@ const groupAccumulators: readonly OperatorEntry[] = [ { value: '$percentile', meta: META_ACCUMULATOR, - description: 'The $percentile operator calculates the percentile of numerical values that match a filtering criteria', + description: + 'The $percentile operator calculates the percentile of numerical values that match a filtering criteria', snippet: '{ $percentile: { input: "${1:\\$field}", p: [${2:0.5}], method: "approximate" } }', link: getDocLink('$percentile', META_ACCUMULATOR), }, @@ -144,7 +149,8 @@ const groupAccumulators: readonly OperatorEntry[] = [ { value: '$stdDevSamp', meta: META_ACCUMULATOR, - description: 'The $stddevsamp operator calculates the standard deviation of a specified sample of values and not the entire population', + description: + 'The $stddevsamp operator calculates the standard deviation of a specified sample of values and not the entire population', snippet: '{ $stdDevSamp: "${1:\\$field}" }', link: getDocLink('$stdDevSamp', META_ACCUMULATOR), }, @@ -175,6 +181,4 @@ const groupAccumulators: readonly OperatorEntry[] = [ // Registration // --------------------------------------------------------------------------- -registerOperators([ - ...groupAccumulators, -]); +registerOperators([...groupAccumulators]); diff --git a/packages/documentdb-constants/src/expressionOperators.ts b/packages/documentdb-constants/src/expressionOperators.ts index 08c16f25a..77b197b85 100644 --- a/packages/documentdb-constants/src/expressionOperators.ts +++ b/packages/documentdb-constants/src/expressionOperators.ts @@ -12,8 +12,10 @@ // // To change operator data, edit the overrides/snippets files and re-run the generator. -import { type OperatorEntry } from './types'; -import { META_EXPR_ARITH, +import { getDocLink } from './docLinks'; +import { registerOperators } from './getFilteredCompletions'; +import { + META_EXPR_ARITH, META_EXPR_ARRAY, META_EXPR_BITWISE, META_EXPR_BOOL, @@ -29,9 +31,9 @@ import { META_EXPR_ARITH, META_EXPR_TIMESTAMP, META_EXPR_TRIG, META_EXPR_TYPE, - META_EXPR_VARIABLE } from './metaTags'; -import { getDocLink } from './docLinks'; -import { registerOperators } from './getFilteredCompletions'; + META_EXPR_VARIABLE, +} from './metaTags'; +import { type OperatorEntry } from './types'; // --------------------------------------------------------------------------- // Arithmetic Expression Operators @@ -104,7 +106,8 @@ const arithmeticExpressionOperators: readonly OperatorEntry[] = [ { value: '$mod', meta: META_EXPR_ARITH, - description: 'The $mod operator performs a modulo operation on the value of a field and selects documents with a specified result.', + description: + 'The $mod operator performs a modulo operation on the value of a field and selects documents with a specified result.', snippet: '{ $mod: ["${1:\\$field1}", "${2:\\$field2}"] }', link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/evaluation-query/$mod', // inferred from another category }, @@ -118,7 +121,8 @@ const arithmeticExpressionOperators: readonly OperatorEntry[] = [ { value: '$pow', meta: META_EXPR_ARITH, - description: 'The `$pow` operator calculates the value of a numerical value raised to the power of a specified exponent.', + description: + 'The `$pow` operator calculates the value of a numerical value raised to the power of a specified exponent.', snippet: '{ $pow: ["${1:\\$field1}", "${2:\\$field2}"] }', link: getDocLink('$pow', META_EXPR_ARITH), }, @@ -152,7 +156,6 @@ const arithmeticExpressionOperators: readonly OperatorEntry[] = [ }, ]; - // --------------------------------------------------------------------------- // Array Expression Operators // --------------------------------------------------------------------------- @@ -189,7 +192,8 @@ const arrayExpressionOperators: readonly OperatorEntry[] = [ { value: '$firstN', meta: META_EXPR_ARRAY, - description: 'The $firstN operator sorts documents on one or more fields specified by the query and returns the first N document matching the filtering criteria', + description: + 'The $firstN operator sorts documents on one or more fields specified by the query and returns the first N document matching the filtering criteria', snippet: '{ $firstN: { input: "${1:\\$array}", n: ${2:number} } }', link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$firstn', // inferred from another category }, @@ -203,7 +207,8 @@ const arrayExpressionOperators: readonly OperatorEntry[] = [ { value: '$indexOfArray', meta: META_EXPR_ARRAY, - description: 'The $indexOfArray operator is used to search for an element in an array and return the index of the first occurrence of the element.', + description: + 'The $indexOfArray operator is used to search for an element in an array and return the index of the first occurrence of the element.', snippet: '{ $indexOfArray: ["${1:\\$array}", "${2:value}"] }', link: getDocLink('$indexOfArray', META_EXPR_ARRAY), }, @@ -259,7 +264,8 @@ const arrayExpressionOperators: readonly OperatorEntry[] = [ { value: '$reduce', meta: META_EXPR_ARRAY, - description: 'The $reduce operator applies an expression to each element in an array & accumulate result as single value.', + description: + 'The $reduce operator applies an expression to each element in an array & accumulate result as single value.', snippet: '{ $reduce: { input: "${1:\\$array}", initialValue: ${2:0}, in: { ${3:expression} } } }', link: getDocLink('$reduce', META_EXPR_ARRAY), }, @@ -273,7 +279,8 @@ const arrayExpressionOperators: readonly OperatorEntry[] = [ { value: '$size', meta: META_EXPR_ARRAY, - description: 'The $size operator is used to query documents where an array field has a specified number of elements.', + description: + 'The $size operator is used to query documents where an array field has a specified number of elements.', snippet: '{ $size: "${1:\\$array}" }', link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-query/$size', // inferred from another category }, @@ -300,7 +307,6 @@ const arrayExpressionOperators: readonly OperatorEntry[] = [ }, ]; - // --------------------------------------------------------------------------- // Bitwise Operators // --------------------------------------------------------------------------- @@ -309,21 +315,24 @@ const bitwiseOperators: readonly OperatorEntry[] = [ { value: '$bitAnd', meta: META_EXPR_BITWISE, - description: 'The $bitAnd operator performs a bitwise AND operation on integer values and returns the result as an integer.', + description: + 'The $bitAnd operator performs a bitwise AND operation on integer values and returns the result as an integer.', snippet: '{ $bitAnd: [${1:value1}, ${2:value2}] }', link: getDocLink('$bitAnd', META_EXPR_BITWISE), }, { value: '$bitNot', meta: META_EXPR_BITWISE, - description: 'The $bitNot operator performs a bitwise NOT operation on integer values and returns the result as an integer.', + description: + 'The $bitNot operator performs a bitwise NOT operation on integer values and returns the result as an integer.', snippet: '{ $bitNot: "${1:\\$field}" }', link: getDocLink('$bitNot', META_EXPR_BITWISE), }, { value: '$bitOr', meta: META_EXPR_BITWISE, - description: 'The $bitOr operator performs a bitwise OR operation on integer values and returns the result as an integer.', + description: + 'The $bitOr operator performs a bitwise OR operation on integer values and returns the result as an integer.', snippet: '{ $bitOr: [${1:value1}, ${2:value2}] }', link: getDocLink('$bitOr', META_EXPR_BITWISE), }, @@ -336,7 +345,6 @@ const bitwiseOperators: readonly OperatorEntry[] = [ }, ]; - // --------------------------------------------------------------------------- // Boolean Expression Operators // --------------------------------------------------------------------------- @@ -345,27 +353,29 @@ const booleanExpressionOperators: readonly OperatorEntry[] = [ { value: '$and', meta: META_EXPR_BOOL, - description: 'The $and operator joins multiple query clauses and returns documents that match all specified conditions.', + description: + 'The $and operator joins multiple query clauses and returns documents that match all specified conditions.', snippet: '{ $and: ["${1:expression1}", "${2:expression2}"] }', link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/logical-query/$and', // inferred from another category }, { value: '$not', meta: META_EXPR_BOOL, - description: 'The $not operator performs a logical NOT operation on a specified expression, selecting documents that don\'t match the expression.', + description: + "The $not operator performs a logical NOT operation on a specified expression, selecting documents that don't match the expression.", snippet: '{ $not: ["${1:expression}"] }', link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/logical-query/$not', // inferred from another category }, { value: '$or', meta: META_EXPR_BOOL, - description: 'The $or operator joins query clauses with a logical OR and returns documents that match at least one of the specified conditions.', + description: + 'The $or operator joins query clauses with a logical OR and returns documents that match at least one of the specified conditions.', snippet: '{ $or: ["${1:expression1}", "${2:expression2}"] }', link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/logical-query/$or', // inferred from another category }, ]; - // --------------------------------------------------------------------------- // Comparison Expression Operators // --------------------------------------------------------------------------- @@ -388,14 +398,16 @@ const comparisonExpressionOperators: readonly OperatorEntry[] = [ { value: '$gt', meta: META_EXPR_COMPARISON, - description: 'The $gt query operator retrieves documents where the value of a field is greater than a specified value', + description: + 'The $gt query operator retrieves documents where the value of a field is greater than a specified value', snippet: '{ $gt: ["${1:\\$field1}", "${2:\\$field2}"] }', link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$gt', // inferred from another category }, { value: '$gte', meta: META_EXPR_COMPARISON, - description: 'The $gte operator retrieves documents where the value of a field is greater than or equal to a specified value', + description: + 'The $gte operator retrieves documents where the value of a field is greater than or equal to a specified value', snippet: '{ $gte: ["${1:\\$field1}", "${2:\\$field2}"] }', link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$gte', // inferred from another category }, @@ -409,20 +421,20 @@ const comparisonExpressionOperators: readonly OperatorEntry[] = [ { value: '$lte', meta: META_EXPR_COMPARISON, - description: 'The $lte operator retrieves documents where the value of a field is less than or equal to a specified value', + description: + 'The $lte operator retrieves documents where the value of a field is less than or equal to a specified value', snippet: '{ $lte: ["${1:\\$field1}", "${2:\\$field2}"] }', link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$lte', // inferred from another category }, { value: '$ne', meta: META_EXPR_COMPARISON, - description: 'The $ne operator retrieves documents where the value of a field doesn\'t equal a specified value', + description: "The $ne operator retrieves documents where the value of a field doesn't equal a specified value", snippet: '{ $ne: ["${1:\\$field1}", "${2:\\$field2}"] }', link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-query/$ne', // inferred from another category }, ]; - // --------------------------------------------------------------------------- // Data Size Operators // --------------------------------------------------------------------------- @@ -444,7 +456,6 @@ const dataSizeOperators: readonly OperatorEntry[] = [ }, ]; - // --------------------------------------------------------------------------- // Date Expression Operators // --------------------------------------------------------------------------- @@ -460,7 +471,8 @@ const dateExpressionOperators: readonly OperatorEntry[] = [ { value: '$dateDiff', meta: META_EXPR_DATE, - description: 'The $dateDiff operator calculates the difference between two dates in various units such as years, months, days, etc.', + description: + 'The $dateDiff operator calculates the difference between two dates in various units such as years, months, days, etc.', snippet: '{ $dateDiff: { startDate: "${1:\\$startDate}", endDate: "${2:\\$endDate}", unit: "${3:day}" } }', link: getDocLink('$dateDiff', META_EXPR_DATE), }, @@ -488,7 +500,8 @@ const dateExpressionOperators: readonly OperatorEntry[] = [ { value: '$dateToParts', meta: META_EXPR_DATE, - description: 'The $dateToParts operator decomposes a date into its individual parts such as year, month, day, and more.', + description: + 'The $dateToParts operator decomposes a date into its individual parts such as year, month, day, and more.', snippet: '{ $dateToParts: { date: "${1:\\$dateField}" } }', link: getDocLink('$dateToParts', META_EXPR_DATE), }, @@ -537,21 +550,24 @@ const dateExpressionOperators: readonly OperatorEntry[] = [ { value: '$isoDayOfWeek', meta: META_EXPR_DATE, - description: 'The $isoDayOfWeek operator returns the weekday number in ISO 8601 format, ranging from 1 (Monday) to 7 (Sunday).', + description: + 'The $isoDayOfWeek operator returns the weekday number in ISO 8601 format, ranging from 1 (Monday) to 7 (Sunday).', snippet: '{ $isoDayOfWeek: "${1:\\$dateField}" }', link: getDocLink('$isoDayOfWeek', META_EXPR_DATE), }, { value: '$isoWeek', meta: META_EXPR_DATE, - description: 'The $isoWeek operator returns the week number of the year in ISO 8601 format, ranging from 1 to 53.', + description: + 'The $isoWeek operator returns the week number of the year in ISO 8601 format, ranging from 1 to 53.', snippet: '{ $isoWeek: "${1:\\$dateField}" }', link: getDocLink('$isoWeek', META_EXPR_DATE), }, { value: '$isoWeekYear', meta: META_EXPR_DATE, - description: 'The $isoWeekYear operator returns the year number in ISO 8601 format, which can differ from the calendar year for dates at the beginning or end of the year.', + description: + 'The $isoWeekYear operator returns the year number in ISO 8601 format, which can differ from the calendar year for dates at the beginning or end of the year.', snippet: '{ $isoWeekYear: "${1:\\$dateField}" }', link: getDocLink('$isoWeekYear', META_EXPR_DATE), }, @@ -606,7 +622,6 @@ const dateExpressionOperators: readonly OperatorEntry[] = [ }, ]; - // --------------------------------------------------------------------------- // Literal Expression Operator // --------------------------------------------------------------------------- @@ -615,13 +630,13 @@ const literalExpressionOperator: readonly OperatorEntry[] = [ { value: '$literal', meta: META_EXPR_LITERAL, - description: 'The $literal operator returns the specified value without parsing it as an expression, allowing literal values to be used in aggregation pipelines.', + description: + 'The $literal operator returns the specified value without parsing it as an expression, allowing literal values to be used in aggregation pipelines.', snippet: '{ $literal: ${1:value} }', link: getDocLink('$literal', META_EXPR_LITERAL), }, ]; - // --------------------------------------------------------------------------- // Miscellaneous Operators // --------------------------------------------------------------------------- @@ -644,13 +659,13 @@ const miscellaneousOperators: readonly OperatorEntry[] = [ { value: '$sampleRate', meta: META_EXPR_MISC, - description: 'The $sampleRate operator randomly samples documents from a collection based on a specified probability rate, useful for statistical analysis and testing.', + description: + 'The $sampleRate operator randomly samples documents from a collection based on a specified probability rate, useful for statistical analysis and testing.', snippet: '{ $sampleRate: ${1:0.5} }', link: getDocLink('$sampleRate', META_EXPR_MISC), }, ]; - // --------------------------------------------------------------------------- // Object Expression Operators // --------------------------------------------------------------------------- @@ -666,7 +681,8 @@ const objectExpressionOperators: readonly OperatorEntry[] = [ { value: '$objectToArray', meta: META_EXPR_OBJECT, - description: 'The objectToArray command is used to transform a document (object) into an array of key-value pairs.', + description: + 'The objectToArray command is used to transform a document (object) into an array of key-value pairs.', snippet: '{ $objectToArray: "${1:\\$object}" }', link: getDocLink('$objectToArray', META_EXPR_OBJECT), }, @@ -679,7 +695,6 @@ const objectExpressionOperators: readonly OperatorEntry[] = [ }, ]; - // --------------------------------------------------------------------------- // Set Expression Operators // --------------------------------------------------------------------------- @@ -695,14 +710,16 @@ const setExpressionOperators: readonly OperatorEntry[] = [ { value: '$anyElementTrue', meta: META_EXPR_SET, - description: 'The $anyElementTrue operator returns true if any element in an array evaluates to a value of true.', + description: + 'The $anyElementTrue operator returns true if any element in an array evaluates to a value of true.', snippet: '{ $anyElementTrue: ["${1:\\$array}"] }', link: getDocLink('$anyElementTrue', META_EXPR_SET), }, { value: '$setDifference', meta: META_EXPR_SET, - description: 'The $setDifference operator returns a set with elements that exist in one set but not in a second set.', + description: + 'The $setDifference operator returns a set with elements that exist in one set but not in a second set.', snippet: '{ $setDifference: ["${1:\\$set1}", "${2:\\$set2}"] }', link: getDocLink('$setDifference', META_EXPR_SET), }, @@ -730,13 +747,13 @@ const setExpressionOperators: readonly OperatorEntry[] = [ { value: '$setUnion', meta: META_EXPR_SET, - description: 'The $setUnion operator returns an array that contains all the unique elements from the input arrays.', + description: + 'The $setUnion operator returns an array that contains all the unique elements from the input arrays.', snippet: '{ $setUnion: ["${1:\\$set1}", "${2:\\$set2}"] }', link: getDocLink('$setUnion', META_EXPR_SET), }, ]; - // --------------------------------------------------------------------------- // String Expression Operators // --------------------------------------------------------------------------- @@ -843,19 +860,22 @@ const stringExpressionOperators: readonly OperatorEntry[] = [ { value: '$substr', meta: META_EXPR_STRING, - description: 'Returns a substring of a string, starting at a specified index for a specified length. Deprecated — use $substrBytes or $substrCP.', + description: + 'Returns a substring of a string, starting at a specified index for a specified length. Deprecated — use $substrBytes or $substrCP.', snippet: '{ $substr: ["${1:\\$string}", ${2:start}, ${3:length}] }', }, { value: '$substrBytes', meta: META_EXPR_STRING, - description: 'Returns a substring of a string by byte index, starting at a specified index for a specified number of bytes.', + description: + 'Returns a substring of a string by byte index, starting at a specified index for a specified number of bytes.', snippet: '{ $substrBytes: ["${1:\\$string}", ${2:start}, ${3:length}] }', }, { value: '$substrCP', meta: META_EXPR_STRING, - description: 'Returns a substring of a string by code point index, starting at a specified index for a specified number of code points.', + description: + 'Returns a substring of a string by code point index, starting at a specified index for a specified number of code points.', snippet: '{ $substrCP: ["${1:\\$string}", ${2:start}, ${3:length}] }', }, { @@ -885,7 +905,6 @@ const stringExpressionOperators: readonly OperatorEntry[] = [ }, ]; - // --------------------------------------------------------------------------- // Timestamp Expression Operators // --------------------------------------------------------------------------- @@ -907,7 +926,6 @@ const timestampExpressionOperators: readonly OperatorEntry[] = [ }, ]; - // --------------------------------------------------------------------------- // Trigonometry Expression Operators // --------------------------------------------------------------------------- @@ -1005,7 +1023,6 @@ const trigonometryExpressionOperators: readonly OperatorEntry[] = [ }, ]; - // --------------------------------------------------------------------------- // Type Expression Operators // --------------------------------------------------------------------------- @@ -1090,7 +1107,6 @@ const typeExpressionOperators: readonly OperatorEntry[] = [ }, ]; - // --------------------------------------------------------------------------- // Variable Expression Operators // --------------------------------------------------------------------------- @@ -1099,13 +1115,13 @@ const variableExpressionOperators: readonly OperatorEntry[] = [ { value: '$let', meta: META_EXPR_VARIABLE, - description: 'The $let operator allows defining variables for use in a specified expression, enabling complex calculations and reducing code repetition.', + description: + 'The $let operator allows defining variables for use in a specified expression, enabling complex calculations and reducing code repetition.', snippet: '{ $let: { vars: { ${1:var}: ${2:expression} }, in: ${3:expression} } }', link: getDocLink('$let', META_EXPR_VARIABLE), }, ]; - // --------------------------------------------------------------------------- // Conditional Expression Operators // --------------------------------------------------------------------------- @@ -1114,22 +1130,26 @@ const conditionalExpressionOperators: readonly OperatorEntry[] = [ { value: '$cond', meta: META_EXPR_CONDITIONAL, - description: 'The $cond operator is used to evaluate a condition and return one of two expressions based on the result.', + description: + 'The $cond operator is used to evaluate a condition and return one of two expressions based on the result.', snippet: '{ $cond: { if: { ${1:expression} }, then: ${2:trueValue}, else: ${3:falseValue} } }', link: getDocLink('$cond', META_EXPR_CONDITIONAL), }, { value: '$ifNull', meta: META_EXPR_CONDITIONAL, - description: 'The $ifNull operator is used to evaluate an expression and return a specified value if the expression resolves to null.', + description: + 'The $ifNull operator is used to evaluate an expression and return a specified value if the expression resolves to null.', snippet: '{ $ifNull: ["${1:\\$field}", ${2:replacement}] }', link: getDocLink('$ifNull', META_EXPR_CONDITIONAL), }, { value: '$switch', meta: META_EXPR_CONDITIONAL, - description: 'The $switch operator is used to evaluate a series of conditions and return a value based on the first condition that evaluates to true.', - snippet: '{ $switch: { branches: [{ case: { ${1:expression} }, then: ${2:value} }], default: ${3:defaultValue} } }', + description: + 'The $switch operator is used to evaluate a series of conditions and return a value based on the first condition that evaluates to true.', + snippet: + '{ $switch: { branches: [{ case: { ${1:expression} }, then: ${2:value} }], default: ${3:defaultValue} } }', link: getDocLink('$switch', META_EXPR_CONDITIONAL), }, ]; diff --git a/packages/documentdb-constants/src/queryOperators.ts b/packages/documentdb-constants/src/queryOperators.ts index e79f5b62d..edfa5a2b0 100644 --- a/packages/documentdb-constants/src/queryOperators.ts +++ b/packages/documentdb-constants/src/queryOperators.ts @@ -12,8 +12,10 @@ // // To change operator data, edit the overrides/snippets files and re-run the generator. -import { type OperatorEntry } from './types'; -import { META_QUERY_ARRAY, +import { getDocLink } from './docLinks'; +import { registerOperators } from './getFilteredCompletions'; +import { + META_QUERY_ARRAY, META_QUERY_BITWISE, META_QUERY_COMPARISON, META_QUERY_ELEMENT, @@ -21,9 +23,9 @@ import { META_QUERY_ARRAY, META_QUERY_GEOSPATIAL, META_QUERY_LOGICAL, META_QUERY_MISC, - META_QUERY_PROJECTION } from './metaTags'; -import { getDocLink } from './docLinks'; -import { registerOperators } from './getFilteredCompletions'; + META_QUERY_PROJECTION, +} from './metaTags'; +import { type OperatorEntry } from './types'; // --------------------------------------------------------------------------- // Comparison Query Operators @@ -40,14 +42,16 @@ const comparisonQueryOperators: readonly OperatorEntry[] = [ { value: '$gt', meta: META_QUERY_COMPARISON, - description: 'The $gt query operator retrieves documents where the value of a field is greater than a specified value', + description: + 'The $gt query operator retrieves documents where the value of a field is greater than a specified value', snippet: '{ $gt: ${1:value} }', link: getDocLink('$gt', META_QUERY_COMPARISON), }, { value: '$gte', meta: META_QUERY_COMPARISON, - description: 'The $gte operator retrieves documents where the value of a field is greater than or equal to a specified value', + description: + 'The $gte operator retrieves documents where the value of a field is greater than or equal to a specified value', snippet: '{ $gte: ${1:value} }', link: getDocLink('$gte', META_QUERY_COMPARISON), }, @@ -68,27 +72,27 @@ const comparisonQueryOperators: readonly OperatorEntry[] = [ { value: '$lte', meta: META_QUERY_COMPARISON, - description: 'The $lte operator retrieves documents where the value of a field is less than or equal to a specified value', + description: + 'The $lte operator retrieves documents where the value of a field is less than or equal to a specified value', snippet: '{ $lte: ${1:value} }', link: getDocLink('$lte', META_QUERY_COMPARISON), }, { value: '$ne', meta: META_QUERY_COMPARISON, - description: 'The $ne operator retrieves documents where the value of a field doesn\'t equal a specified value', + description: "The $ne operator retrieves documents where the value of a field doesn't equal a specified value", snippet: '{ $ne: ${1:value} }', link: getDocLink('$ne', META_QUERY_COMPARISON), }, { value: '$nin', meta: META_QUERY_COMPARISON, - description: 'The $nin operator retrieves documents where the value of a field doesn\'t match a list of values', + description: "The $nin operator retrieves documents where the value of a field doesn't match a list of values", snippet: '{ $nin: [${1:value}] }', link: getDocLink('$nin', META_QUERY_COMPARISON), }, ]; - // --------------------------------------------------------------------------- // Logical Query Operators // --------------------------------------------------------------------------- @@ -97,34 +101,37 @@ const logicalQueryOperators: readonly OperatorEntry[] = [ { value: '$and', meta: META_QUERY_LOGICAL, - description: 'The $and operator joins multiple query clauses and returns documents that match all specified conditions.', + description: + 'The $and operator joins multiple query clauses and returns documents that match all specified conditions.', snippet: '{ $and: [{ ${1:expression} }] }', link: getDocLink('$and', META_QUERY_LOGICAL), }, { value: '$not', meta: META_QUERY_LOGICAL, - description: 'The $not operator performs a logical NOT operation on a specified expression, selecting documents that don\'t match the expression.', + description: + "The $not operator performs a logical NOT operation on a specified expression, selecting documents that don't match the expression.", snippet: '{ $not: { ${1:expression} } }', link: getDocLink('$not', META_QUERY_LOGICAL), }, { value: '$nor', meta: META_QUERY_LOGICAL, - description: 'The $nor operator performs a logical NOR on an array of expressions and retrieves documents that fail all the conditions.', + description: + 'The $nor operator performs a logical NOR on an array of expressions and retrieves documents that fail all the conditions.', snippet: '{ $nor: [{ ${1:expression} }] }', link: getDocLink('$nor', META_QUERY_LOGICAL), }, { value: '$or', meta: META_QUERY_LOGICAL, - description: 'The $or operator joins query clauses with a logical OR and returns documents that match at least one of the specified conditions.', + description: + 'The $or operator joins query clauses with a logical OR and returns documents that match at least one of the specified conditions.', snippet: '{ $or: [{ ${1:expression} }] }', link: getDocLink('$or', META_QUERY_LOGICAL), }, ]; - // --------------------------------------------------------------------------- // Element Query Operators // --------------------------------------------------------------------------- @@ -133,7 +140,8 @@ const elementQueryOperators: readonly OperatorEntry[] = [ { value: '$exists', meta: META_QUERY_ELEMENT, - description: 'The $exists operator retrieves documents that contain the specified field in their document structure.', + description: + 'The $exists operator retrieves documents that contain the specified field in their document structure.', snippet: '{ $exists: ${1:true} }', link: getDocLink('$exists', META_QUERY_ELEMENT), }, @@ -146,7 +154,6 @@ const elementQueryOperators: readonly OperatorEntry[] = [ }, ]; - // --------------------------------------------------------------------------- // Evaluation Query Operators // --------------------------------------------------------------------------- @@ -155,28 +162,32 @@ const evaluationQueryOperators: readonly OperatorEntry[] = [ { value: '$expr', meta: META_QUERY_EVALUATION, - description: 'The $expr operator allows the use of aggregation expressions within the query language, enabling complex field comparisons and calculations.', + description: + 'The $expr operator allows the use of aggregation expressions within the query language, enabling complex field comparisons and calculations.', snippet: '{ $expr: { ${1:expression} } }', link: getDocLink('$expr', META_QUERY_EVALUATION), }, { value: '$jsonSchema', meta: META_QUERY_EVALUATION, - description: 'The $jsonSchema operator validates documents against a JSON Schema definition for data validation and structure enforcement. Discover supported features and limitations.', + description: + 'The $jsonSchema operator validates documents against a JSON Schema definition for data validation and structure enforcement. Discover supported features and limitations.', snippet: '{ $jsonSchema: { bsonType: "${1:object}" } }', link: getDocLink('$jsonSchema', META_QUERY_EVALUATION), }, { value: '$mod', meta: META_QUERY_EVALUATION, - description: 'The $mod operator performs a modulo operation on the value of a field and selects documents with a specified result.', + description: + 'The $mod operator performs a modulo operation on the value of a field and selects documents with a specified result.', snippet: '{ $mod: [${1:divisor}, ${2:remainder}] }', link: getDocLink('$mod', META_QUERY_EVALUATION), }, { value: '$regex', meta: META_QUERY_EVALUATION, - description: 'The $regex operator provides regular expression capabilities for pattern matching in queries, allowing flexible string matching and searching.', + description: + 'The $regex operator provides regular expression capabilities for pattern matching in queries, allowing flexible string matching and searching.', snippet: '{ $regex: /${1:pattern}/ }', link: getDocLink('$regex', META_QUERY_EVALUATION), applicableBsonTypes: ['string'], @@ -184,14 +195,14 @@ const evaluationQueryOperators: readonly OperatorEntry[] = [ { value: '$text', meta: META_QUERY_EVALUATION, - description: 'The $text operator performs text search on the content of indexed string fields, enabling full-text search capabilities.', + description: + 'The $text operator performs text search on the content of indexed string fields, enabling full-text search capabilities.', snippet: '{ $text: { \\$search: "${1:text}" } }', link: getDocLink('$text', META_QUERY_EVALUATION), applicableBsonTypes: ['string'], }, ]; - // --------------------------------------------------------------------------- // Geospatial Operators // --------------------------------------------------------------------------- @@ -200,14 +211,16 @@ const geospatialOperators: readonly OperatorEntry[] = [ { value: '$geoIntersects', meta: META_QUERY_GEOSPATIAL, - description: 'The $geoIntersects operator selects documents whose location field intersects with a specified GeoJSON object.', + description: + 'The $geoIntersects operator selects documents whose location field intersects with a specified GeoJSON object.', snippet: '{ $geoIntersects: { \\$geometry: { type: "${1:GeoJSON type}", coordinates: ${2:coordinates} } } }', link: getDocLink('$geoIntersects', META_QUERY_GEOSPATIAL), }, { value: '$geoWithin', meta: META_QUERY_GEOSPATIAL, - description: 'The $geoWithin operator selects documents whose location field is completely within a specified geometry.', + description: + 'The $geoWithin operator selects documents whose location field is completely within a specified geometry.', snippet: '{ $geoWithin: { \\$geometry: { type: "${1:GeoJSON type}", coordinates: ${2:coordinates} } } }', link: getDocLink('$geoWithin', META_QUERY_GEOSPATIAL), }, @@ -242,41 +255,47 @@ const geospatialOperators: readonly OperatorEntry[] = [ { value: '$maxDistance', meta: META_QUERY_GEOSPATIAL, - description: 'The $maxDistance operator specifies the maximum distance that can exist between two points in a geospatial query.', + description: + 'The $maxDistance operator specifies the maximum distance that can exist between two points in a geospatial query.', snippet: '${1:distance}', link: getDocLink('$maxDistance', META_QUERY_GEOSPATIAL), }, { value: '$minDistance', meta: META_QUERY_GEOSPATIAL, - description: 'The $minDistance operator specifies the minimum distance that must exist between two points in a geospatial query.', + description: + 'The $minDistance operator specifies the minimum distance that must exist between two points in a geospatial query.', snippet: '${1:distance}', link: getDocLink('$minDistance', META_QUERY_GEOSPATIAL), }, { value: '$polygon', meta: META_QUERY_GEOSPATIAL, - description: 'The $polygon operator defines a polygon for geospatial queries, allowing you to find locations within an irregular shape.', + description: + 'The $polygon operator defines a polygon for geospatial queries, allowing you to find locations within an irregular shape.', snippet: '[[${1:x1}, ${2:y1}], [${3:x2}, ${4:y2}], [${5:x3}, ${6:y3}]]', link: getDocLink('$polygon', META_QUERY_GEOSPATIAL), }, { value: '$near', meta: META_QUERY_GEOSPATIAL, - description: 'The $near operator returns documents with location fields that are near a specified point, sorted by distance.', - snippet: '{ $near: { \\$geometry: { type: "Point", coordinates: [${1:lng}, ${2:lat}] }, \\$maxDistance: ${3:distance} } }', + description: + 'The $near operator returns documents with location fields that are near a specified point, sorted by distance.', + snippet: + '{ $near: { \\$geometry: { type: "Point", coordinates: [${1:lng}, ${2:lat}] }, \\$maxDistance: ${3:distance} } }', link: getDocLink('$near', META_QUERY_GEOSPATIAL), }, { value: '$nearSphere', meta: META_QUERY_GEOSPATIAL, - description: 'The $nearSphere operator returns documents whose location fields are near a specified point on a sphere, sorted by distance on a spherical surface.', - snippet: '{ $nearSphere: { \\$geometry: { type: "Point", coordinates: [${1:lng}, ${2:lat}] }, \\$maxDistance: ${3:distance} } }', + description: + 'The $nearSphere operator returns documents whose location fields are near a specified point on a sphere, sorted by distance on a spherical surface.', + snippet: + '{ $nearSphere: { \\$geometry: { type: "Point", coordinates: [${1:lng}, ${2:lat}] }, \\$maxDistance: ${3:distance} } }', link: getDocLink('$nearSphere', META_QUERY_GEOSPATIAL), }, ]; - // --------------------------------------------------------------------------- // Array Query Operators // --------------------------------------------------------------------------- @@ -293,7 +312,8 @@ const arrayQueryOperators: readonly OperatorEntry[] = [ { value: '$elemMatch', meta: META_QUERY_ARRAY, - description: 'The $elemmatch operator returns complete array, qualifying criteria with at least one matching array element.', + description: + 'The $elemmatch operator returns complete array, qualifying criteria with at least one matching array element.', snippet: '{ $elemMatch: { ${1:query} } }', link: getDocLink('$elemMatch', META_QUERY_ARRAY), applicableBsonTypes: ['array'], @@ -301,14 +321,14 @@ const arrayQueryOperators: readonly OperatorEntry[] = [ { value: '$size', meta: META_QUERY_ARRAY, - description: 'The $size operator is used to query documents where an array field has a specified number of elements.', + description: + 'The $size operator is used to query documents where an array field has a specified number of elements.', snippet: '{ $size: ${1:number} }', link: getDocLink('$size', META_QUERY_ARRAY), applicableBsonTypes: ['array'], }, ]; - // --------------------------------------------------------------------------- // Bitwise Query Operators // --------------------------------------------------------------------------- @@ -317,7 +337,8 @@ const bitwiseQueryOperators: readonly OperatorEntry[] = [ { value: '$bitsAllClear', meta: META_QUERY_BITWISE, - description: 'The $bitsAllClear operator is used to match documents where all the bit positions specified in a bitmask are clear.', + description: + 'The $bitsAllClear operator is used to match documents where all the bit positions specified in a bitmask are clear.', snippet: '{ $bitsAllClear: ${1:bitmask} }', link: getDocLink('$bitsAllClear', META_QUERY_BITWISE), applicableBsonTypes: ['int', 'long'], @@ -333,7 +354,8 @@ const bitwiseQueryOperators: readonly OperatorEntry[] = [ { value: '$bitsAnyClear', meta: META_QUERY_BITWISE, - description: 'The $bitsAnyClear operator matches documents where any of the specified bit positions in a bitmask are clear.', + description: + 'The $bitsAnyClear operator matches documents where any of the specified bit positions in a bitmask are clear.', snippet: '{ $bitsAnyClear: ${1:bitmask} }', link: getDocLink('$bitsAnyClear', META_QUERY_BITWISE), applicableBsonTypes: ['int', 'long'], @@ -341,14 +363,14 @@ const bitwiseQueryOperators: readonly OperatorEntry[] = [ { value: '$bitsAnySet', meta: META_QUERY_BITWISE, - description: 'The $bitsAnySet operator returns documents where any of the specified bit positions are set to 1.', + description: + 'The $bitsAnySet operator returns documents where any of the specified bit positions are set to 1.', snippet: '{ $bitsAnySet: ${1:bitmask} }', link: getDocLink('$bitsAnySet', META_QUERY_BITWISE), applicableBsonTypes: ['int', 'long'], }, ]; - // --------------------------------------------------------------------------- // Projection Operators // --------------------------------------------------------------------------- @@ -357,13 +379,15 @@ const projectionOperators: readonly OperatorEntry[] = [ { value: '$', meta: META_QUERY_PROJECTION, - description: 'The $ positional operator identifies an element in an array to update without explicitly specifying the position of the element in the array.', + description: + 'The $ positional operator identifies an element in an array to update without explicitly specifying the position of the element in the array.', link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$', // inferred from another category }, { value: '$elemMatch', meta: META_QUERY_PROJECTION, - description: 'The $elemmatch operator returns complete array, qualifying criteria with at least one matching array element.', + description: + 'The $elemmatch operator returns complete array, qualifying criteria with at least one matching array element.', snippet: '{ $elemMatch: { ${1:query} } }', link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-query/$elemmatch', // inferred from another category }, @@ -376,7 +400,6 @@ const projectionOperators: readonly OperatorEntry[] = [ }, ]; - // --------------------------------------------------------------------------- // Miscellaneous Query Operators // --------------------------------------------------------------------------- @@ -385,7 +408,8 @@ const miscellaneousQueryOperators: readonly OperatorEntry[] = [ { value: '$comment', meta: META_QUERY_MISC, - description: 'The $comment operator adds a comment to a query to help identify the query in logs and profiler output.', + description: + 'The $comment operator adds a comment to a query to help identify the query in logs and profiler output.', snippet: '{ $comment: "${1:comment}" }', link: getDocLink('$comment', META_QUERY_MISC), }, @@ -399,7 +423,8 @@ const miscellaneousQueryOperators: readonly OperatorEntry[] = [ { value: '$natural', meta: META_QUERY_MISC, - description: 'The $natural operator forces the query to use the natural order of documents in a collection, providing control over document ordering and retrieval.', + description: + 'The $natural operator forces the query to use the natural order of documents in a collection, providing control over document ordering and retrieval.', snippet: '{ $natural: ${1:1} }', link: getDocLink('$natural', META_QUERY_MISC), }, diff --git a/packages/documentdb-constants/src/stages.ts b/packages/documentdb-constants/src/stages.ts index 975f07302..59e5a212a 100644 --- a/packages/documentdb-constants/src/stages.ts +++ b/packages/documentdb-constants/src/stages.ts @@ -12,10 +12,10 @@ // // To change operator data, edit the overrides/snippets files and re-run the generator. -import { type OperatorEntry } from './types'; -import { META_STAGE } from './metaTags'; import { getDocLink } from './docLinks'; import { registerOperators } from './getFilteredCompletions'; +import { META_STAGE } from './metaTags'; +import { type OperatorEntry } from './types'; // --------------------------------------------------------------------------- // Aggregation Pipeline Stages @@ -39,7 +39,8 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ { value: '$bucketAuto', meta: META_STAGE, - description: 'Categorizes documents into a specified number of groups based on a given expression, automatically determining bucket boundaries.', + description: + 'Categorizes documents into a specified number of groups based on a given expression, automatically determining bucket boundaries.', snippet: '{ $bucketAuto: { groupBy: "${1:\\$field}", buckets: ${2:number} } }', }, { @@ -52,14 +53,16 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ { value: '$collStats', meta: META_STAGE, - description: 'The $collStats stage in the aggregation pipeline is used to return statistics about a collection.', + description: + 'The $collStats stage in the aggregation pipeline is used to return statistics about a collection.', snippet: '{ $collStats: { storageStats: {} } }', link: getDocLink('$collStats', META_STAGE), }, { value: '$count', meta: META_STAGE, - description: 'The `$count` operator is used to count the number of documents that match a query filtering criteria.', + description: + 'The `$count` operator is used to count the number of documents that match a query filtering criteria.', snippet: '{ $count: "${1:countField}" }', link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$count', // inferred from another category }, @@ -80,34 +83,41 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ { value: '$facet', meta: META_STAGE, - description: 'The $facet allows for multiple parallel aggregations to be executed within a single pipeline stage.', + description: + 'The $facet allows for multiple parallel aggregations to be executed within a single pipeline stage.', snippet: '{ $facet: { ${1:outputField}: [{ ${2:stage} }] } }', link: getDocLink('$facet', META_STAGE), }, { value: '$fill', meta: META_STAGE, - description: 'The $fill stage allows filling missing values in documents based on specified methods and criteria.', + description: + 'The $fill stage allows filling missing values in documents based on specified methods and criteria.', snippet: '{ $fill: { output: { ${1:field}: { method: "${2:linear}" } } } }', link: getDocLink('$fill', META_STAGE), }, { value: '$geoNear', meta: META_STAGE, - description: 'The $geoNear operator finds and sorts documents by their proximity to a geospatial point, returning distance information for each document.', - snippet: '{ $geoNear: { near: { type: "Point", coordinates: [${1:lng}, ${2:lat}] }, distanceField: "${3:distance}" } }', + description: + 'The $geoNear operator finds and sorts documents by their proximity to a geospatial point, returning distance information for each document.', + snippet: + '{ $geoNear: { near: { type: "Point", coordinates: [${1:lng}, ${2:lat}] }, distanceField: "${3:distance}" } }', link: getDocLink('$geoNear', META_STAGE), }, { value: '$graphLookup', meta: META_STAGE, - description: 'Performs a recursive search on a collection to return documents connected by a specified field relationship.', - snippet: '{ $graphLookup: { from: "${1:collection}", startWith: "${2:\\$field}", connectFromField: "${3:field}", connectToField: "${4:field}", as: "${5:result}" } }', + description: + 'Performs a recursive search on a collection to return documents connected by a specified field relationship.', + snippet: + '{ $graphLookup: { from: "${1:collection}", startWith: "${2:\\$field}", connectFromField: "${3:field}", connectToField: "${4:field}", as: "${5:result}" } }', }, { value: '$group', meta: META_STAGE, - description: 'The $group stage groups documents by specified identifier expressions and applies accumulator expressions.', + description: + 'The $group stage groups documents by specified identifier expressions and applies accumulator expressions.', snippet: '{ $group: { _id: "${1:\\$field}", ${2:accumulator}: { ${3:\\$sum}: 1 } } }', link: getDocLink('$group', META_STAGE), }, @@ -127,28 +137,33 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ { value: '$lookup', meta: META_STAGE, - description: 'The $lookup stage in the Aggregation Framework is used to perform left outer joins with other collections.', - snippet: '{ $lookup: { from: "${1:collection}", localField: "${2:field}", foreignField: "${3:field}", as: "${4:result}" } }', + description: + 'The $lookup stage in the Aggregation Framework is used to perform left outer joins with other collections.', + snippet: + '{ $lookup: { from: "${1:collection}", localField: "${2:field}", foreignField: "${3:field}", as: "${4:result}" } }', link: getDocLink('$lookup', META_STAGE), }, { value: '$match', meta: META_STAGE, - description: 'The $match stage in the aggregation pipeline is used to filter documents that match a specified condition.', + description: + 'The $match stage in the aggregation pipeline is used to filter documents that match a specified condition.', snippet: '{ $match: { ${1:query} } }', link: getDocLink('$match', META_STAGE), }, { value: '$merge', meta: META_STAGE, - description: 'The $merge stage in an aggregation pipeline writes the results of the aggregation to a specified collection.', + description: + 'The $merge stage in an aggregation pipeline writes the results of the aggregation to a specified collection.', snippet: '{ $merge: { into: "${1:collection}" } }', link: getDocLink('$merge', META_STAGE), }, { value: '$out', meta: META_STAGE, - description: 'The `$out` stage in an aggregation pipeline writes the resulting documents to a specified collection.', + description: + 'The `$out` stage in an aggregation pipeline writes the resulting documents to a specified collection.', snippet: '{ $out: "${1:collection}" }', link: getDocLink('$out', META_STAGE), }, @@ -162,7 +177,8 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ value: '$redact', meta: META_STAGE, description: 'Filters the content of the documents based on access rights.', - snippet: '{ $redact: { \\$cond: { if: { ${1:expression} }, then: "${2:\\$\\$DESCEND}", else: "${3:\\$\\$PRUNE}" } } }', + snippet: + '{ $redact: { \\$cond: { if: { ${1:expression} }, then: "${2:\\$\\$DESCEND}", else: "${3:\\$\\$PRUNE}" } } }', link: getDocLink('$redact', META_STAGE), }, { @@ -174,7 +190,8 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ { value: '$replaceWith', meta: META_STAGE, - description: 'The $replaceWith operator in Azure DocumentDB returns a document after replacing a document with the specified document', + description: + 'The $replaceWith operator in Azure DocumentDB returns a document after replacing a document with the specified document', snippet: '{ $replaceWith: "${1:\\$field}" }', link: getDocLink('$replaceWith', META_STAGE), }, @@ -207,27 +224,32 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ { value: '$setWindowFields', meta: META_STAGE, - description: 'Adds computed fields to documents using window functions over a specified partition and sort order.', - snippet: '{ $setWindowFields: { partitionBy: "${1:\\$field}", sortBy: { ${2:field}: ${3:1} }, output: { ${4:newField}: { ${5:windowFunc} } } } }', + description: + 'Adds computed fields to documents using window functions over a specified partition and sort order.', + snippet: + '{ $setWindowFields: { partitionBy: "${1:\\$field}", sortBy: { ${2:field}: ${3:1} }, output: { ${4:newField}: { ${5:windowFunc} } } } }', }, { value: '$skip', meta: META_STAGE, - description: 'The $skip stage in the aggregation pipeline is used to skip a specified number of documents from the input and pass the remaining documents to the next stage in the pipeline.', + description: + 'The $skip stage in the aggregation pipeline is used to skip a specified number of documents from the input and pass the remaining documents to the next stage in the pipeline.', snippet: '{ $skip: ${1:number} }', link: getDocLink('$skip', META_STAGE), }, { value: '$sort', meta: META_STAGE, - description: 'The $sort stage in the aggregation pipeline is used to order the documents in the pipeline by a specified field or fields.', + description: + 'The $sort stage in the aggregation pipeline is used to order the documents in the pipeline by a specified field or fields.', snippet: '{ $sort: { ${1:field}: ${2:1} } }', link: getDocLink('$sort', META_STAGE), }, { value: '$sortByCount', meta: META_STAGE, - description: 'The $sortByCount stage in the aggregation pipeline is used to group documents by a specified expression and then sort the count of documents in each group in descending order.', + description: + 'The $sortByCount stage in the aggregation pipeline is used to group documents by a specified expression and then sort the count of documents in each group in descending order.', snippet: '{ $sortByCount: "${1:\\$field}" }', link: getDocLink('$sortByCount', META_STAGE), }, @@ -247,7 +269,8 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ { value: '$unwind', meta: META_STAGE, - description: 'The $unwind stage in the aggregation framework is used to deconstruct an array field from the input documents to output a document for each element.', + description: + 'The $unwind stage in the aggregation framework is used to deconstruct an array field from the input documents to output a document for each element.', snippet: '{ $unwind: "${1:\\$arrayField}" }', link: getDocLink('$unwind', META_STAGE), }, @@ -263,6 +286,4 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ // Registration // --------------------------------------------------------------------------- -registerOperators([ - ...aggregationPipelineStages, -]); +registerOperators([...aggregationPipelineStages]); diff --git a/packages/documentdb-constants/src/systemVariables.ts b/packages/documentdb-constants/src/systemVariables.ts index 68fc8e6e5..4a404f7bb 100644 --- a/packages/documentdb-constants/src/systemVariables.ts +++ b/packages/documentdb-constants/src/systemVariables.ts @@ -12,9 +12,9 @@ // // To change operator data, edit the overrides/snippets files and re-run the generator. -import { type OperatorEntry } from './types'; -import { META_VARIABLE } from './metaTags'; import { registerOperators } from './getFilteredCompletions'; +import { META_VARIABLE } from './metaTags'; +import { type OperatorEntry } from './types'; // --------------------------------------------------------------------------- // Variables in Aggregation Expressions @@ -24,37 +24,44 @@ const systemVariables: readonly OperatorEntry[] = [ { value: '$$NOW', meta: META_VARIABLE, - description: 'Returns the current datetime as a Date object. Constant throughout a single aggregation pipeline.', + description: + 'Returns the current datetime as a Date object. Constant throughout a single aggregation pipeline.', }, { value: '$$ROOT', meta: META_VARIABLE, - description: 'References the root document — the top-level document currently being processed in the pipeline stage.', + description: + 'References the root document — the top-level document currently being processed in the pipeline stage.', }, { value: '$$REMOVE', meta: META_VARIABLE, - description: 'Removes a field from the output document. Used with $project or $addFields to conditionally exclude fields.', + description: + 'Removes a field from the output document. Used with $project or $addFields to conditionally exclude fields.', }, { value: '$$CURRENT', meta: META_VARIABLE, - description: 'References the current document in the pipeline stage. Equivalent to $$ROOT at the start of the pipeline.', + description: + 'References the current document in the pipeline stage. Equivalent to $$ROOT at the start of the pipeline.', }, { value: '$$DESCEND', meta: META_VARIABLE, - description: 'Used with $redact. Returns the document fields at the current level and continues descending into subdocuments.', + description: + 'Used with $redact. Returns the document fields at the current level and continues descending into subdocuments.', }, { value: '$$PRUNE', meta: META_VARIABLE, - description: 'Used with $redact. Excludes all fields at the current document level and stops descending into subdocuments.', + description: + 'Used with $redact. Excludes all fields at the current document level and stops descending into subdocuments.', }, { value: '$$KEEP', meta: META_VARIABLE, - description: 'Used with $redact. Keeps all fields at the current document level without further descending into subdocuments.', + description: + 'Used with $redact. Keeps all fields at the current document level without further descending into subdocuments.', }, ]; @@ -62,6 +69,4 @@ const systemVariables: readonly OperatorEntry[] = [ // Registration // --------------------------------------------------------------------------- -registerOperators([ - ...systemVariables, -]); +registerOperators([...systemVariables]); diff --git a/packages/documentdb-constants/src/updateOperators.ts b/packages/documentdb-constants/src/updateOperators.ts index 883b3f2a0..92c3d4b6b 100644 --- a/packages/documentdb-constants/src/updateOperators.ts +++ b/packages/documentdb-constants/src/updateOperators.ts @@ -12,12 +12,10 @@ // // To change operator data, edit the overrides/snippets files and re-run the generator. -import { type OperatorEntry } from './types'; -import { META_UPDATE_ARRAY, - META_UPDATE_BITWISE, - META_UPDATE_FIELD } from './metaTags'; import { getDocLink } from './docLinks'; import { registerOperators } from './getFilteredCompletions'; +import { META_UPDATE_ARRAY, META_UPDATE_BITWISE, META_UPDATE_FIELD } from './metaTags'; +import { type OperatorEntry } from './types'; // --------------------------------------------------------------------------- // Field Update Operators @@ -27,7 +25,8 @@ const fieldUpdateOperators: readonly OperatorEntry[] = [ { value: '$currentDate', meta: META_UPDATE_FIELD, - description: 'The $currentDate operator sets the value of a field to the current date, either as a Date or a timestamp.', + description: + 'The $currentDate operator sets the value of a field to the current date, either as a Date or a timestamp.', snippet: '{ $currentDate: { "${1:field}": true } }', link: getDocLink('$currentDate', META_UPDATE_FIELD), }, @@ -76,7 +75,8 @@ const fieldUpdateOperators: readonly OperatorEntry[] = [ { value: '$setOnInsert', meta: META_UPDATE_FIELD, - description: 'The $setOnInsert operator sets field values only when an upsert operation results in an insert of a new document.', + description: + 'The $setOnInsert operator sets field values only when an upsert operation results in an insert of a new document.', snippet: '{ $setOnInsert: { "${1:field}": ${2:value} } }', link: getDocLink('$setOnInsert', META_UPDATE_FIELD), }, @@ -89,7 +89,6 @@ const fieldUpdateOperators: readonly OperatorEntry[] = [ }, ]; - // --------------------------------------------------------------------------- // Array Update Operators // --------------------------------------------------------------------------- @@ -98,7 +97,8 @@ const arrayUpdateOperators: readonly OperatorEntry[] = [ { value: '$', meta: META_UPDATE_ARRAY, - description: 'The $ positional operator identifies an element in an array to update without explicitly specifying the position of the element in the array.', + description: + 'The $ positional operator identifies an element in an array to update without explicitly specifying the position of the element in the array.', link: getDocLink('$', META_UPDATE_ARRAY), }, { @@ -109,12 +109,14 @@ const arrayUpdateOperators: readonly OperatorEntry[] = [ { value: '$[identifier]', meta: META_UPDATE_ARRAY, - description: 'Filtered positional operator. Acts as a placeholder to update elements that match an arrayFilters condition.', + description: + 'Filtered positional operator. Acts as a placeholder to update elements that match an arrayFilters condition.', }, { value: '$addToSet', meta: META_UPDATE_ARRAY, - description: 'The addToSet operator adds elements to an array if they don\'t already exist, while ensuring uniqueness of elements within the set.', + description: + "The addToSet operator adds elements to an array if they don't already exist, while ensuring uniqueness of elements within the set.", snippet: '{ $addToSet: { "${1:field}": ${2:value} } }', link: getDocLink('$addToSet', META_UPDATE_ARRAY), }, @@ -149,14 +151,16 @@ const arrayUpdateOperators: readonly OperatorEntry[] = [ { value: '$each', meta: META_UPDATE_ARRAY, - description: 'The $each operator is used within an `$addToSet`or`$push` operation to add multiple elements to an array field in a single update operation.', + description: + 'The $each operator is used within an `$addToSet`or`$push` operation to add multiple elements to an array field in a single update operation.', snippet: '{ $each: [${1:values}] }', link: getDocLink('$each', META_UPDATE_ARRAY), }, { value: '$position', meta: META_UPDATE_ARRAY, - description: 'Specifies the position in the array at which the $push operator inserts elements. Used with $each.', + description: + 'Specifies the position in the array at which the $push operator inserts elements. Used with $each.', snippet: '{ $position: ${1:index} }', }, { @@ -169,13 +173,13 @@ const arrayUpdateOperators: readonly OperatorEntry[] = [ { value: '$sort', meta: META_UPDATE_ARRAY, - description: 'The $sort stage in the aggregation pipeline is used to order the documents in the pipeline by a specified field or fields.', + description: + 'The $sort stage in the aggregation pipeline is used to order the documents in the pipeline by a specified field or fields.', snippet: '{ $sort: { "${1:field}": ${2:1} } }', link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/aggregation/$sort', // inferred from another category }, ]; - // --------------------------------------------------------------------------- // Bitwise Update Operators // --------------------------------------------------------------------------- @@ -194,8 +198,4 @@ const bitwiseUpdateOperators: readonly OperatorEntry[] = [ // Registration // --------------------------------------------------------------------------- -registerOperators([ - ...fieldUpdateOperators, - ...arrayUpdateOperators, - ...bitwiseUpdateOperators, -]); +registerOperators([...fieldUpdateOperators, ...arrayUpdateOperators, ...bitwiseUpdateOperators]); diff --git a/packages/documentdb-constants/src/windowOperators.ts b/packages/documentdb-constants/src/windowOperators.ts index cb15c76af..f1af97c8c 100644 --- a/packages/documentdb-constants/src/windowOperators.ts +++ b/packages/documentdb-constants/src/windowOperators.ts @@ -12,10 +12,10 @@ // // To change operator data, edit the overrides/snippets files and re-run the generator. -import { type OperatorEntry } from './types'; -import { META_WINDOW } from './metaTags'; import { getDocLink } from './docLinks'; import { registerOperators } from './getFilteredCompletions'; +import { META_WINDOW } from './metaTags'; +import { type OperatorEntry } from './types'; // --------------------------------------------------------------------------- // Window Operators @@ -39,14 +39,16 @@ const windowOperators: readonly OperatorEntry[] = [ { value: '$addToSet', meta: META_WINDOW, - description: 'The addToSet operator adds elements to an array if they don\'t already exist, while ensuring uniqueness of elements within the set.', + description: + "The addToSet operator adds elements to an array if they don't already exist, while ensuring uniqueness of elements within the set.", snippet: '{ $addToSet: "${1:\\$field}" }', link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$addtoset', // inferred from another category }, { value: '$count', meta: META_WINDOW, - description: 'The `$count` operator is used to count the number of documents that match a query filtering criteria.', + description: + 'The `$count` operator is used to count the number of documents that match a query filtering criteria.', snippet: '{ $count: "${1:\\$field}" }', link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$count', // inferred from another category }, @@ -81,7 +83,8 @@ const windowOperators: readonly OperatorEntry[] = [ { value: '$bottom', meta: META_WINDOW, - description: 'The $bottom operator returns the last document from the query\'s result set sorted by one or more fields', + description: + "The $bottom operator returns the last document from the query's result set sorted by one or more fields", snippet: '{ $bottom: "${1:\\$field}" }', link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$bottom', // inferred from another category }, @@ -109,42 +112,47 @@ const windowOperators: readonly OperatorEntry[] = [ { value: '$denseRank', meta: META_WINDOW, - description: 'The $denseRank operator assigns and returns a positional ranking for each document within a partition based on a specified sort order', + description: + 'The $denseRank operator assigns and returns a positional ranking for each document within a partition based on a specified sort order', snippet: '{ $denseRank: {} }', link: getDocLink('$denseRank', META_WINDOW), }, { value: '$derivative', meta: META_WINDOW, - description: 'The $derivative operator calculates the average rate of change of the value of a field within a specified window.', + description: + 'The $derivative operator calculates the average rate of change of the value of a field within a specified window.', snippet: '{ $derivative: { input: "${1:\\$field}", unit: "${2:hour}" } }', link: getDocLink('$derivative', META_WINDOW), }, { value: '$documentNumber', meta: META_WINDOW, - description: 'The $documentNumber operator assigns and returns a position for each document within a partition based on a specified sort order', + description: + 'The $documentNumber operator assigns and returns a position for each document within a partition based on a specified sort order', snippet: '{ $documentNumber: {} }', link: getDocLink('$documentNumber', META_WINDOW), }, { value: '$expMovingAvg', meta: META_WINDOW, - description: 'The $expMovingAvg operator calculates the moving average of a field based on the specified number of documents to hold the highest weight', + description: + 'The $expMovingAvg operator calculates the moving average of a field based on the specified number of documents to hold the highest weight', snippet: '{ $expMovingAvg: { input: "${1:\\$field}", N: ${2:number} } }', link: getDocLink('$expMovingAvg', META_WINDOW), }, { value: '$first', meta: META_WINDOW, - description: 'The $first operator returns the first value in a group according to the group\'s sorting order.', + description: "The $first operator returns the first value in a group according to the group's sorting order.", snippet: '{ $first: "${1:\\$field}" }', link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$first', // inferred from another category }, { value: '$integral', meta: META_WINDOW, - description: 'The $integral operator calculates the area under a curve with the specified range of documents forming the adjacent documents for the calculation.', + description: + 'The $integral operator calculates the area under a curve with the specified range of documents forming the adjacent documents for the calculation.', snippet: '{ $integral: { input: "${1:\\$field}", unit: "${2:hour}" } }', link: getDocLink('$integral', META_WINDOW), }, @@ -158,14 +166,16 @@ const windowOperators: readonly OperatorEntry[] = [ { value: '$linearFill', meta: META_WINDOW, - description: 'The $linearFill operator interpolates missing values in a sequence of documents using linear interpolation.', + description: + 'The $linearFill operator interpolates missing values in a sequence of documents using linear interpolation.', snippet: '{ $linearFill: "${1:\\$field}" }', link: getDocLink('$linearFill', META_WINDOW), }, { value: '$locf', meta: META_WINDOW, - description: 'The $locf operator propagates the last observed non-null value forward within a partition in a windowed query.', + description: + 'The $locf operator propagates the last observed non-null value forward within a partition in a windowed query.', snippet: '{ $locf: "${1:\\$field}" }', link: getDocLink('$locf', META_WINDOW), }, @@ -193,7 +203,8 @@ const windowOperators: readonly OperatorEntry[] = [ { value: '$stdDevSamp', meta: META_WINDOW, - description: 'The $stddevsamp operator calculates the standard deviation of a specified sample of values and not the entire population', + description: + 'The $stddevsamp operator calculates the standard deviation of a specified sample of values and not the entire population', snippet: '{ $stdDevSamp: "${1:\\$field}" }', link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$stddevsamp', // inferred from another category }, @@ -217,6 +228,4 @@ const windowOperators: readonly OperatorEntry[] = [ // Registration // --------------------------------------------------------------------------- -registerOperators([ - ...windowOperators, -]); +registerOperators([...windowOperators]); From ab68d89c21f2ac7ea59eb44ce91ab19420b9bf60 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Fri, 20 Feb 2026 16:13:24 +0000 Subject: [PATCH 037/128] fix: update Jest test path for operator reference validation in README --- packages/documentdb-constants/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/documentdb-constants/README.md b/packages/documentdb-constants/README.md index 94588bae2..836915a27 100644 --- a/packages/documentdb-constants/README.md +++ b/packages/documentdb-constants/README.md @@ -59,7 +59,7 @@ This runs the scraper and then formats the output with Prettier. The scraper: 3. **Fetches** per-operator documentation (descriptions, syntax) with a global file index fallback for operators filed in unexpected directories 4. **Generates** `resources/scraped/operator-reference.md` in a structured heading format (`### $operator` with description, syntax, and doc link) -The dump serves as the authoritative reference for the TypeScript implementation. A Jest test (`test/operatorReference.test.ts`) will validate that the implementation matches the dump. +The dump serves as the authoritative reference for the TypeScript implementation. A Jest test (`src/operatorReference.test.ts`) validates that the implementation matches the dump. ## Structure From 9290f70085058571c6d7cd57c962c7d2a9a921dd Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 23 Feb 2026 12:32:40 +0000 Subject: [PATCH 038/128] =?UTF-8?q?docs:=20fix=20JSDoc=20=E2=80=94=20'froz?= =?UTF-8?q?en=20array'=20=E2=86=92=20'readonly=20array'=20in=20getFiltered?= =?UTF-8?q?Completions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/documentdb-constants/src/getFilteredCompletions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/documentdb-constants/src/getFilteredCompletions.ts b/packages/documentdb-constants/src/getFilteredCompletions.ts index dad83f262..2f029418f 100644 --- a/packages/documentdb-constants/src/getFilteredCompletions.ts +++ b/packages/documentdb-constants/src/getFilteredCompletions.ts @@ -42,7 +42,7 @@ export function registerOperators(entries: readonly OperatorEntry[]): void { * `applicableBsonTypes` (universal operators) are always included. * * @param filter - the filtering criteria - * @returns matching operator entries (frozen array) + * @returns matching operator entries (readonly array) */ export function getFilteredCompletions(filter: CompletionFilter): readonly OperatorEntry[] { return allOperators.filter((entry) => { From b13745d4b42da14a7fe02bd24496d8124104bc7c Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 23 Feb 2026 12:34:17 +0000 Subject: [PATCH 039/128] refactor: derive MetaTag from ALL_META_TAGS union with string escape hatch MetaTag is now (typeof ALL_META_TAGS)[number] | (string & {}), giving IntelliSense for known tags while preserving extensibility for runtime- injected tags like field:identifier. --- packages/documentdb-constants/src/types.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/documentdb-constants/src/types.ts b/packages/documentdb-constants/src/types.ts index 785bf812d..92efe14e4 100644 --- a/packages/documentdb-constants/src/types.ts +++ b/packages/documentdb-constants/src/types.ts @@ -3,6 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { type ALL_META_TAGS } from './metaTags'; + /** * Represents a single operator, stage, accumulator, or BSON constructor * for use in autocomplete, hover docs, and diagnostics. @@ -109,4 +111,4 @@ export interface CompletionFilter { * - 'variable' — system variables ($$NOW, $$ROOT, etc.) * - 'field:identifier' — injected field names from schema (not static) */ -export type MetaTag = string; +export type MetaTag = (typeof ALL_META_TAGS)[number] | (string & {}); From 2366b42f102b6ce8a02fcf73faec29e357b70560 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 23 Feb 2026 13:29:58 +0000 Subject: [PATCH 040/128] chore: remove devDependencies from documentdb-constants, delegate to root Aligns with Approach A (monorepo delegation): dev tooling (jest, ts-jest, prettier, ts-node, @types/jest) is provided by the root package.json. Eliminates the Jest 29 vs 30 version mismatch. Added root-install note to README. --- packages/documentdb-constants/README.md | 9 +++++++++ packages/documentdb-constants/package.json | 9 +-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/documentdb-constants/README.md b/packages/documentdb-constants/README.md index 836915a27..4835cdcc2 100644 --- a/packages/documentdb-constants/README.md +++ b/packages/documentdb-constants/README.md @@ -2,6 +2,15 @@ Static operator metadata for all DocumentDB-supported operators, aggregation stages, accumulators, update operators, BSON type constructors, and system variables. +> **Monorepo package** — this package is part of the `vscode-documentdb` workspace. +> Dev dependencies (Jest, ts-jest, Prettier, ts-node, etc.) are provided by the +> root `package.json`. Always install from the repository root: +> +> ```bash +> cd +> npm install +> ``` + ## Purpose This package is the **single source of truth** for operator metadata when the connected database is DocumentDB. It provides: diff --git a/packages/documentdb-constants/package.json b/packages/documentdb-constants/package.json index 1d178e8c7..566f295b5 100644 --- a/packages/documentdb-constants/package.json +++ b/packages/documentdb-constants/package.json @@ -21,12 +21,5 @@ "url": "https://github.com/microsoft/vscode-documentdb", "directory": "packages/documentdb-constants" }, - "license": "MIT", - "devDependencies": { - "@types/jest": "^29.5.14", - "jest": "^29.7.0", - "prettier": "~3.6.2", - "ts-jest": "^29.3.4", - "ts-node": "^10.9.2" - } + "license": "MIT" } From 42fcdd42e334ae97142d5ac7e46fe2f819061339 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 23 Feb 2026 14:03:19 +0000 Subject: [PATCH 041/128] chore: unify workspace configs across packages - Root prettier check now covers packages/ (was missing, only prettier-fix had it) - schema-analyzer jest.config.js: add maxWorkers '50%' to match documentdb-constants - schema-analyzer README: add monorepo root-install note (matching documentdb-constants) - No .nvmrc or prettier configs needed per-package (inherited from root) --- package.json | 2 +- packages/schema-analyzer/README.md | 9 +++++++++ packages/schema-analyzer/jest.config.js | 3 +++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index ec67c79ca..a823a6616 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "package-prerelease:default": "npm run webpack-prod && cd dist && npm pkg delete \"scripts.vscode:prepublish\" && npx vsce package --pre-release --no-dependencies --out ../${npm_package_name}-${npm_package_version}-pre-release.vsix", "lint": "eslint --quiet .", "lint-fix": "eslint . --fix", - "prettier": "prettier -c \"(src|test|l10n|grammar|docs)/**/*.@(js|ts|jsx|tsx|json)\" \"./*.@(js|ts|jsx|tsx|json)\"", + "prettier": "prettier -c \"(src|test|l10n|grammar|docs|packages)/**/*.@(js|ts|jsx|tsx|json)\" \"./*.@(js|ts|jsx|tsx|json)\"", "prettier-fix": "prettier -w \"(src|test|l10n|grammar|docs|packages)/**/*.@(js|ts|jsx|tsx|json)\" \"./*.@(js|ts|jsx|tsx|json)\"", "pretest": "npm run build", "test": "vscode-test", diff --git a/packages/schema-analyzer/README.md b/packages/schema-analyzer/README.md index 2010f2e7a..1efa58f49 100644 --- a/packages/schema-analyzer/README.md +++ b/packages/schema-analyzer/README.md @@ -2,6 +2,15 @@ Incremental JSON Schema analyzer for DocumentDB API and MongoDB API documents. Processes documents one at a time (or in batches) and produces an extended JSON Schema with statistical metadata — field occurrence counts, BSON type distributions, min/max values, and array length stats. +> **Monorepo package** — this package is part of the `vscode-documentdb` workspace. +> Dev dependencies (Jest, ts-jest, Prettier, TypeScript, etc.) are provided by the +> root `package.json`. Always install from the repository root: +> +> ```bash +> cd +> npm install +> ``` +> > **Note:** This package is not yet published to npm. We plan to publish it once the API stabilizes. For now, it is consumed internally via npm workspaces within the [vscode-documentdb](https://github.com/microsoft/vscode-documentdb) repository. ## Overview diff --git a/packages/schema-analyzer/jest.config.js b/packages/schema-analyzer/jest.config.js index 388d1e1d1..6aecf39aa 100644 --- a/packages/schema-analyzer/jest.config.js +++ b/packages/schema-analyzer/jest.config.js @@ -1,5 +1,8 @@ /** @type {import('ts-jest').JestConfigWithTsJest} **/ module.exports = { + // Limit workers to avoid OOM kills on machines with many cores. + // Each ts-jest worker loads the TypeScript compiler and consumes ~500MB+. + maxWorkers: '50%', testEnvironment: 'node', testMatch: ['/test/**/*.test.ts'], transform: { From 6c7e614379c1a310bb9b0aff3fc1dde6a52ee363 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 23 Feb 2026 16:22:59 +0000 Subject: [PATCH 042/128] chore(documentdb-constants): add tsconfig.scripts.json for CI script type checking --- packages/documentdb-constants/package.json | 1 + packages/documentdb-constants/tsconfig.scripts.json | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 packages/documentdb-constants/tsconfig.scripts.json diff --git a/packages/documentdb-constants/package.json b/packages/documentdb-constants/package.json index 566f295b5..00fb83442 100644 --- a/packages/documentdb-constants/package.json +++ b/packages/documentdb-constants/package.json @@ -11,6 +11,7 @@ "build": "tsc -p .", "clean": "rimraf dist tsconfig.tsbuildinfo", "test": "jest --config jest.config.js", + "typecheck:scripts": "tsc -p tsconfig.scripts.json --noEmit", "prettier-fix": "prettier -w \"(scripts|src)/**/*.@(js|ts|jsx|tsx|json|md)\" \"./*.@(js|ts|jsx|tsx|json|md)\"", "scrape": "ts-node scripts/scrape-operator-docs.ts && prettier --write resources/scraped/operator-reference.md", "generate": "ts-node scripts/generate-from-reference.ts", diff --git a/packages/documentdb-constants/tsconfig.scripts.json b/packages/documentdb-constants/tsconfig.scripts.json new file mode 100644 index 000000000..841c83b0a --- /dev/null +++ b/packages/documentdb-constants/tsconfig.scripts.json @@ -0,0 +1,13 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "composite": false, + "declaration": false, + "declarationMap": false, + "noEmit": true, + "rootDir": ".", + "types": ["node"] + }, + "include": ["scripts/**/*", "src/**/*"], + "exclude": ["node_modules", "dist", "src/**/*.test.ts", "src/**/*.spec.ts"] +} From 0ece75a766cdf7ccf1cc75b9aa93cef60d740b10 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 23 Feb 2026 16:25:13 +0000 Subject: [PATCH 043/128] refactor(documentdb-constants): replace side-effect imports with explicit loadOperators() factory --- .../documentdb-constants/src/accumulators.ts | 4 +- .../src/bsonConstructors.ts | 4 +- .../src/expressionOperators.ts | 40 +++++++++-------- .../src/getFilteredCompletions.ts | 8 ++++ packages/documentdb-constants/src/index.ts | 44 ++++++++++++++----- .../src/queryOperators.ts | 24 +++++----- packages/documentdb-constants/src/stages.ts | 4 +- .../src/systemVariables.ts | 4 +- .../src/updateOperators.ts | 4 +- .../src/windowOperators.ts | 4 +- 10 files changed, 94 insertions(+), 46 deletions(-) diff --git a/packages/documentdb-constants/src/accumulators.ts b/packages/documentdb-constants/src/accumulators.ts index 4b7c6694a..c2d4d97d0 100644 --- a/packages/documentdb-constants/src/accumulators.ts +++ b/packages/documentdb-constants/src/accumulators.ts @@ -181,4 +181,6 @@ const groupAccumulators: readonly OperatorEntry[] = [ // Registration // --------------------------------------------------------------------------- -registerOperators([...groupAccumulators]); +export function loadAccumulators(): void { + registerOperators([...groupAccumulators]); +} diff --git a/packages/documentdb-constants/src/bsonConstructors.ts b/packages/documentdb-constants/src/bsonConstructors.ts index fbe25bb0d..83377bbd1 100644 --- a/packages/documentdb-constants/src/bsonConstructors.ts +++ b/packages/documentdb-constants/src/bsonConstructors.ts @@ -78,4 +78,6 @@ const bsonConstructors: readonly OperatorEntry[] = [ // Registration // --------------------------------------------------------------------------- -registerOperators(bsonConstructors); +export function loadBsonConstructors(): void { + registerOperators(bsonConstructors); +} diff --git a/packages/documentdb-constants/src/expressionOperators.ts b/packages/documentdb-constants/src/expressionOperators.ts index 77b197b85..203ee41eb 100644 --- a/packages/documentdb-constants/src/expressionOperators.ts +++ b/packages/documentdb-constants/src/expressionOperators.ts @@ -1158,22 +1158,24 @@ const conditionalExpressionOperators: readonly OperatorEntry[] = [ // Registration // --------------------------------------------------------------------------- -registerOperators([ - ...arithmeticExpressionOperators, - ...arrayExpressionOperators, - ...bitwiseOperators, - ...booleanExpressionOperators, - ...comparisonExpressionOperators, - ...dataSizeOperators, - ...dateExpressionOperators, - ...literalExpressionOperator, - ...miscellaneousOperators, - ...objectExpressionOperators, - ...setExpressionOperators, - ...stringExpressionOperators, - ...timestampExpressionOperators, - ...trigonometryExpressionOperators, - ...typeExpressionOperators, - ...variableExpressionOperators, - ...conditionalExpressionOperators, -]); +export function loadExpressionOperators(): void { + registerOperators([ + ...arithmeticExpressionOperators, + ...arrayExpressionOperators, + ...bitwiseOperators, + ...booleanExpressionOperators, + ...comparisonExpressionOperators, + ...dataSizeOperators, + ...dateExpressionOperators, + ...literalExpressionOperator, + ...miscellaneousOperators, + ...objectExpressionOperators, + ...setExpressionOperators, + ...stringExpressionOperators, + ...timestampExpressionOperators, + ...trigonometryExpressionOperators, + ...typeExpressionOperators, + ...variableExpressionOperators, + ...conditionalExpressionOperators, + ]); +} diff --git a/packages/documentdb-constants/src/getFilteredCompletions.ts b/packages/documentdb-constants/src/getFilteredCompletions.ts index 2f029418f..fafdf2a13 100644 --- a/packages/documentdb-constants/src/getFilteredCompletions.ts +++ b/packages/documentdb-constants/src/getFilteredCompletions.ts @@ -29,6 +29,14 @@ export function registerOperators(entries: readonly OperatorEntry[]): void { allOperators.push(...entries); } +/** + * Clears all registered operator entries. + * Intended for internal/testing use only. + */ +export function clearOperators(): void { + allOperators.length = 0; +} + /** * Returns operator entries matching the given filter. * diff --git a/packages/documentdb-constants/src/index.ts b/packages/documentdb-constants/src/index.ts index ba442cc13..d888fcf6b 100644 --- a/packages/documentdb-constants/src/index.ts +++ b/packages/documentdb-constants/src/index.ts @@ -65,17 +65,41 @@ export { } from './metaTags'; // -- Consumer API -- -export { getAllCompletions, getFilteredCompletions, registerOperators } from './getFilteredCompletions'; +export { getAllCompletions, getFilteredCompletions } from './getFilteredCompletions'; // -- Documentation URL helpers -- export { getDocBase, getDocLink } from './docLinks'; -// -- Operator data modules (self-register on import) -- -import './accumulators'; -import './bsonConstructors'; -import './expressionOperators'; -import './queryOperators'; -import './stages'; -import './systemVariables'; -import './updateOperators'; -import './windowOperators'; +// -- Operator data modules -- +import { loadAccumulators } from './accumulators'; +import { loadBsonConstructors } from './bsonConstructors'; +import { loadExpressionOperators } from './expressionOperators'; +import { loadQueryOperators } from './queryOperators'; +import { loadStages } from './stages'; +import { loadSystemVariables } from './systemVariables'; +import { loadUpdateOperators } from './updateOperators'; +import { loadWindowOperators } from './windowOperators'; + +/** + * Loads all built-in operator data into the registry. + * + * Called automatically at module import time so that consumers using + * `import { getFilteredCompletions } from '@vscode-documentdb/documentdb-constants'` + * get all operators without any additional setup. + * + * Can also be called explicitly (e.g. in workers or tests) — the call is + * idempotent when combined with {@link clearOperators}. + */ +export function loadOperators(): void { + loadAccumulators(); + loadBsonConstructors(); + loadExpressionOperators(); + loadQueryOperators(); + loadStages(); + loadSystemVariables(); + loadUpdateOperators(); + loadWindowOperators(); +} + +// Auto-load on module import so the public API works out of the box. +loadOperators(); diff --git a/packages/documentdb-constants/src/queryOperators.ts b/packages/documentdb-constants/src/queryOperators.ts index edfa5a2b0..a673e0fb2 100644 --- a/packages/documentdb-constants/src/queryOperators.ts +++ b/packages/documentdb-constants/src/queryOperators.ts @@ -434,14 +434,16 @@ const miscellaneousQueryOperators: readonly OperatorEntry[] = [ // Registration // --------------------------------------------------------------------------- -registerOperators([ - ...comparisonQueryOperators, - ...logicalQueryOperators, - ...elementQueryOperators, - ...evaluationQueryOperators, - ...geospatialOperators, - ...arrayQueryOperators, - ...bitwiseQueryOperators, - ...projectionOperators, - ...miscellaneousQueryOperators, -]); +export function loadQueryOperators(): void { + registerOperators([ + ...comparisonQueryOperators, + ...logicalQueryOperators, + ...elementQueryOperators, + ...evaluationQueryOperators, + ...geospatialOperators, + ...arrayQueryOperators, + ...bitwiseQueryOperators, + ...projectionOperators, + ...miscellaneousQueryOperators, + ]); +} diff --git a/packages/documentdb-constants/src/stages.ts b/packages/documentdb-constants/src/stages.ts index 59e5a212a..0752d7734 100644 --- a/packages/documentdb-constants/src/stages.ts +++ b/packages/documentdb-constants/src/stages.ts @@ -286,4 +286,6 @@ const aggregationPipelineStages: readonly OperatorEntry[] = [ // Registration // --------------------------------------------------------------------------- -registerOperators([...aggregationPipelineStages]); +export function loadStages(): void { + registerOperators([...aggregationPipelineStages]); +} diff --git a/packages/documentdb-constants/src/systemVariables.ts b/packages/documentdb-constants/src/systemVariables.ts index 4a404f7bb..219d04eb0 100644 --- a/packages/documentdb-constants/src/systemVariables.ts +++ b/packages/documentdb-constants/src/systemVariables.ts @@ -69,4 +69,6 @@ const systemVariables: readonly OperatorEntry[] = [ // Registration // --------------------------------------------------------------------------- -registerOperators([...systemVariables]); +export function loadSystemVariables(): void { + registerOperators([...systemVariables]); +} diff --git a/packages/documentdb-constants/src/updateOperators.ts b/packages/documentdb-constants/src/updateOperators.ts index 92c3d4b6b..a90f62fcd 100644 --- a/packages/documentdb-constants/src/updateOperators.ts +++ b/packages/documentdb-constants/src/updateOperators.ts @@ -198,4 +198,6 @@ const bitwiseUpdateOperators: readonly OperatorEntry[] = [ // Registration // --------------------------------------------------------------------------- -registerOperators([...fieldUpdateOperators, ...arrayUpdateOperators, ...bitwiseUpdateOperators]); +export function loadUpdateOperators(): void { + registerOperators([...fieldUpdateOperators, ...arrayUpdateOperators, ...bitwiseUpdateOperators]); +} diff --git a/packages/documentdb-constants/src/windowOperators.ts b/packages/documentdb-constants/src/windowOperators.ts index f1af97c8c..f15b412e1 100644 --- a/packages/documentdb-constants/src/windowOperators.ts +++ b/packages/documentdb-constants/src/windowOperators.ts @@ -228,4 +228,6 @@ const windowOperators: readonly OperatorEntry[] = [ // Registration // --------------------------------------------------------------------------- -registerOperators([...windowOperators]); +export function loadWindowOperators(): void { + registerOperators([...windowOperators]); +} From 5b994542932f83c514f497860255ce168cd61ab7 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 23 Feb 2026 16:26:23 +0000 Subject: [PATCH 044/128] fix(documentdb-constants): correct expr:bool and expr:comparison doc dir mappings in getDocLink --- packages/documentdb-constants/src/docLinks.test.ts | 10 ++++++++++ packages/documentdb-constants/src/docLinks.ts | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/documentdb-constants/src/docLinks.test.ts b/packages/documentdb-constants/src/docLinks.test.ts index 444b5423e..c79a53da9 100644 --- a/packages/documentdb-constants/src/docLinks.test.ts +++ b/packages/documentdb-constants/src/docLinks.test.ts @@ -68,5 +68,15 @@ describe('docLinks', () => { test('returns undefined for variable meta tag (no docs directory)', () => { expect(getDocLink('$$NOW', 'variable')).toBeUndefined(); }); + + test('generates correct URL for boolean expression operator', () => { + const link = getDocLink('$and', 'expr:bool'); + expect(link).toBe('https://learn.microsoft.com/en-us/azure/documentdb/operators/boolean-expression/$and'); + }); + + test('generates correct URL for comparison expression operator', () => { + const link = getDocLink('$eq', 'expr:comparison'); + expect(link).toBe('https://learn.microsoft.com/en-us/azure/documentdb/operators/comparison-expression/$eq'); + }); }); }); diff --git a/packages/documentdb-constants/src/docLinks.ts b/packages/documentdb-constants/src/docLinks.ts index 0df2ca0cb..460112548 100644 --- a/packages/documentdb-constants/src/docLinks.ts +++ b/packages/documentdb-constants/src/docLinks.ts @@ -33,8 +33,8 @@ const META_TO_DOC_DIR: Record = { accumulator: 'accumulators', 'expr:arith': 'arithmetic-expression', 'expr:array': 'array-expression', - 'expr:bool': 'logical-query', - 'expr:comparison': 'comparison-query', + 'expr:bool': 'boolean-expression', + 'expr:comparison': 'comparison-expression', 'expr:conditional': 'conditional-expression', 'expr:date': 'date-expression', 'expr:object': 'object-expression', From 1e74364009d4b041916b329c4eb0d4ddb152b197 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 23 Feb 2026 16:28:46 +0000 Subject: [PATCH 045/128] fix(documentdb-constants): correct expr:bool and expr:comparison doc dir mappings, update generator template --- .../scripts/generate-from-reference.ts | 19 ++++++-- .../documentdb-constants/src/accumulators.ts | 6 +-- .../src/expressionOperators.ts | 46 +++++++++---------- .../src/queryOperators.ts | 6 +-- packages/documentdb-constants/src/stages.ts | 2 +- .../src/updateOperators.ts | 12 ++--- .../src/windowOperators.ts | 30 ++++++------ 7 files changed, 66 insertions(+), 55 deletions(-) diff --git a/packages/documentdb-constants/scripts/generate-from-reference.ts b/packages/documentdb-constants/scripts/generate-from-reference.ts index b1a9de6a9..945c94aa0 100644 --- a/packages/documentdb-constants/scripts/generate-from-reference.ts +++ b/packages/documentdb-constants/scripts/generate-from-reference.ts @@ -613,12 +613,19 @@ import { registerOperators } from './getFilteredCompletions'; content += sectionsStr; - // Registration call - const allVarNames = specs.map((s) => `...${s.variableName}`).join(',\n '); + // Derive the exported load function name from the first spec's fileName + // e.g. "queryOperators" → "loadQueryOperators" + const fileName = specs[0]?.fileName ?? 'operators'; + const loadFnName = 'load' + fileName.charAt(0).toUpperCase() + fileName.slice(1); + + // Emit an explicit load function instead of a side-effect registration call + const allVarNames = specs.map((s) => `...${s.variableName}`).join(',\n '); content += `// ---------------------------------------------------------------------------\n`; content += `// Registration\n`; content += `// ---------------------------------------------------------------------------\n\n`; - content += `registerOperators([\n ${allVarNames},\n]);\n`; + content += `export function ${loadFnName}(): void {\n`; + content += ` registerOperators([\n ${allVarNames},\n ]);\n`; + content += `}\n`; return content; } @@ -649,8 +656,12 @@ function generateSection(spec: FileSpec, snippets: Map Date: Mon, 23 Feb 2026 16:29:46 +0000 Subject: [PATCH 046/128] fix(documentdb-constants): add idempotent registration guard to operator registry --- .../src/getFilteredCompletions.test.ts | 11 +++++++++++ .../src/getFilteredCompletions.ts | 13 ++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/packages/documentdb-constants/src/getFilteredCompletions.test.ts b/packages/documentdb-constants/src/getFilteredCompletions.test.ts index b188dbc47..046146832 100644 --- a/packages/documentdb-constants/src/getFilteredCompletions.test.ts +++ b/packages/documentdb-constants/src/getFilteredCompletions.test.ts @@ -17,6 +17,7 @@ import { WINDOW_COMPLETION_META, getAllCompletions, getFilteredCompletions, + loadOperators, } from './index'; describe('getFilteredCompletions', () => { @@ -220,3 +221,13 @@ describe('completion context presets', () => { expect(results.length).toBe(0); }); }); + +describe('registry idempotency', () => { + test('calling loadOperators() twice does not duplicate entries', () => { + const countBefore = getAllCompletions().length; + // loadOperators is re-exported from index + loadOperators(); + const countAfter = getAllCompletions().length; + expect(countAfter).toBe(countBefore); + }); +}); diff --git a/packages/documentdb-constants/src/getFilteredCompletions.ts b/packages/documentdb-constants/src/getFilteredCompletions.ts index fafdf2a13..fed7ba6e3 100644 --- a/packages/documentdb-constants/src/getFilteredCompletions.ts +++ b/packages/documentdb-constants/src/getFilteredCompletions.ts @@ -17,16 +17,26 @@ import { type CompletionFilter, type OperatorEntry } from './types'; * individual operator module files (queryOperators, stages, etc.) * via {@link registerOperators}. */ +const allOperatorsSet = new Set(); const allOperators: OperatorEntry[] = []; /** * Registers operator entries into the global registry. + * Duplicate entries (same value + meta key) are silently skipped, + * making repeated calls idempotent. + * * Called by each operator module during module initialization. * * @param entries - array of OperatorEntry objects to register */ export function registerOperators(entries: readonly OperatorEntry[]): void { - allOperators.push(...entries); + for (const entry of entries) { + const key = `${entry.value}|${entry.meta}`; + if (!allOperatorsSet.has(key)) { + allOperatorsSet.add(key); + allOperators.push(entry); + } + } } /** @@ -35,6 +45,7 @@ export function registerOperators(entries: readonly OperatorEntry[]): void { */ export function clearOperators(): void { allOperators.length = 0; + allOperatorsSet.clear(); } /** From df45bfbba2fbe3d60a0c2a32d477ba39e5dd5662 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 23 Feb 2026 16:30:57 +0000 Subject: [PATCH 047/128] fix(documentdb-constants): log ambiguous and unambiguous override fallbacks in applyOverrides --- .../scripts/generate-from-reference.ts | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/packages/documentdb-constants/scripts/generate-from-reference.ts b/packages/documentdb-constants/scripts/generate-from-reference.ts index 945c94aa0..056640077 100644 --- a/packages/documentdb-constants/scripts/generate-from-reference.ts +++ b/packages/documentdb-constants/scripts/generate-from-reference.ts @@ -364,19 +364,27 @@ function applyOverrides( // Try to find operators across all categories (override category // may not match dump category exactly for cross-category operators) for (const [opName, override] of opOverrides) { - let found = false; - for (const [, catOps] of categorizedOps) { + const matches: Array<{ category: string; op: ParsedOperator }> = []; + for (const [cat, catOps] of categorizedOps) { const op = catOps.find((o) => o.value === opName); - if (op) { - mergeOverride(op, override); - applied++; - found = true; - break; - } + if (op) matches.push({ category: cat, op }); } - if (!found) { + if (matches.length === 0) { console.warn(`⚠️ Override target not found: ${opName} in "${category}"`); missed++; + } else { + if (matches.length > 1) { + const catList = matches.map((m) => `"${m.category}"`).join(', '); + console.warn( + `⚠️ Ambiguous override fallback: "${opName}" — found in ${matches.length} categories: [${catList}]. Override from "${category}" applied to first match. Specify the correct category to disambiguate.`, + ); + } else { + console.log( + `ℹ️ Override fallback: "${opName}" not found in "${category}", applied to match in "${matches[0].category}".`, + ); + } + mergeOverride(matches[0].op, override); + applied++; } } continue; From cee31fac0a7b688bc4ff4260bb1abdb0c6599e9f Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 23 Feb 2026 16:52:27 +0000 Subject: [PATCH 048/128] fix(documentdb-constants): integrate script typecheck into build; revert generator inferred-link override (scraper ground truth takes precedence) --- packages/documentdb-constants/package.json | 3 +- .../scripts/generate-from-reference.ts | 7 +-- .../documentdb-constants/src/accumulators.ts | 6 +-- .../src/expressionOperators.ts | 44 +++++++++---------- packages/documentdb-constants/src/index.ts | 2 +- .../src/queryOperators.ts | 6 +-- packages/documentdb-constants/src/stages.ts | 2 +- .../src/updateOperators.ts | 12 ++--- .../src/windowOperators.ts | 30 ++++++------- 9 files changed, 54 insertions(+), 58 deletions(-) diff --git a/packages/documentdb-constants/package.json b/packages/documentdb-constants/package.json index 00fb83442..99f3fb017 100644 --- a/packages/documentdb-constants/package.json +++ b/packages/documentdb-constants/package.json @@ -8,10 +8,9 @@ "dist" ], "scripts": { - "build": "tsc -p .", + "build": "tsc -p . && tsc -p tsconfig.scripts.json --noEmit", "clean": "rimraf dist tsconfig.tsbuildinfo", "test": "jest --config jest.config.js", - "typecheck:scripts": "tsc -p tsconfig.scripts.json --noEmit", "prettier-fix": "prettier -w \"(scripts|src)/**/*.@(js|ts|jsx|tsx|json|md)\" \"./*.@(js|ts|jsx|tsx|json|md)\"", "scrape": "ts-node scripts/scrape-operator-docs.ts && prettier --write resources/scraped/operator-reference.md", "generate": "ts-node scripts/generate-from-reference.ts", diff --git a/packages/documentdb-constants/scripts/generate-from-reference.ts b/packages/documentdb-constants/scripts/generate-from-reference.ts index 056640077..a34e77c99 100644 --- a/packages/documentdb-constants/scripts/generate-from-reference.ts +++ b/packages/documentdb-constants/scripts/generate-from-reference.ts @@ -664,12 +664,9 @@ function generateSection(spec: FileSpec, snippets: Map Date: Mon, 23 Feb 2026 18:11:35 +0000 Subject: [PATCH 049/128] fix(documentdb-constants): return shallow copy from getAllCompletions to prevent registry mutation --- packages/documentdb-constants/src/getFilteredCompletions.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/documentdb-constants/src/getFilteredCompletions.ts b/packages/documentdb-constants/src/getFilteredCompletions.ts index fed7ba6e3..7de80d58a 100644 --- a/packages/documentdb-constants/src/getFilteredCompletions.ts +++ b/packages/documentdb-constants/src/getFilteredCompletions.ts @@ -89,7 +89,9 @@ export function getFilteredCompletions(filter: CompletionFilter): readonly Opera /** * Returns all operator entries (unfiltered). * Useful for validation, testing, and diagnostics. + * + * Returns a shallow copy so callers cannot mutate the internal registry. */ export function getAllCompletions(): readonly OperatorEntry[] { - return allOperators; + return [...allOperators]; } From cadb1f6c5460ab8deac8f50a75bc37a52ce00b79 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 23 Feb 2026 18:11:59 +0000 Subject: [PATCH 050/128] =?UTF-8?q?docs(documentdb-constants):=20expand=20?= =?UTF-8?q?returnType=20JSDoc=20=E2=80=94=20experimental=20field=20with=20?= =?UTF-8?q?planned=20values=20and=20usage=20context?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/documentdb-constants/src/types.ts | 31 +++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/packages/documentdb-constants/src/types.ts b/packages/documentdb-constants/src/types.ts index 92efe14e4..a5602406c 100644 --- a/packages/documentdb-constants/src/types.ts +++ b/packages/documentdb-constants/src/types.ts @@ -48,9 +48,34 @@ export interface OperatorEntry { readonly applicableBsonTypes?: readonly string[]; /** - * Operator return type or value type hint. - * Used by CompletionItemProvider for contextual snippet generation. - * Example: "$gt" → "same" (same type as input), "$size" → "number" + * @experimental Not yet populated by the generator; reserved for a future + * contextual-snippet feature. + * + * When populated, this field carries a hint about the type of value an operator + * produces or expects, enabling the CompletionItemProvider to tailor snippets + * and insert sensible placeholder values based on context. + * + * Planned values and their meanings: + * - `"number"` — operator always produces a number + * (e.g. `$size` on an array field → insert a numeric comparand) + * - `"boolean"` — operator produces true/false + * (e.g. `$and`, `$or` in expression context) + * - `"string"` — operator produces a string + * (e.g. `$concat`, `$toLower`) + * - `"array"` — operator produces an array + * (e.g. `$push` accumulator, `$concatArrays`) + * - `"date"` — operator produces a date + * (e.g. `$dateAdd`, `$toDate`) + * - `"same"` — operator produces the same type as its input + * (e.g. `$min`, `$max`, comparison operators like `$gt`) + * - `"object"` — operator produces a document/object + * (e.g. `$mergeObjects`) + * - `"any"` — return type is undetermined or context-dependent + * + * This field is intentionally absent from all current entries. The generator + * (`scripts/generate-from-reference.ts`) does not yet emit it. It will be + * populated in a follow-up pass once the `CompletionItemProvider` is ready + * to consume it. */ readonly returnType?: string; } From 782eb2d864de12537b7ad194bdc28c4364f20408 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 23 Feb 2026 18:12:40 +0000 Subject: [PATCH 051/128] =?UTF-8?q?fix(documentdb-constants):=20exit=201?= =?UTF-8?q?=20on=20network=20failures=20in=20scraper=20=E2=80=94=20404s=20?= =?UTF-8?q?are=20tolerated,=20connectivity=20errors=20are=20not?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scripts/scrape-operator-docs.ts | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/packages/documentdb-constants/scripts/scrape-operator-docs.ts b/packages/documentdb-constants/scripts/scrape-operator-docs.ts index c9a428f23..c1a6026ee 100644 --- a/packages/documentdb-constants/scripts/scrape-operator-docs.ts +++ b/packages/documentdb-constants/scripts/scrape-operator-docs.ts @@ -645,7 +645,11 @@ async function buildGlobalFileIndex(): Promise> { return index; } -async function fetchOperatorDocs(operators: OperatorInfo[]): Promise { +interface FetchOperatorDocsResult { + failureDetails: { operator: string; category: string; reason: string }[]; +} + +async function fetchOperatorDocs(operators: OperatorInfo[]): Promise { // Build a global index of all doc files to use as fallback console.log(' Building global file index from GitHub API...'); const globalIndex = await buildGlobalFileIndex(); @@ -789,6 +793,8 @@ async function fetchOperatorDocs(operators: OperatorInfo[]): Promise { console.log(''); } } + + return { failureDetails }; } // --------------------------------------------------------------------------- @@ -918,9 +924,24 @@ async function main(): Promise { console.log(''); // Phase 2: Fetch per-operator docs - await fetchOperatorDocs(operators); + const { failureDetails } = await fetchOperatorDocs(operators); console.log(''); + // Fail immediately on network errors (transient connectivity problems that + // exhaust all retries). 404s are expected for operators without dedicated + // doc pages and do not abort the run. + const networkFailures = failureDetails.filter((f) => f.reason.startsWith('NetworkError:')); + if (networkFailures.length > 0) { + console.error( + `ERROR: ${networkFailures.length} operator(s) failed due to network errors (not 404). Aborting.`, + ); + for (const f of networkFailures) { + console.error(` - ${f.operator} (${f.category}): ${f.reason}`); + } + process.exit(1); + } + + // Phase 3: Generate dump console.log(' Phase 3: Generating scraped/operator-reference.md...'); const dump = generateDump(operators); From 812702cea3def68a5ec8941a8afc6aab91cd0e47 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 23 Feb 2026 18:25:12 +0000 Subject: [PATCH 052/128] docs(documentdb-constants): note that getFilteredCompletions already returns a safe copy via Array.filter --- packages/documentdb-constants/src/getFilteredCompletions.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/documentdb-constants/src/getFilteredCompletions.ts b/packages/documentdb-constants/src/getFilteredCompletions.ts index 7de80d58a..170353f78 100644 --- a/packages/documentdb-constants/src/getFilteredCompletions.ts +++ b/packages/documentdb-constants/src/getFilteredCompletions.ts @@ -61,7 +61,9 @@ export function clearOperators(): void { * `applicableBsonTypes` (universal operators) are always included. * * @param filter - the filtering criteria - * @returns matching operator entries (readonly array) + * @returns matching operator entries as a new array — `Array.prototype.filter` + * always allocates a fresh array, so callers cannot mutate the internal registry + * through this return value. */ export function getFilteredCompletions(filter: CompletionFilter): readonly OperatorEntry[] { return allOperators.filter((entry) => { From bc5adc38684682ce489a09c29d2f1ca16cf1fa7a Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 23 Feb 2026 18:29:36 +0000 Subject: [PATCH 053/128] chore: package-lock.json update --- package-lock.json | 19136 +++++++++++++++++++------------------------- 1 file changed, 8452 insertions(+), 10684 deletions(-) diff --git a/package-lock.json b/package-lock.json index cf28dcd8b..010535649 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6055,16 +6055,6 @@ "@types/send": "*" } }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/hast": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", @@ -9798,334 +9788,272 @@ "dev": true, "license": "MIT" }, - "node_modules/create-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "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-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" + "cross-spawn": "^7.0.1" }, "bin": { - "create-jest": "bin/create-jest.js" + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" } }, - "node_modules/create-jest/node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 8" } }, - "node_modules/create-jest/node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", "dev": true, - "license": "MIT", - "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - }, + "license": "BSD-3-Clause", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "*" } }, - "node_modules/create-jest/node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "node_modules/css-loader": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz", + "integrity": "sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA==", "dev": true, "license": "MIT", "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/create-jest/node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "jest-get-type": "^29.6.3" + "node": ">= 18.12.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/create-jest/node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/create-jest/node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.27.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } } }, - "node_modules/create-jest/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "@sinclair/typebox": "^0.27.8" + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/create-jest/node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, + "license": "BSD-2-Clause", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/create-jest/node_modules/@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" + "bin": { + "cssesc": "bin/cssesc" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=4" } }, - "node_modules/create-jest/node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/create-jest/node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" } }, - "node_modules/create-jest/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/create-jest/node_modules/@sinclair/typebox": { - "version": "0.27.10", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", - "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==", - "dev": true, + "node_modules/dayjs": { + "version": "1.11.19", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", + "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", "license": "MIT" }, - "node_modules/create-jest/node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/create-jest/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } + "license": "MIT" }, - "node_modules/create-jest/node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "dev": true, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" + "ms": "^2.1.3" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6.0" }, - "peerDependencies": { - "@babel/core": "^7.8.0" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/create-jest/node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/create-jest/node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "dev": true, + "node_modules/decode-named-character-reference": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", + "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", "license": "MIT", "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" + "character-entities": "^2.0.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/create-jest/node_modules/babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "dev": true, "license": "MIT", "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" + "mimic-response": "^3.1.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/create-jest/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", "dev": true, "license": "MIT", "engines": { @@ -10135,773 +10063,632 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/create-jest/node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" + "node_modules/dedent": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", + "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true } - ], + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, "license": "MIT", + "optional": true, "engines": { - "node": ">=8" + "node": ">=4.0.0" } }, - "node_modules/create-jest/node_modules/cjs-module-lexer": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", - "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, "license": "MIT" }, - "node_modules/create-jest/node_modules/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", - "dev": true, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "license": "MIT", - "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/create-jest/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "node_modules/deepmerge-json": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/deepmerge-json/-/deepmerge-json-1.5.0.tgz", + "integrity": "sha512-jZRrDmBKjmGcqMFEUJ14FjMJwm05Qaked+1vxaALRtF0UAl7lPU8OLWXFxvoeg3jbQM249VPFVn8g2znaQkEtA==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=4.0.0" } }, - "node_modules/create-jest/node_modules/jest-circus": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", - "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", - "dev": true, + "node_modules/default-browser": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.4.0.tgz", + "integrity": "sha512-XDuvSq38Hr1MdN47EDvYtx3U0MTqpCEn+F6ft8z2vYDzMrvQhVp0ui9oQdqW3MvK3vqUETglt1tVGgjLuJ5izg==", "license": "MIT", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.7.0", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.7.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/create-jest/node_modules/jest-config": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", - "dev": true, + "node_modules/default-browser-id": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" + "node": ">=18" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/create-jest/node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "node_modules/defaults": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-2.0.2.tgz", + "integrity": "sha512-cuIw0PImdp76AOfgkjbW4VhQODRmNNcKR73vdCH5cLd/ifj7aamfoXvYgfGkEAjNJZ3ozMIy9Gu2LutUkGEPbA==", "dev": true, "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/create-jest/node_modules/jest-docblock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", - "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", "dev": true, "license": "MIT", - "dependencies": { - "detect-newline": "^3.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" } }, - "node_modules/create-jest/node_modules/jest-each": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", - "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/create-jest/node_modules/jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", - "dev": true, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/create-jest/node_modules/jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" }, - "optionalDependencies": { - "fsevents": "^2.3.2" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/create-jest/node_modules/jest-leak-detector": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", - "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true, "license": "MIT", - "dependencies": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.4.0" } }, - "node_modules/create-jest/node_modules/jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10" } }, - "node_modules/create-jest/node_modules/jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.8" } }, - "node_modules/create-jest/node_modules/jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", - "dev": true, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6" } }, - "node_modules/create-jest/node_modules/jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "dev": true, "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/create-jest/node_modules/jest-resolve": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", - "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - }, + "license": "Apache-2.0", + "optional": true, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/create-jest/node_modules/jest-runner": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/environment": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-leak-detector": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-resolve": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-util": "^29.7.0", - "jest-watcher": "^29.7.0", - "jest-worker": "^29.7.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/create-jest/node_modules/jest-runtime": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", "dev": true, + "license": "MIT" + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", "license": "MIT", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" + "dequal": "^2.0.0" }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/diff": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "dev": true, + "license": "BSD-3-Clause", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.3.1" } }, - "node_modules/create-jest/node_modules/jest-snapshot": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "node_modules/discontinuous-range": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", + "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==", + "license": "MIT" + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" + "@leichtgewicht/ip-codec": "^2.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6" } }, - "node_modules/create-jest/node_modules/jest-snapshot/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" }, "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/create-jest/node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/create-jest/node_modules/jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" + "domelementtype": "^2.3.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/create-jest/node_modules/jest-watcher": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/create-jest/node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" } }, - "node_modules/create-jest/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true, - "license": "MIT", + "license": "MIT" + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/editions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/editions/-/editions-6.22.0.tgz", + "integrity": "sha512-UgGlf8IW75je7HZjNDpJdCv4cGJWIi6yumFdZ0R7A8/CIhQiWUjyGLCxdHpd8bmyD1gnkfUNK0oeOXqUS2cpfQ==", + "dev": true, + "license": "Artistic-2.0", "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "version-range": "^4.15.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "ecmascript": ">= es5", + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" } }, - "node_modules/create-jest/node_modules/pure-rand": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", - "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], "license": "MIT" }, - "node_modules/create-jest/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "node_modules/electron-to-chromium": { + "version": "1.5.286", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", + "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", "dev": true, + "license": "ISC" + }, + "node_modules/embla-carousel": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz", + "integrity": "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==", "license": "MIT" }, - "node_modules/create-jest/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/embla-carousel-autoplay": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel-autoplay/-/embla-carousel-autoplay-8.6.0.tgz", + "integrity": "sha512-OBu5G3nwaSXkZCo1A6LTaFMZ8EpkYbwIaH+bPqdBnDGQ2fh4+NbzjXjs2SktoPNKCtflfVMc75njaDHOYXcrsA==", + "license": "MIT", + "peerDependencies": { + "embla-carousel": "8.6.0" } }, - "node_modules/create-jest/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/embla-carousel-fade": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel-fade/-/embla-carousel-fade-8.6.0.tgz", + "integrity": "sha512-qaYsx5mwCz72ZrjlsXgs1nKejSrW+UhkbOMwLgfRT7w2LtdEB03nPRI06GHuHv5ac2USvbEiX2/nAHctcDwvpg==", + "license": "MIT", + "peerDependencies": { + "embla-carousel": "8.6.0" + } + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true, "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, - "node_modules/create-jest/node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "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": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } + "license": "MIT" }, - "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==", + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">= 4" + } }, - "node_modules/cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "dev": true, "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "bin": { - "cross-env": "src/bin/cross-env.js", - "cross-env-shell": "src/bin/cross-env-shell.js" - }, "engines": { - "node": ">=10.14", - "npm": ">=6", - "yarn": ">=1" + "node": ">= 0.8" } }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "node_modules/encoding-sniffer": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", + "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==", "dev": true, "license": "MIT", "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" }, - "engines": { - "node": ">= 8" + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" } }, - "node_modules/crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": "*" + "license": "MIT", + "optional": true, + "dependencies": { + "once": "^1.4.0" } }, - "node_modules/css-loader": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz", - "integrity": "sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA==", + "node_modules/enhanced-resolve": { + "version": "5.19.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz", + "integrity": "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==", "dev": true, "license": "MIT", "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" + "graceful-fs": "^4.2.4", + "tapable": "^2.3.0" }, "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.27.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/css-select": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", - "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "node": ">=10.13.0" } }, - "node_modules/css-what": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", - "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, "license": "BSD-2-Clause", "engines": { - "node": ">= 6" + "node": ">=0.12" }, "funding": { - "url": "https://github.com/sponsors/fb55" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "node_modules/envinfo": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.20.0.tgz", + "integrity": "sha512-+zUomDcLXsVkQ37vUqWBvQwLaLlj8eZPSi61llaEFAVBY5mhcXdaSw1pSJVl4yTYD5g/gEfpNl28YYk4IPvrrg==", "dev": true, "license": "MIT", "bin": { - "cssesc": "bin/cssesc" + "envinfo": "dist/cli.js" }, "engines": { "node": ">=4" } }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "license": "MIT" - }, - "node_modules/data-view-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", - "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", "dev": true, "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, "engines": { - "node": ">= 0.4" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/data-view-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", - "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/inspect-js" + "is-arrayish": "^0.2.1" } }, - "node_modules/data-view-byte-offset": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", - "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", + "stackframe": "^1.3.4" + } + }, + "node_modules/es-abstract": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" }, "engines": { "node": ">= 0.4" @@ -10910,1824 +10697,1691 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/dayjs": { - "version": "1.11.19", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", - "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", - "license": "MIT" - }, - "node_modules/debounce": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", - "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">= 0.4" } }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.4" } }, - "node_modules/decode-named-character-reference": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", - "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", + "node_modules/es-module-lexer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, "license": "MIT", "dependencies": { - "character-entities": "^2.0.0" + "es-errors": "^1.3.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "engines": { + "node": ">= 0.4" } }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "dev": true, "license": "MIT", "dependencies": { - "mimic-response": "^3.1.0" + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.4" } }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "hasown": "^2.0.2" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">= 0.4" } }, - "node_modules/dedent": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", - "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==", + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dev": true, "license": "MIT", - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "node_modules/es-toolkit": { + "version": "1.42.0", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.42.0.tgz", + "integrity": "sha512-SLHIyY7VfDJBM8clz4+T2oquwTQxEzu263AyhVK4jREOAwJ+8eebaa4wM3nlvnAqhDrMm2EsA6hWHaQsMPQ1nA==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", - "optional": true, "engines": { - "node": ">=4.0.0" + "node": ">=6" } }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "dev": true, "license": "MIT" }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/deepmerge-json": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/deepmerge-json/-/deepmerge-json-1.5.0.tgz", - "integrity": "sha512-jZRrDmBKjmGcqMFEUJ14FjMJwm05Qaked+1vxaALRtF0UAl7lPU8OLWXFxvoeg3jbQM249VPFVn8g2znaQkEtA==", + "node_modules/eslint": { + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", + "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "dev": true, "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/default-browser": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.4.0.tgz", - "integrity": "sha512-XDuvSq38Hr1MdN47EDvYtx3U0MTqpCEn+F6ft8z2vYDzMrvQhVp0ui9oQdqW3MvK3vqUETglt1tVGgjLuJ5izg==", - "license": "MIT", "dependencies": { - "bundle-name": "^4.1.0", - "default-browser-id": "^5.0.0" + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.1", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" }, - "engines": { - "node": ">=18" + "bin": { + "eslint": "bin/eslint.js" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser-id": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", - "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", - "license": "MIT", "engines": { - "node": ">=18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, - "node_modules/defaults": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-2.0.2.tgz", - "integrity": "sha512-cuIw0PImdp76AOfgkjbW4VhQODRmNNcKR73vdCH5cLd/ifj7aamfoXvYgfGkEAjNJZ3ozMIy9Gu2LutUkGEPbA==", + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "ms": "^2.1.1" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "node_modules/eslint-module-utils": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", "dev": true, "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" + "debug": "^3.2.7" }, "engines": { - "node": ">= 0.4" + "node": ">=4" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, - "node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "ms": "^2.1.1" } }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" }, "engines": { - "node": ">= 0.4" + "node": ">=4" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.10" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "ms": "^2.1.1" } }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": "*" } }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=8" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "node_modules/eslint-plugin-jest": { + "version": "29.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.1.0.tgz", + "integrity": "sha512-LabxXbASXVjguqL+kBHTPMf3gUeSqwH4fsrEyHTY/MCs42I/p9+ctg09SJpYiD8eGaIsP6GwYr5xW6xWS9XgZg==", "dev": true, "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^8.0.0" + }, "engines": { - "node": ">=8" + "node": "^20.12.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", + "jest": "*" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } } }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "node_modules/eslint-plugin-license-header": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-license-header/-/eslint-plugin-license-header-0.8.0.tgz", + "integrity": "sha512-khTCz6G3JdoQfwrtY4XKl98KW4PpnWUKuFx8v+twIRhJADEyYglMDC0td8It75C1MZ88gcvMusWuUlJsos7gYg==", "dev": true, - "license": "MIT" - }, - "node_modules/devlop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", "license": "MIT", "dependencies": { - "dequal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "requireindex": "^1.2.0" } }, - "node_modules/diff": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", - "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "node_modules/eslint-plugin-mocha": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-11.2.0.tgz", + "integrity": "sha512-nMdy3tEXZac8AH5Z/9hwUkSfWu8xHf4XqwB5UEQzyTQGKcNlgFeciRAjLjliIKC3dR1Ex/a2/5sqgQzvYRkkkA==", "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.1", + "globals": "^15.14.0" + }, + "peerDependencies": { + "eslint": ">=9.0.0" } }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "node_modules/eslint-plugin-mocha/node_modules/globals": { + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", "dev": true, "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==", - "license": "MIT" - }, - "node_modules/dns-packet": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", - "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "@leichtgewicht/ip-codec": "^2.0.1" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">=6" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, "engines": { - "node": ">=0.10.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "domelementtype": "^2.3.0" - }, + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 4" + "node": ">=10" }, "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/domutils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", - "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 0.4" + "node": ">=10.13.0" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, "license": "MIT" }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "license": "Apache-2.0", + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", "dependencies": { - "safe-buffer": "^5.0.1" + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "node_modules/editions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/editions/-/editions-6.22.0.tgz", - "integrity": "sha512-UgGlf8IW75je7HZjNDpJdCv4cGJWIi6yumFdZ0R7A8/CIhQiWUjyGLCxdHpd8bmyD1gnkfUNK0oeOXqUS2cpfQ==", + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, - "license": "Artistic-2.0", + "license": "BSD-2-Clause", "dependencies": { - "version-range": "^4.15.0" + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "ecmascript": ">= es5", - "node": ">=4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://bevry.me/fund" + "url": "https://opencollective.com/eslint" } }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true, - "license": "MIT" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.286", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", - "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, - "license": "ISC" - }, - "node_modules/embla-carousel": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz", - "integrity": "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==", - "license": "MIT" - }, - "node_modules/embla-carousel-autoplay": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/embla-carousel-autoplay/-/embla-carousel-autoplay-8.6.0.tgz", - "integrity": "sha512-OBu5G3nwaSXkZCo1A6LTaFMZ8EpkYbwIaH+bPqdBnDGQ2fh4+NbzjXjs2SktoPNKCtflfVMc75njaDHOYXcrsA==", - "license": "MIT", - "peerDependencies": { - "embla-carousel": "8.6.0" + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" } }, - "node_modules/embla-carousel-fade": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/embla-carousel-fade/-/embla-carousel-fade-8.6.0.tgz", - "integrity": "sha512-qaYsx5mwCz72ZrjlsXgs1nKejSrW+UhkbOMwLgfRT7w2LtdEB03nPRI06GHuHv5ac2USvbEiX2/nAHctcDwvpg==", - "license": "MIT", - "peerDependencies": { - "embla-carousel": "8.6.0" + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" } }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" + "engines": { + "node": ">=4.0" } }, - "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==", + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "license": "MIT" + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } }, - "node_modules/emojis-list": { + "node_modules/estree-util-is-identifier-name": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">= 4" + "node": ">=0.10.0" } }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">= 0.6" } }, - "node_modules/encoding-sniffer": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", - "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==", + "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", - "dependencies": { - "iconv-lite": "^0.6.3", - "whatwg-encoding": "^3.1.1" - }, - "funding": { - "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + "engines": { + "node": ">=0.8.x" } }, - "node_modules/end-of-stream": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", - "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", "dev": true, - "license": "MIT", - "optional": true, + "license": "Apache-2.0", "dependencies": { - "once": "^1.4.0" + "bare-events": "^2.7.0" } }, - "node_modules/enhanced-resolve": { - "version": "5.19.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz", - "integrity": "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==", + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.3.0" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" + "node": ">=10" }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/envinfo": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.20.0.tgz", - "integrity": "sha512-+zUomDcLXsVkQ37vUqWBvQwLaLlj8eZPSi61llaEFAVBY5mhcXdaSw1pSJVl4yTYD5g/gEfpNl28YYk4IPvrrg==", + "node_modules/exit-x": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz", + "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==", "dev": true, "license": "MIT", - "bin": { - "envinfo": "dist/cli.js" - }, "engines": { - "node": ">=4" + "node": ">= 0.8.0" } }, - "node_modules/environment": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", - "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", "dev": true, - "license": "MIT", + "license": "(MIT OR WTFPL)", + "optional": true, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/error-ex": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", - "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" + "node": ">=6" } }, - "node_modules/error-stack-parser": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", - "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "node_modules/expect": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", + "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", "dev": true, "license": "MIT", "dependencies": { - "stackframe": "^1.3.4" + "@jest/expect-utils": "30.2.0", + "@jest/get-type": "30.1.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-util": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/es-abstract": { - "version": "1.24.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", - "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", + "node_modules/express": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", "dev": true, "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.14.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" }, "engines": { - "node": ">= 0.4" + "node": ">= 0.10.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.4" + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/es-module-lexer": { + "node_modules/express/node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", - "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true, "license": "MIT" }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "node_modules/ext-list": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", + "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0" + "mime-db": "^1.28.0" }, "engines": { - "node": ">= 0.4" + "node": ">=0.10.0" } }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "node_modules/ext-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", + "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" + "ext-list": "^2.0.0", + "sort-keys-length": "^1.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=4" } }, - "node_modules/es-shim-unscopables": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", - "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } + "license": "MIT" }, - "node_modules/es-to-primitive": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", - "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, "license": "MIT", "dependencies": { - "is-callable": "^1.2.7", - "is-date-object": "^1.0.5", - "is-symbol": "^1.0.4" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8.6.0" } }, - "node_modules/es-toolkit": { - "version": "1.42.0", - "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.42.0.tgz", - "integrity": "sha512-SLHIyY7VfDJBM8clz4+T2oquwTQxEzu263AyhVK4jREOAwJ+8eebaa4wM3nlvnAqhDrMm2EsA6hWHaQsMPQ1nA==", - "license": "MIT", - "workspaces": [ - "docs", - "benchmarks" - ] + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "license": "MIT" }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } + "license": "MIT" }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", "dev": true, - "license": "MIT" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" }, - "node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 4.9.1" } }, - "node_modules/eslint": { - "version": "9.39.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", - "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@eslint-community/eslint-utils": "^4.8.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.1", - "@eslint/config-helpers": "^0.4.2", - "@eslint/core": "^0.17.0", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.39.1", - "@eslint/plugin-kit": "^0.4.1", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@types/estree": "^1.0.6", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.4.0", - "eslint-visitor-keys": "^4.2.1", - "espree": "^10.4.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "websocket-driver": ">=0.5.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } + "node": ">=0.8.0" } }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", "dev": true, "license": "MIT", "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" + "pend": "~1.2.0" } }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "license": "MIT" + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.1" + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/eslint-module-utils": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", - "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", + "node_modules/file-type": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-20.5.0.tgz", + "integrity": "sha512-BfHZtG/l9iMm4Ecianu7P8HRD2tBHLtjXinm4X62XBOYzi7CYA7jyqfJzOvXHqzVrVPYqBo2/GvbARMaaJkKVg==", "dev": true, "license": "MIT", "dependencies": { - "debug": "^3.2.7" + "@tokenizer/inflate": "^0.2.6", + "strtok3": "^10.2.0", + "token-types": "^6.0.0", + "uint8array-extras": "^1.4.0" }, "engines": { - "node": ">=4" + "node": ">=18" }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" } }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/filename-reserved-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-3.0.0.tgz", + "integrity": "sha512-hn4cQfU6GOT/7cFHXBqeBg2TbrMBgdD0kcjLhvSQYYwm3s4B6cjvBfb7nBALJLAXqmU5xajSa7X2NnUud/VCdw==", "dev": true, "license": "MIT", - "dependencies": { - "ms": "^2.1.1" + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-plugin-import": { - "version": "2.32.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", - "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "node_modules/filenamify": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-6.0.0.tgz", + "integrity": "sha512-vqIlNogKeyD3yzrm0yhRMQg8hOVwYcYRfjEoODd49iCprMn4HL85gK3HcykQE53EPIpX3HcAbGA5ELQv216dAQ==", "dev": true, "license": "MIT", "dependencies": { - "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.9", - "array.prototype.findlastindex": "^1.2.6", - "array.prototype.flat": "^1.3.3", - "array.prototype.flatmap": "^1.3.3", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.1", - "hasown": "^2.0.2", - "is-core-module": "^2.16.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "object.groupby": "^1.0.3", - "object.values": "^1.2.1", - "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.9", - "tsconfig-paths": "^3.15.0" + "filename-reserved-regex": "^3.0.0" }, "engines": { - "node": ">=4" + "node": ">=16" }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.1" + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" } }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "ms": "2.0.0" } }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } + "license": "MIT" }, - "node_modules/eslint-plugin-jest": { - "version": "29.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.1.0.tgz", - "integrity": "sha512-LabxXbASXVjguqL+kBHTPMf3gUeSqwH4fsrEyHTY/MCs42I/p9+ctg09SJpYiD8eGaIsP6GwYr5xW6xWS9XgZg==", + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^8.0.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": "^20.12.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^8.0.0", - "eslint": "^8.57.0 || ^9.0.0", - "jest": "*" + "node": ">=10" }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - }, - "jest": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-plugin-license-header": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-license-header/-/eslint-plugin-license-header-0.8.0.tgz", - "integrity": "sha512-khTCz6G3JdoQfwrtY4XKl98KW4PpnWUKuFx8v+twIRhJADEyYglMDC0td8It75C1MZ88gcvMusWuUlJsos7gYg==", + "node_modules/find-versions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-5.1.0.tgz", + "integrity": "sha512-+iwzCJ7C5v5KgcBuueqVoNiHVoQpwiUK5XFLjf0affFTep+Wcw93tPvmb8tqujDNmzhBDPddnWV/qgWSXgq+Hg==", "dev": true, "license": "MIT", "dependencies": { - "requireindex": "^1.2.0" + "semver-regex": "^4.0.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-plugin-mocha": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-11.2.0.tgz", - "integrity": "sha512-nMdy3tEXZac8AH5Z/9hwUkSfWu8xHf4XqwB5UEQzyTQGKcNlgFeciRAjLjliIKC3dR1Ex/a2/5sqgQzvYRkkkA==", + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.1", - "globals": "^15.14.0" + "flatted": "^3.2.9", + "keyv": "^4.5.4" }, - "peerDependencies": { - "eslint": ">=9.0.0" + "engines": { + "node": ">=16" } }, - "node_modules/eslint-plugin-mocha/node_modules/globals": { - "version": "15.15.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", - "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dev": true, "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, "engines": { - "node": ">=18" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "dev": true, - "license": "BSD-2-Clause", + "license": "ISC", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=14" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "license": "Apache-2.0", + "license": "ISC", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=14" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">= 6" } }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/form-data-encoder": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", + "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": ">= 14.17" } }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.6" } }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, + "license": "MIT", "engines": { - "node": ">=10.13.0" + "node": ">= 0.6" } }, - "node_modules/eslint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/fs-extra": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.2.tgz", + "integrity": "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": "*" + "node": ">=14.14" } }, - "node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.15.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" - }, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "estraverse": "^5.1.0" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" }, "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" + "node": ">= 0.4" }, - "engines": { - "node": ">=4.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-util-is-identifier-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", - "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", "license": "MIT", "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=6.9.0" } }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, - "license": "MIT", + "license": "ISC", "engines": { - "node": ">=0.8.x" + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/events-universal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", - "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "node_modules/get-east-asian-width": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", + "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "bare-events": "^2.7.0" + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.8.0" + "node": ">=8.0.0" } }, - "node_modules/exit-x": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz", - "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==", + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "dev": true, "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, "engines": { - "node": ">= 0.8.0" + "node": ">= 0.4" } }, - "node_modules/expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "node_modules/get-stdin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", + "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", "dev": true, - "license": "(MIT OR WTFPL)", - "optional": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/expect": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", - "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/expect-utils": "30.2.0", - "@jest/get-type": "30.1.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", - "jest-util": "30.2.0" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/express": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", - "dev": true, - "license": "MIT", + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "~1.20.3", - "content-disposition": "~0.5.4", - "content-type": "~1.0.4", - "cookie": "~0.7.1", - "cookie-signature": "~1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.3.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "~0.1.12", - "proxy-addr": "~2.0.7", - "qs": "~6.14.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "~0.19.0", - "serve-static": "~1.16.2", - "setprototypeof": "1.2.0", - "statuses": "~2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" }, "engines": { - "node": ">= 0.10.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", "dev": true, "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, - "license": "MIT" + "optional": true }, - "node_modules/ext-list": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", - "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", + "node_modules/glob": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-12.0.0.tgz", + "integrity": "sha512-5Qcll1z7IKgHr5g485ePDdHcNQY0k2dtv/bjYy0iuyGxQw2qSOiiXUXJ+AYQpg3HNoUMHqAruX478Jeev7UULw==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "mime-db": "^1.28.0" + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=0.10.0" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/ext-name": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", - "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "ext-list": "^2.0.0", - "sort-keys-length": "^1.0.0" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=4" + "node": ">= 6" } }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "license": "MIT" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "node_modules/glob-to-regex.js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/glob-to-regex.js/-/glob-to-regex.js-1.2.0.tgz", + "integrity": "sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==", "dev": true, - "license": "MIT" + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } }, - "node_modules/fast-fifo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", - "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true, - "license": "MIT" + "license": "BSD-2-Clause" }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "node_modules/glob/node_modules/minimatch": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" + "@isaacs/brace-expansion": "^5.0.0" }, "engines": { - "node": ">=8.6.0" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "node_modules/globals": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", "dev": true, "license": "MIT", "engines": { - "node": ">= 4.9.1" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "reusify": "^1.0.4" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "node_modules/globby": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", + "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "websocket-driver": ">=0.5.1" + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.3", + "path-type": "^6.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.3.0" }, "engines": { - "node": ">=0.8.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "bser": "2.1.1" - } - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/fflate": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", - "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", - "license": "MIT" - }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "node_modules/globby/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, "license": "MIT", - "dependencies": { - "flat-cache": "^4.0.0" - }, "engines": { - "node": ">=16.0.0" + "node": ">= 4" } }, - "node_modules/file-type": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-20.5.0.tgz", - "integrity": "sha512-BfHZtG/l9iMm4Ecianu7P8HRD2tBHLtjXinm4X62XBOYzi7CYA7jyqfJzOvXHqzVrVPYqBo2/GvbARMaaJkKVg==", + "node_modules/globby/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "dev": true, "license": "MIT", - "dependencies": { - "@tokenizer/inflate": "^0.2.6", - "strtok3": "^10.2.0", - "token-types": "^6.0.0", - "uint8array-extras": "^1.4.0" - }, "engines": { - "node": ">=18" + "node": ">=14.16" }, "funding": { - "url": "https://github.com/sindresorhus/file-type?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/filename-reserved-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-3.0.0.tgz", - "integrity": "sha512-hn4cQfU6GOT/7cFHXBqeBg2TbrMBgdD0kcjLhvSQYYwm3s4B6cjvBfb7nBALJLAXqmU5xajSa7X2NnUud/VCdw==", + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "dev": true, "license": "MIT", "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/filenamify": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-6.0.0.tgz", - "integrity": "sha512-vqIlNogKeyD3yzrm0yhRMQg8hOVwYcYRfjEoODd49iCprMn4HL85gK3HcykQE53EPIpX3HcAbGA5ELQv216dAQ==", + "node_modules/got": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/got/-/got-13.0.0.tgz", + "integrity": "sha512-XfBk1CxOOScDcMr9O1yKkNaQyy865NbYs+F7dr4H0LZMVgCj2Le59k6PqbNHoL5ToeaEQUYh6c6yMfVcc6SJxA==", "dev": true, "license": "MIT", "dependencies": { - "filename-reserved-regex": "^3.0.0" + "@sindresorhus/is": "^5.2.0", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^10.2.8", + "decompress-response": "^6.0.0", + "form-data-encoder": "^2.1.2", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^3.0.0" }, "engines": { "node": ">=16" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" + "url": "https://github.com/sindresorhus/got?sponsor=1" } }, - "node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true, - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } + "license": "ISC" }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } + "license": "MIT" }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", "dev": true, "license": "MIT" }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" }, "engines": { - "node": ">=10" + "node": ">=0.4.7" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optionalDependencies": { + "uglify-js": "^3.1.4" } }, - "node_modules/find-versions": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-5.1.0.tgz", - "integrity": "sha512-+iwzCJ7C5v5KgcBuueqVoNiHVoQpwiUK5XFLjf0affFTep+Wcw93tPvmb8tqujDNmzhBDPddnWV/qgWSXgq+Hg==", + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", "dev": true, "license": "MIT", - "dependencies": { - "semver-regex": "^4.0.5" - }, "engines": { - "node": ">=12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "BSD-3-Clause", - "bin": { - "flat": "cli.js" + "license": "MIT", + "engines": { + "node": ">=8" } }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "license": "MIT", "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" + "es-define-property": "^1.0.0" }, - "engines": { - "node": ">=16" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "dev": true, - "license": "ISC" - }, - "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, "engines": { - "node": ">=4.0" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/for-each": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", - "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7" - }, "engines": { "node": ">= 0.4" }, @@ -12735,275 +12389,363 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" + "has-symbols": "^1.0.3" }, "engines": { - "node": ">=14" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">= 0.4" } }, - "node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", - "dev": true, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", "license": "MIT", "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" }, - "engines": { - "node": ">= 6" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/form-data-encoder": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", - "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", - "dev": true, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", "license": "MIT", - "engines": { - "node": ">= 14.17" + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "license": "MIT", - "engines": { - "node": ">= 0.6" + "bin": { + "he": "bin/he" } }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=10" } }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/fs-extra": { - "version": "11.3.2", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.2.tgz", - "integrity": "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==", + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", "dev": true, "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" } }, - "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==", + "node_modules/html-entities": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", + "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", "dev": true, - "license": "ISC" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT" }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true, - "hasInstallScript": true, + "license": "MIT" + }, + "node_modules/html-to-text": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-8.2.1.tgz", + "integrity": "sha512-aN/3JvAk8qFsWVeE9InWAWueLXrbkoVZy0TkzaGhoRBC2gCFEeRLDDJN3/ijIGHohy6H+SZzUQWN/hcYtaPK8w==", "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "@selderee/plugin-htmlparser2": "^0.6.0", + "deepmerge": "^4.2.2", + "he": "^1.2.0", + "htmlparser2": "^6.1.0", + "minimist": "^1.2.6", + "selderee": "^0.6.0" + }, + "bin": { + "html-to-text": "bin/cli.js" + }, "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">=10.23.2" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, + "node_modules/html-to-text/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/function.prototype.name": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", - "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", - "dev": true, - "license": "MIT", + "node_modules/html-to-text/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "license": "BSD-2-Clause", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "functions-have-names": "^1.2.3", - "hasown": "^2.0.2", - "is-callable": "^1.2.7" + "domelementtype": "^2.2.0" }, "engines": { - "node": ">= 0.4" + "node": ">= 4" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "license": "MIT", + "node_modules/html-to-text/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/generator-function": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", - "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" + "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, + "node_modules/html-to-text/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/html-to-text/node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], "license": "MIT", - "engines": { - "node": ">=6.9.0" + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" + "node_modules/html-url-attributes": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz", + "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/get-east-asian-width": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", - "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", + "node_modules/htmlparser2": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz", + "integrity": "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==", "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.1", + "entities": "^6.0.0" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">=18" + "node": ">=0.12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true, + "license": "MIT" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.8" } }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "node_modules/http-parser-js": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz", + "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dev": true, "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, "engines": { "node": ">=8.0.0" } }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "license": "MIT", "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, "engines": { - "node": ">= 0.4" + "node": ">= 14" } }, - "node_modules/get-stdin": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", - "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", + "node_modules/http-proxy-middleware": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz", + "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==", "dev": true, "license": "MIT", + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, "engines": { - "node": ">=8" + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } } }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "node_modules/http-proxy-middleware/node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", "dev": true, "license": "MIT", "engines": { @@ -13013,281 +12755,292 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/get-symbol-description": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", - "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "node_modules/http-proxy/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true, + "license": "MIT" + }, + "node_modules/http2-wrapper": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", + "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6" + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.2.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10.19.0" } }, - "node_modules/github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", - "dev": true, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "license": "MIT", - "optional": true - }, - "node_modules/glob": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-12.0.0.tgz", - "integrity": "sha512-5Qcll1z7IKgHr5g485ePDdHcNQY0k2dtv/bjYy0iuyGxQw2qSOiiXUXJ+AYQpg3HNoUMHqAruX478Jeev7UULw==", - "dev": true, - "license": "BlueOak-1.0.0", "dependencies": { - "foreground-child": "^3.3.1", - "jackspeak": "^4.1.1", - "minimatch": "^10.1.1", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^2.0.0" - }, - "bin": { - "glob": "dist/esm/bin.mjs" + "agent-base": "^7.1.2", + "debug": "4" }, "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">= 14" } }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, + "license": "Apache-2.0", "engines": { - "node": ">= 6" + "node": ">=10.17.0" } }, - "node_modules/glob-to-regex.js": { + "node_modules/hyperdyperid": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/glob-to-regex.js/-/glob-to-regex.js-1.2.0.tgz", - "integrity": "sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==", + "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", + "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" + "node": ">=10.18" } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/glob/node_modules/minimatch": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", - "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", "dependencies": { - "@isaacs/brace-expansion": "^5.0.0" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=0.10.0" } }, - "node_modules/globals": { - "version": "16.5.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", - "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", "dev": true, - "license": "MIT", + "license": "ISC", "engines": { - "node": ">=18" + "node": "^10 || ^12 || >= 14" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "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", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 4" } }, - "node_modules/globby": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", - "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/immutable": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz", + "integrity": "sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==", + "dev": true, + "license": "MIT" + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, "license": "MIT", "dependencies": { - "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.3", - "ignore": "^7.0.3", - "path-type": "^6.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.3.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { - "node": ">=18" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globby/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/globby/node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, "engines": { - "node": ">=14.16" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.8.19" } }, - "node_modules/got": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/got/-/got-13.0.0.tgz", - "integrity": "sha512-XfBk1CxOOScDcMr9O1yKkNaQyy865NbYs+F7dr4H0LZMVgCj2Le59k6PqbNHoL5ToeaEQUYh6c6yMfVcc6SJxA==", + "node_modules/index-to-position": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.2.0.tgz", + "integrity": "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==", "dev": true, "license": "MIT", - "dependencies": { - "@sindresorhus/is": "^5.2.0", - "@szmarczak/http-timer": "^5.0.1", - "cacheable-lookup": "^7.0.0", - "cacheable-request": "^10.2.8", - "decompress-response": "^6.0.0", - "form-data-encoder": "^2.1.2", - "get-stream": "^6.0.1", - "http2-wrapper": "^2.1.10", - "lowercase-keys": "^3.0.0", - "p-cancelable": "^3.0.0", - "responselike": "^3.0.0" - }, "engines": { - "node": ">=16" + "node": ">=18" }, "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true, "license": "ISC" }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/inline-style-parser": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", + "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", "license": "MIT" }, - "node_modules/handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "node_modules/inspect-with-kind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/inspect-with-kind/-/inspect-with-kind-1.0.5.tgz", + "integrity": "sha512-MAQUJuIo7Xqk8EVNP+6d3CKq9c80hi4tjIbIAT6lmGW9W6WzlHiu9PS8uSuUYU+Do+j1baiFp3H25XEVxDIG2g==", "dev": true, - "license": "MIT" + "license": "ISC", + "dependencies": { + "kind-of": "^6.0.2" + } }, - "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, "license": "MIT", "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" }, "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" + "node": ">= 0.4" } }, - "node_modules/handlebars/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=10.13.0" } }, - "node_modules/has-bigints": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", - "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, "engines": { "node": ">= 0.4" }, @@ -13295,37 +13048,71 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", "dev": true, "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0" + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-proto": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", - "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "license": "MIT", "dependencies": { - "dunder-proto": "^1.0.0" + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -13334,10 +13121,17 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, "license": "MIT", "engines": { @@ -13347,14 +13141,14 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, "license": "MIT", "dependencies": { - "has-symbols": "^1.0.3" + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -13363,5370 +13157,3373 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "dev": true, "license": "MIT", "dependencies": { - "function-bind": "^1.1.2" + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hast-util-to-jsx-runtime": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", - "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "hast-util-whitespace": "^3.0.0", - "mdast-util-mdx-expression": "^2.0.0", - "mdast-util-mdx-jsx": "^3.0.0", - "mdast-util-mdxjs-esm": "^2.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0", - "style-to-js": "^1.0.0", - "unist-util-position": "^5.0.0", - "vfile-message": "^4.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hast-util-whitespace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", - "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "license": "MIT", "bin": { - "he": "bin/he" + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", "dev": true, "license": "MIT", "dependencies": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "node_modules/html-entities": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", - "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/mdevils" - }, - { - "type": "patreon", - "url": "https://patreon.com/mdevils" - } - ], - "license": "MIT" + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, - "license": "MIT" - }, - "node_modules/html-to-text": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-8.2.1.tgz", - "integrity": "sha512-aN/3JvAk8qFsWVeE9InWAWueLXrbkoVZy0TkzaGhoRBC2gCFEeRLDDJN3/ijIGHohy6H+SZzUQWN/hcYtaPK8w==", "license": "MIT", - "dependencies": { - "@selderee/plugin-htmlparser2": "^0.6.0", - "deepmerge": "^4.2.2", - "he": "^1.2.0", - "htmlparser2": "^6.1.0", - "minimist": "^1.2.6", - "selderee": "^0.6.0" - }, - "bin": { - "html-to-text": "bin/cli.js" - }, "engines": { - "node": ">=10.23.2" + "node": ">=8" } }, - "node_modules/html-to-text/node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, "license": "MIT", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + "engines": { + "node": ">=6" } }, - "node_modules/html-to-text/node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "license": "BSD-2-Clause", + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", "dependencies": { - "domelementtype": "^2.2.0" + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { - "node": ">= 4" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/html-to-text/node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "license": "BSD-2-Clause", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" + "is-extglob": "^2.1.1" }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/html-to-text/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "license": "BSD-2-Clause", + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "license": "MIT", "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/html-to-text/node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", "license": "MIT", "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/html-url-attributes": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz", - "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==", + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "dev": true, "license": "MIT", + "engines": { + "node": ">=12" + }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/htmlparser2": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz", - "integrity": "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==", + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], "license": "MIT", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.2.1", - "entities": "^6.0.0" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/htmlparser2/node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "engines": { - "node": ">=0.12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/http-cache-semantics": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "node_modules/is-network-error": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.0.tgz", + "integrity": "sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==", "dev": true, - "license": "BSD-2-Clause" + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dev": true, "license": "MIT", "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/http-parser-js": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz", - "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==", + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", "dev": true, "license": "MIT", - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, "engines": { - "node": ">=8.0.0" + "node": ">=0.10.0" } }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" + "isobject": "^3.0.1" }, "engines": { - "node": ">= 14" + "node": ">=0.10.0" } }, - "node_modules/http-proxy-middleware": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz", - "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==", + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, "license": "MIT", "dependencies": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@types/express": "^4.17.13" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/http-proxy-middleware/node_modules/is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/http-proxy/node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true, - "license": "MIT" - }, - "node_modules/http2-wrapper": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", - "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, "license": "MIT", "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.2.0" + "call-bound": "^1.0.3" }, "engines": { - "node": ">=10.19.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, "engines": { - "node": ">= 14" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, "engines": { - "node": ">=10.17.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hyperdyperid": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", - "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, "engines": { - "node": ">=10.18" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "which-typed-array": "^1.1.16" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, - "license": "ISC", + "license": "MIT", "engines": { - "node": "^10 || ^12 || >= 14" + "node": ">=10" }, - "peerDependencies": { - "postcss": "^8.1.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "dev": true, "license": "MIT", "engines": { - "node": ">= 4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/immutable": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz", - "integrity": "sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==", - "dev": true, - "license": "MIT" - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", "dev": true, "license": "MIT", "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "call-bound": "^1.0.3" }, "engines": { - "node": ">=6" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/import-local": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", "dev": true, "license": "MIT", "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/index-to-position": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.2.0.tgz", - "integrity": "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw==", - "dev": true, + "node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, "engines": { - "node": ">=18" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "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.", + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } + "license": "MIT" }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true, "license": "ISC" }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "dev": true, - "license": "ISC", - "optional": true - }, - "node_modules/inline-style-parser": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", - "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/inspect-with-kind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/inspect-with-kind/-/inspect-with-kind-1.0.5.tgz", - "integrity": "sha512-MAQUJuIo7Xqk8EVNP+6d3CKq9c80hi4tjIbIAT6lmGW9W6WzlHiu9PS8uSuUYU+Do+j1baiFp3H25XEVxDIG2g==", + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, - "license": "ISC", - "dependencies": { - "kind-of": "^6.0.2" + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" } }, - "node_modules/internal-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", - "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.2", - "side-channel": "^1.1.0" + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" }, "engines": { - "node": ">= 0.4" + "node": ">=10" } }, - "node_modules/interpret": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", - "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=10.13.0" + "node": ">=10" } }, - "node_modules/ipaddr.js": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", - "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">= 10" - } - }, - "node_modules/is-alphabetical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", - "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node": ">=8" } }, - "node_modules/is-alphanumerical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", - "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", - "license": "MIT", + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "is-alphabetical": "^2.0.0", - "is-decimal": "^2.0.0" + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "engines": { + "node": ">=10" } }, - "node_modules/is-array-buffer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", - "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-async-function": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", - "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "node_modules/istextorbinary": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-9.5.0.tgz", + "integrity": "sha512-5mbUj3SiZXCuRf9fT3ibzbSSEWiy63gFfksmGfdOzujPjW3k+z8WvIBxcJHBoQNlaZaiyB25deviif2+osLmLw==", "dev": true, - "license": "MIT", + "license": "Artistic-2.0", "dependencies": { - "async-function": "^1.0.0", - "call-bound": "^1.0.3", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" + "binaryextensions": "^6.11.0", + "editions": "^6.21.0", + "textextensions": "^6.11.0" }, "engines": { - "node": ">= 0.4" + "node": ">=4" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://bevry.me/fund" } }, - "node_modules/is-bigint": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", - "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "node_modules/jackspeak": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", + "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "has-bigints": "^1.0.2" + "@isaacs/cliui": "^8.0.2" }, "engines": { - "node": ">= 0.4" + "node": "20 || >=22" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "node_modules/jest": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-30.2.0.tgz", + "integrity": "sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==", "dev": true, "license": "MIT", "dependencies": { - "binary-extensions": "^2.0.0" + "@jest/core": "30.2.0", + "@jest/types": "30.2.0", + "import-local": "^3.2.0", + "jest-cli": "30.2.0" + }, + "bin": { + "jest": "bin/jest.js" }, "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", - "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" }, - "engines": { - "node": ">= 0.4" + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "node_modules/jest-changed-files": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.2.0.tgz", + "integrity": "sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.4" + "dependencies": { + "execa": "^5.1.1", + "jest-util": "30.2.0", + "p-limit": "^3.1.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "node_modules/jest-circus": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.2.0.tgz", + "integrity": "sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg==", "dev": true, "license": "MIT", "dependencies": { - "hasown": "^2.0.2" + "@jest/environment": "30.2.0", + "@jest/expect": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "co": "^4.6.0", + "dedent": "^1.6.0", + "is-generator-fn": "^2.1.0", + "jest-each": "30.2.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-runtime": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", + "p-limit": "^3.1.0", + "pretty-format": "30.2.0", + "pure-rand": "^7.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-data-view": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", - "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "node_modules/jest-cli": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.2.0.tgz", + "integrity": "sha512-Os9ukIvADX/A9sLt6Zse3+nmHtHaE6hqOsjQtNiugFTbKRHYIYtZXNGNK9NChseXy7djFPjndX1tL0sCTlfpAA==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "is-typed-array": "^1.1.13" + "@jest/core": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", + "chalk": "^4.1.2", + "exit-x": "^0.2.2", + "import-local": "^3.2.0", + "jest-config": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "yargs": "^17.7.2" + }, + "bin": { + "jest": "bin/jest.js" }, "engines": { - "node": ">= 0.4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/is-date-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", - "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "node_modules/jest-config": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.2.0.tgz", + "integrity": "sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" + "@babel/core": "^7.27.4", + "@jest/get-type": "30.1.0", + "@jest/pattern": "30.0.1", + "@jest/test-sequencer": "30.2.0", + "@jest/types": "30.2.0", + "babel-jest": "30.2.0", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "deepmerge": "^4.3.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-circus": "30.2.0", + "jest-docblock": "30.2.0", + "jest-environment-node": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.2.0", + "jest-runner": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "micromatch": "^4.0.8", + "parse-json": "^5.2.0", + "pretty-format": "30.2.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">= 0.4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-decimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", - "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "peerDependencies": { + "@types/node": "*", + "esbuild-register": ">=3.4.0", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "esbuild-register": { + "optional": true + }, + "ts-node": { + "optional": true + } } }, - "node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "node_modules/jest-diff": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", + "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "dev": true, "license": "MIT", - "bin": { - "is-docker": "cli.js" + "dependencies": { + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "pretty-format": "30.2.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/jest-docblock": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.2.0.tgz", + "integrity": "sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==", "dev": true, "license": "MIT", + "dependencies": { + "detect-newline": "^3.1.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-finalizationregistry": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", - "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "node_modules/jest-each": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.2.0.tgz", + "integrity": "sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3" + "@jest/get-type": "30.1.0", + "@jest/types": "30.2.0", + "chalk": "^4.1.2", + "jest-util": "30.2.0", + "pretty-format": "30.2.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/jest-environment-node": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.2.0.tgz", + "integrity": "sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA==", "dev": true, "license": "MIT", + "dependencies": { + "@jest/environment": "30.2.0", + "@jest/fake-timers": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-mock": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0" + }, "engines": { - "node": ">=8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/is-generator-function": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", - "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "node_modules/jest-haste-map": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.2.0.tgz", + "integrity": "sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.4", - "generator-function": "^2.0.0", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" + "@jest/types": "30.2.0", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.1", + "jest-util": "30.2.0", + "jest-worker": "30.2.0", + "micromatch": "^4.0.8", + "walker": "^1.0.8" }, "engines": { - "node": ">= 0.4" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "optionalDependencies": { + "fsevents": "^2.3.3" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/jest-leak-detector": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.2.0.tgz", + "integrity": "sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ==", "dev": true, "license": "MIT", "dependencies": { - "is-extglob": "^2.1.1" + "@jest/get-type": "30.1.0", + "pretty-format": "30.2.0" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-hexadecimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", - "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "node_modules/jest-matcher-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", + "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", + "dev": true, "license": "MIT", "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "jest-diff": "30.2.0", + "pretty-format": "30.2.0" }, "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-interactive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", - "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "node_modules/jest-message-util": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", + "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.2.0", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.2.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "node_modules/jest-mock": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", + "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.4" + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-util": "30.2.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "node_modules/jest-mock-vscode": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/jest-mock-vscode/-/jest-mock-vscode-4.0.5.tgz", + "integrity": "sha512-XLK3mZjKLAUpERm9p5j0nbDlTTYGUxvZLOFFCv5iM2dmi8LUszhlKGzYYnR9rvvbx3UYRRj+yuzK3Q0jK6s1jg==", "dev": true, "license": "MIT", + "dependencies": { + "vscode-uri": "^3.0.8" + }, "engines": { - "node": ">= 0.4" + "node": ">20.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@types/vscode": "^1.90.0" } }, - "node_modules/is-network-error": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.0.tgz", - "integrity": "sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==", + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, "license": "MIT", "engines": { - "node": ">=16" + "node": ">=6" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.12.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-number-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", - "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "node_modules/jest-resolve": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.2.0.tgz", + "integrity": "sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-pnp-resolver": "^1.2.3", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "slash": "^3.0.0", + "unrs-resolver": "^1.7.11" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "license": "MIT", "engines": { - "node": ">=8" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "node_modules/jest-resolve-dependencies": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.2.0.tgz", + "integrity": "sha512-xTOIGug/0RmIe3mmCqCT95yO0vj6JURrn1TKWlNbhiAefJRWINNPgwVkrVgt/YaerPzY3iItufd80v3lOrFJ2w==", "dev": true, "license": "MIT", + "dependencies": { + "jest-regex-util": "30.0.1", + "jest-snapshot": "30.2.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "node_modules/jest-runner": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.2.0.tgz", + "integrity": "sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ==", "dev": true, "license": "MIT", "dependencies": { - "isobject": "^3.0.1" + "@jest/console": "30.2.0", + "@jest/environment": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-docblock": "30.2.0", + "jest-environment-node": "30.2.0", + "jest-haste-map": "30.2.0", + "jest-leak-detector": "30.2.0", + "jest-message-util": "30.2.0", + "jest-resolve": "30.2.0", + "jest-runtime": "30.2.0", + "jest-util": "30.2.0", + "jest-watcher": "30.2.0", + "jest-worker": "30.2.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" }, "engines": { - "node": ">=0.10.0" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-regex": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "node_modules/jest-runtime": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.2.0.tgz", + "integrity": "sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" + "@jest/environment": "30.2.0", + "@jest/fake-timers": "30.2.0", + "@jest/globals": "30.2.0", + "@jest/source-map": "30.0.1", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "cjs-module-lexer": "^2.1.0", + "collect-v8-coverage": "^1.0.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "node_modules/jest-snapshot": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.2.0.tgz", + "integrity": "sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.4" + "dependencies": { + "@babel/core": "^7.27.4", + "@babel/generator": "^7.27.5", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1", + "@babel/types": "^7.27.3", + "@jest/expect-utils": "30.2.0", + "@jest/get-type": "30.1.0", + "@jest/snapshot-utils": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "babel-preset-current-node-syntax": "^1.2.0", + "chalk": "^4.1.2", + "expect": "30.2.0", + "graceful-fs": "^4.2.11", + "jest-diff": "30.2.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-util": "30.2.0", + "pretty-format": "30.2.0", + "semver": "^7.7.2", + "synckit": "^0.11.8" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", - "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "node_modules/jest-util": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", + "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3" + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/jest-util/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/is-string": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", - "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "node_modules/jest-validate": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.2.0.tgz", + "integrity": "sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" + "@jest/get-type": "30.1.0", + "@jest/types": "30.2.0", + "camelcase": "^6.3.0", + "chalk": "^4.1.2", + "leven": "^3.1.0", + "pretty-format": "30.2.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-symbol": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", - "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-symbols": "^1.1.0", - "safe-regex-test": "^1.1.0" - }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "node_modules/jest-watcher": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.2.0.tgz", + "integrity": "sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg==", "dev": true, "license": "MIT", "dependencies": { - "which-typed-array": "^1.1.16" + "@jest/test-result": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "jest-util": "30.2.0", + "string-length": "^4.0.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "node_modules/jest-worker": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.2.0.tgz", + "integrity": "sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g==", "dev": true, "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.2.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.1.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", - "dev": true, - "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/is-weakref": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", - "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/is-weakset": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", - "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/is-wsl": { + "node_modules/jsesc": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, "license": "MIT", - "dependencies": { - "is-inside-container": "^1.0.0" + "bin": { + "jsesc": "bin/jsesc" }, "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true, "license": "MIT" }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "license": "MIT" + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", - "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", - "dev": true, - "license": "BSD-3-Clause", + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "license": "MIT", "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", "semver": "^7.5.4" }, "engines": { - "node": ">=10" + "node": ">=12", + "npm": ">=6" } }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", "dev": true, - "license": "BSD-3-Clause", + "license": "(MIT OR GPL-3.0-or-later)", "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" } }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, + "node_modules/jwa": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" } }, - "node_modules/istanbul-lib-source-maps": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", - "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", - "dev": true, - "license": "BSD-3-Clause", + "node_modules/jws": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.3.tgz", + "integrity": "sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g==", + "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.23", - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0" - }, - "engines": { - "node": ">=10" + "jwa": "^1.4.2", + "safe-buffer": "^5.0.1" } }, - "node_modules/istanbul-reports": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", - "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "node_modules/keyborg": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/keyborg/-/keyborg-2.6.0.tgz", + "integrity": "sha512-o5kvLbuTF+o326CMVYpjlaykxqYP9DphFQZ2ZpgrvBouyvOxyEB7oqe8nOLFpiV5VCtz0D3pt8gXQYWpLpBnmA==", + "license": "MIT" + }, + "node_modules/keytar": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz", + "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==", "dev": true, - "license": "BSD-3-Clause", + "hasInstallScript": true, + "license": "MIT", + "optional": true, "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" + "node-addon-api": "^4.3.0", + "prebuild-install": "^7.0.1" } }, - "node_modules/istextorbinary": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-9.5.0.tgz", - "integrity": "sha512-5mbUj3SiZXCuRf9fT3ibzbSSEWiy63gFfksmGfdOzujPjW3k+z8WvIBxcJHBoQNlaZaiyB25deviif2+osLmLw==", + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, - "license": "Artistic-2.0", + "license": "MIT", "dependencies": { - "binaryextensions": "^6.11.0", - "editions": "^6.21.0", - "textextensions": "^6.11.0" - }, - "engines": { - "node": ">=4" - }, - "funding": { - "url": "https://bevry.me/fund" + "json-buffer": "3.0.1" } }, - "node_modules/jackspeak": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", - "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, + "license": "MIT", "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=0.10.0" } }, - "node_modules/jest": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-30.2.0.tgz", - "integrity": "sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==", + "node_modules/launch-editor": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.12.0.tgz", + "integrity": "sha512-giOHXoOtifjdHqUamwKq6c49GzBdLjvxrd2D+Q4V6uOHopJv7p9VJxikDsQ/CBXZbEITgUqSVHXLTG3VhPP1Dg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/core": "30.2.0", - "@jest/types": "30.2.0", - "import-local": "^3.2.0", - "jest-cli": "30.2.0" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "picocolors": "^1.1.1", + "shell-quote": "^1.8.3" } }, - "node_modules/jest-changed-files": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.2.0.tgz", - "integrity": "sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ==", + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true, "license": "MIT", - "dependencies": { - "execa": "^5.1.1", - "jest-util": "30.2.0", - "p-limit": "^3.1.0" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=6" } }, - "node_modules/jest-circus": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.2.0.tgz", - "integrity": "sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg==", + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/expect": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/types": "30.2.0", - "@types/node": "*", - "chalk": "^4.1.2", - "co": "^4.6.0", - "dedent": "^1.6.0", - "is-generator-fn": "^2.1.0", - "jest-each": "30.2.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-runtime": "30.2.0", - "jest-snapshot": "30.2.0", - "jest-util": "30.2.0", - "p-limit": "^3.1.0", - "pretty-format": "30.2.0", - "pure-rand": "^7.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.6" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.8.0" } }, - "node_modules/jest-cli": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.2.0.tgz", - "integrity": "sha512-Os9ukIvADX/A9sLt6Zse3+nmHtHaE6hqOsjQtNiugFTbKRHYIYtZXNGNK9NChseXy7djFPjndX1tL0sCTlfpAA==", + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/core": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/types": "30.2.0", - "chalk": "^4.1.2", - "exit-x": "^0.2.2", - "import-local": "^3.2.0", - "jest-config": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", - "yargs": "^17.7.2" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "immediate": "~3.0.5" } }, - "node_modules/jest-config": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.2.0.tgz", - "integrity": "sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA==", + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.27.4", - "@jest/get-type": "30.1.0", - "@jest/pattern": "30.0.1", - "@jest/test-sequencer": "30.2.0", - "@jest/types": "30.2.0", - "babel-jest": "30.2.0", - "chalk": "^4.1.2", - "ci-info": "^4.2.0", - "deepmerge": "^4.3.1", - "glob": "^10.3.10", - "graceful-fs": "^4.2.11", - "jest-circus": "30.2.0", - "jest-docblock": "30.2.0", - "jest-environment-node": "30.2.0", - "jest-regex-util": "30.0.1", - "jest-resolve": "30.2.0", - "jest-runner": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", - "micromatch": "^4.0.8", - "parse-json": "^5.2.0", - "pretty-format": "30.2.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "esbuild-register": ">=3.4.0", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "esbuild-register": { - "optional": true - }, - "ts-node": { - "optional": true - } - } + "license": "MIT" }, - "node_modules/jest-diff": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", - "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/diff-sequences": "30.0.1", - "@jest/get-type": "30.1.0", - "chalk": "^4.1.2", - "pretty-format": "30.2.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "uc.micro": "^2.0.0" } }, - "node_modules/jest-docblock": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.2.0.tgz", - "integrity": "sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==", + "node_modules/loader-runner": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", + "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", "dev": true, "license": "MIT", - "dependencies": { - "detect-newline": "^3.1.0" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-each": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.2.0.tgz", - "integrity": "sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/get-type": "30.1.0", - "@jest/types": "30.2.0", - "chalk": "^4.1.2", - "jest-util": "30.2.0", - "pretty-format": "30.2.0" + "node": ">=6.11.5" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/jest-environment-node": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.2.0.tgz", - "integrity": "sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA==", + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/fake-timers": "30.2.0", - "@jest/types": "30.2.0", - "@types/node": "*", - "jest-mock": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0" + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8.9.0" } }, - "node_modules/jest-haste-map": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.2.0.tgz", - "integrity": "sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==", + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", - "@types/node": "*", - "anymatch": "^3.1.3", - "fb-watchman": "^2.0.2", - "graceful-fs": "^4.2.11", - "jest-regex-util": "30.0.1", - "jest-util": "30.2.0", - "jest-worker": "30.2.0", - "micromatch": "^4.0.8", - "walker": "^1.0.8" + "p-locate": "^5.0.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=10" }, - "optionalDependencies": { - "fsevents": "^2.3.3" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-leak-detector": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.2.0.tgz", - "integrity": "sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ==", + "node_modules/lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "dev": true, - "license": "MIT", - "dependencies": { - "@jest/get-type": "30.1.0", - "pretty-format": "30.2.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } + "license": "MIT" }, - "node_modules/jest-matcher-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", - "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/get-type": "30.1.0", - "chalk": "^4.1.2", - "jest-diff": "30.2.0", - "pretty-format": "30.2.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" }, - "node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", - "@types/stack-utils": "^2.0.3", - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.6" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" }, - "node_modules/jest-mock": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", - "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "30.2.0", - "@types/node": "*", - "jest-util": "30.2.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } + "license": "MIT" }, - "node_modules/jest-mock-vscode": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/jest-mock-vscode/-/jest-mock-vscode-4.0.5.tgz", - "integrity": "sha512-XLK3mZjKLAUpERm9p5j0nbDlTTYGUxvZLOFFCv5iM2dmi8LUszhlKGzYYnR9rvvbx3UYRRj+yuzK3Q0jK6s1jg==", + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "license": "MIT", "dependencies": { - "vscode-uri": "^3.0.8" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "engines": { - "node": ">20.0.0" + "node": ">=10" }, - "peerDependencies": { - "@types/vscode": "^1.90.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", "license": "MIT", - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/jest-regex-util": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", - "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", + "node_modules/lowercase-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", + "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", "dev": true, "license": "MIT", "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-resolve": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.2.0.tgz", - "integrity": "sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A==", + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "jest-haste-map": "30.2.0", - "jest-pnp-resolver": "^1.2.3", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", - "slash": "^3.0.0", - "unrs-resolver": "^1.7.11" + "yallist": "^4.0.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=10" } }, - "node_modules/jest-resolve-dependencies": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.2.0.tgz", - "integrity": "sha512-xTOIGug/0RmIe3mmCqCT95yO0vj6JURrn1TKWlNbhiAefJRWINNPgwVkrVgt/YaerPzY3iItufd80v3lOrFJ2w==", + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "license": "MIT", "dependencies": { - "jest-regex-util": "30.0.1", - "jest-snapshot": "30.2.0" + "semver": "^7.5.3" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-runner": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.2.0.tgz", - "integrity": "sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ==", + "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": "MIT", + "license": "ISC" + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@jest/console": "30.2.0", - "@jest/environment": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", - "@types/node": "*", - "chalk": "^4.1.2", - "emittery": "^0.13.1", - "exit-x": "^0.2.2", - "graceful-fs": "^4.2.11", - "jest-docblock": "30.2.0", - "jest-environment-node": "30.2.0", - "jest-haste-map": "30.2.0", - "jest-leak-detector": "30.2.0", - "jest-message-util": "30.2.0", - "jest-resolve": "30.2.0", - "jest-runtime": "30.2.0", - "jest-util": "30.2.0", - "jest-watcher": "30.2.0", - "jest-worker": "30.2.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "tmpl": "1.0.5" } }, - "node_modules/jest-runtime": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.2.0.tgz", - "integrity": "sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg==", + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/fake-timers": "30.2.0", - "@jest/globals": "30.2.0", - "@jest/source-map": "30.0.1", - "@jest/test-result": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", - "@types/node": "*", - "chalk": "^4.1.2", - "cjs-module-lexer": "^2.1.0", - "collect-v8-coverage": "^1.0.2", - "glob": "^10.3.10", - "graceful-fs": "^4.2.11", - "jest-haste-map": "30.2.0", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", - "jest-regex-util": "30.0.1", - "jest-resolve": "30.2.0", - "jest-snapshot": "30.2.0", - "jest-util": "30.2.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "bin": { + "markdown-it": "bin/markdown-it.mjs" } }, - "node_modules/jest-snapshot": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.2.0.tgz", - "integrity": "sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA==", + "node_modules/markdown-it/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, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.27.4", - "@babel/generator": "^7.27.5", - "@babel/plugin-syntax-jsx": "^7.27.1", - "@babel/plugin-syntax-typescript": "^7.27.1", - "@babel/types": "^7.27.3", - "@jest/expect-utils": "30.2.0", - "@jest/get-type": "30.1.0", - "@jest/snapshot-utils": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", - "babel-preset-current-node-syntax": "^1.2.0", - "chalk": "^4.1.2", - "expect": "30.2.0", - "graceful-fs": "^4.2.11", - "jest-diff": "30.2.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-util": "30.2.0", - "pretty-format": "30.2.0", - "semver": "^7.7.2", - "synckit": "^0.11.8" - }, + "license": "Python-2.0" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" } }, - "node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "node_modules/md5": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" + } + }, + "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", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", - "@types/node": "*", - "chalk": "^4.1.2", - "ci-info": "^4.2.0", - "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/jest-util/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/jest-validate": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.2.0.tgz", - "integrity": "sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw==", - "dev": true, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", "license": "MIT", "dependencies": { - "@jest/get-type": "30.1.0", - "@jest/types": "30.2.0", - "camelcase": "^6.3.0", - "chalk": "^4.1.2", - "leven": "^3.1.0", - "pretty-format": "30.2.0" + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/jest-watcher": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.2.0.tgz", - "integrity": "sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg==", - "dev": true, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", "license": "MIT", "dependencies": { - "@jest/test-result": "30.2.0", - "@jest/types": "30.2.0", - "@types/node": "*", - "ansi-escapes": "^4.3.2", - "chalk": "^4.1.2", - "emittery": "^0.13.1", - "jest-util": "30.2.0", - "string-length": "^4.0.2" + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/jest-worker": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.2.0.tgz", - "integrity": "sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g==", - "dev": true, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", "license": "MIT", "dependencies": { - "@types/node": "*", - "@ungap/structured-clone": "^1.3.0", - "jest-util": "30.2.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.1.1" + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/js-tokens": { + "node_modules/mdast-util-to-string": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", - "dev": true, + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", "license": "MIT", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "@types/mdast": "^4.0.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true, + "license": "MIT" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "dev": true, "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, "engines": { - "node": ">=6" + "node": ">= 0.6" } }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "node_modules/memfs": { + "version": "4.51.0", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.51.0.tgz", + "integrity": "sha512-4zngfkVM/GpIhC8YazOsM6E8hoB33NP0BCESPOA6z7qaL6umPJNqkO8CNYaLV2FB2MV6H1O3x2luHHOSqppv+A==", "dev": true, - "license": "MIT" + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/json-pack": "^1.11.0", + "@jsonjoy.com/util": "^1.9.0", + "glob-to-regex.js": "^1.0.1", + "thingies": "^2.5.0", + "tree-dump": "^1.0.3", + "tslib": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + } }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", "license": "MIT" }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true, "license": "MIT" }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, "engines": { - "node": ">=6" + "node": ">= 8" } }, - "node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "license": "MIT" - }, - "node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "dev": true, "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", - "license": "MIT", - "dependencies": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^7.5.4" - }, "engines": { - "node": ">=12", - "npm": ">=6" + "node": ">= 0.6" } }, - "node_modules/jszip": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", - "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", - "dev": true, - "license": "(MIT OR GPL-3.0-or-later)", + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", "dependencies": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "setimmediate": "^1.0.5" + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/jwa": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", - "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "buffer-equal-constant-time": "^1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/jws": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.3.tgz", - "integrity": "sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g==", + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "jwa": "^1.4.2", - "safe-buffer": "^5.0.1" + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/keyborg": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/keyborg/-/keyborg-2.6.0.tgz", - "integrity": "sha512-o5kvLbuTF+o326CMVYpjlaykxqYP9DphFQZ2ZpgrvBouyvOxyEB7oqe8nOLFpiV5VCtz0D3pt8gXQYWpLpBnmA==", - "license": "MIT" - }, - "node_modules/keytar": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz", - "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==", - "dev": true, - "hasInstallScript": true, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", - "optional": true, "dependencies": { - "node-addon-api": "^4.3.0", - "prebuild-install": "^7.0.1" + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/launch-editor": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.12.0.tgz", - "integrity": "sha512-giOHXoOtifjdHqUamwKq6c49GzBdLjvxrd2D+Q4V6uOHopJv7p9VJxikDsQ/CBXZbEITgUqSVHXLTG3VhPP1Dg==", - "dev": true, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "picocolors": "^1.1.1", - "shell-quote": "^1.8.3" + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/lie": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", - "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", - "dev": true, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "immediate": "~3.0.5" + "micromark-util-symbol": "^2.0.0" } }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, - "license": "MIT" - }, - "node_modules/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", - "dev": true, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "uc.micro": "^2.0.0" + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/loader-runner": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", - "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", - "dev": true, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", - "engines": { - "node": ">=6.11.5" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" + "micromark-util-symbol": "^2.0.0" } }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" } }, - "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", - "license": "MIT" - }, - "node_modules/lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", - "license": "MIT" - }, - "node_modules/lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", - "license": "MIT" - }, - "node_modules/lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", - "license": "MIT" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "license": "MIT" - }, - "node_modules/lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", - "license": "MIT" - }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "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", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", - "license": "MIT" - }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", - "dev": true, - "license": "MIT" - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/longest-streak": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", - "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/lowercase-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", - "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "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/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "tmpl": "1.0.5" - } - }, - "node_modules/markdown-it": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", - "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.0", - "mdurl": "^2.0.0", - "punycode.js": "^2.3.1", - "uc.micro": "^2.1.0" - }, - "bin": { - "markdown-it": "bin/markdown-it.mjs" - } - }, - "node_modules/markdown-it/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, - "license": "Python-2.0" - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/md5": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", - "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "charenc": "0.0.2", - "crypt": "0.0.2", - "is-buffer": "~1.1.6" - } - }, - "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", - "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark": "^4.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-expression": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", - "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-jsx": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", - "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "devlop": "^1.1.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "parse-entities": "^4.0.0", - "stringify-entities": "^4.0.0", - "unist-util-stringify-position": "^4.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdxjs-esm": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", - "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-phrasing": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", - "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-hast": { - "version": "13.2.1", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", - "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", - "devlop": "^1.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "trim-lines": "^3.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-markdown": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", - "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", - "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "dev": true, - "license": "MIT" - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memfs": { - "version": "4.51.0", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.51.0.tgz", - "integrity": "sha512-4zngfkVM/GpIhC8YazOsM6E8hoB33NP0BCESPOA6z7qaL6umPJNqkO8CNYaLV2FB2MV6H1O3x2luHHOSqppv+A==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jsonjoy.com/json-pack": "^1.11.0", - "@jsonjoy.com/util": "^1.9.0", - "glob-to-regex.js": "^1.0.1", - "thingies": "^2.5.0", - "tree-dump": "^1.0.3", - "tslib": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - } - }, - "node_modules/memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "license": "MIT" - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "license": "MIT" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromark": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", - "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-core-commonmark": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", - "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-destination": "^2.0.0", - "micromark-factory-label": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-title": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-html-tag-name": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-destination": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", - "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-label": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", - "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-space": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", - "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-title": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", - "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-whitespace": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", - "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-character": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", - "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-chunked": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", - "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-classify-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", - "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-combine-extensions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", - "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-chunked": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-numeric-character-reference": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", - "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-string": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", - "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-encode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", - "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-html-tag-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", - "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-normalize-identifier": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", - "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-resolve-all": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", - "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", - "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-subtokenize": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", - "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-symbol": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", - "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-types": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", - "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/mimic-function": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", - "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mimic-response": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", - "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true, - "license": "ISC" - }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/mocha": { - "version": "11.7.5", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz", - "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==", - "dev": true, - "license": "MIT", - "dependencies": { - "browser-stdout": "^1.3.1", - "chokidar": "^4.0.1", - "debug": "^4.3.5", - "diff": "^7.0.0", - "escape-string-regexp": "^4.0.0", - "find-up": "^5.0.0", - "glob": "^10.4.5", - "he": "^1.2.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "log-symbols": "^4.1.0", - "minimatch": "^9.0.5", - "ms": "^2.1.3", - "picocolors": "^1.1.1", - "serialize-javascript": "^6.0.2", - "strip-json-comments": "^3.1.1", - "supports-color": "^8.1.1", - "workerpool": "^9.2.0", - "yargs": "^17.7.2", - "yargs-parser": "^21.1.1", - "yargs-unparser": "^2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/mocha-junit-reporter": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-2.2.1.tgz", - "integrity": "sha512-iDn2tlKHn8Vh8o4nCzcUVW4q7iXp7cC4EB78N0cDHIobLymyHNwe0XG8HEHHjc3hJlXm0Vy6zcrxaIhnI2fWmw==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4", - "md5": "^2.3.0", - "mkdirp": "^3.0.0", - "strip-ansi": "^6.0.1", - "xml": "^1.0.1" - }, - "peerDependencies": { - "mocha": ">=2.2.5" - } - }, - "node_modules/mocha-junit-reporter/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/mocha-junit-reporter/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/mocha-multi-reporters": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/mocha-multi-reporters/-/mocha-multi-reporters-1.5.1.tgz", - "integrity": "sha512-Yb4QJOaGLIcmB0VY7Wif5AjvLMUFAdV57D2TWEva1Y0kU/3LjKpeRVmlMIfuO1SVbauve459kgtIizADqxMWPg==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.1.1", - "lodash": "^4.17.15" - }, - "engines": { - "node": ">=6.0.0" - }, - "peerDependencies": { - "mocha": ">=3.1.2" - } - }, - "node_modules/mocha/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, - "license": "Python-2.0" - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/monaco-editor": { - "version": "0.52.2", - "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz", - "integrity": "sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==", - "license": "MIT" - }, - "node_modules/monaco-editor-webpack-plugin": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-7.1.1.tgz", - "integrity": "sha512-WxdbFHS3Wtz4V9hzhe/Xog5hQRSMxmDLkEEYZwqMDHgJlkZo00HVFZR0j5d0nKypjTUkkygH3dDSXERLG4757A==", - "dev": true, - "license": "MIT", - "dependencies": { - "loader-utils": "^2.0.2" - }, - "peerDependencies": { - "monaco-editor": ">= 0.31.0", - "webpack": "^4.5.0 || 5.x" - } - }, - "node_modules/mongodb": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-7.0.0.tgz", - "integrity": "sha512-vG/A5cQrvGGvZm2mTnCSz1LUcbOPl83hfB6bxULKQ8oFZauyox/2xbZOoGNl+64m8VBrETkdGCDBdOsCr3F3jg==", - "license": "Apache-2.0", - "dependencies": { - "@mongodb-js/saslprep": "^1.3.0", - "bson": "^7.0.0", - "mongodb-connection-string-url": "^7.0.0" - }, - "engines": { - "node": ">=20.19.0" - }, - "peerDependencies": { - "@aws-sdk/credential-providers": "^3.806.0", - "@mongodb-js/zstd": "^7.0.0", - "gcp-metadata": "^7.0.1", - "kerberos": "^7.0.0", - "mongodb-client-encryption": ">=7.0.0 <7.1.0", - "snappy": "^7.3.2", - "socks": "^2.8.6" - }, - "peerDependenciesMeta": { - "@aws-sdk/credential-providers": { - "optional": true - }, - "@mongodb-js/zstd": { - "optional": true - }, - "gcp-metadata": { - "optional": true - }, - "kerberos": { - "optional": true - }, - "mongodb-client-encryption": { - "optional": true - }, - "snappy": { - "optional": true - }, - "socks": { - "optional": true - } - } - }, - "node_modules/mongodb-connection-string-url": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz", - "integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==", - "license": "Apache-2.0", - "dependencies": { - "@types/whatwg-url": "^11.0.2", - "whatwg-url": "^14.1.0 || ^13.0.0" - } - }, - "node_modules/mongodb-explain-compat": { - "version": "3.3.23", - "resolved": "https://registry.npmjs.org/mongodb-explain-compat/-/mongodb-explain-compat-3.3.23.tgz", - "integrity": "sha512-3OygQjzjHr0hsT3y0f91yP7Ylp+2bbEM3IPil2yv+9avmGhA9Ru+CcgTXI+IfkfNlbcly/w7alvHDk+dlX28QQ==", - "license": "SSPL" - }, - "node_modules/mongodb/node_modules/@types/whatwg-url": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-13.0.0.tgz", - "integrity": "sha512-N8WXpbE6Wgri7KUSvrmQcqrMllKZ9uxkYWMt+mCSGwNc0Hsw9VQTW7ApqI4XNrx6/SaM2QQJCzMPDEXE058s+Q==", - "license": "MIT", - "dependencies": { - "@types/webidl-conversions": "*" - } - }, - "node_modules/mongodb/node_modules/mongodb-connection-string-url": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-7.0.0.tgz", - "integrity": "sha512-irhhjRVLE20hbkRl4zpAYLnDMM+zIZnp0IDB9akAFFUZp/3XdOfwwddc7y6cNvF2WCEtfTYRwYbIfYa2kVY0og==", - "license": "Apache-2.0", - "dependencies": { - "@types/whatwg-url": "^13.0.0", - "whatwg-url": "^14.1.0" - }, - "engines": { - "node": ">=20.19.0" - } - }, - "node_modules/moo": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", - "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==", - "license": "BSD-3-Clause" - }, - "node_modules/mrmime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", - "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dev": true, - "license": "MIT", - "dependencies": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - }, - "bin": { - "multicast-dns": "cli.js" - } - }, - "node_modules/multiple-select-vanilla": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/multiple-select-vanilla/-/multiple-select-vanilla-4.4.0.tgz", - "integrity": "sha512-QxZep610yATWMZhDMq0kzZWZSTb/Iffc0OdknY1El5SOjSm0o7CSHxN7CfOJRlbSyYGNv4TyFlL5A8FRN08F2A==", - "license": "MIT", - "dependencies": { - "@types/trusted-types": "^2.0.7" - }, - "funding": { - "type": "ko_fi", - "url": "https://ko-fi.com/ghiscoding" - } - }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true, - "license": "ISC" - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/napi-build-utils": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", - "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/napi-postinstall": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", - "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", - "dev": true, - "license": "MIT", - "bin": { - "napi-postinstall": "lib/cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/napi-postinstall" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" - }, - "node_modules/nearley": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", - "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", - "license": "MIT", - "dependencies": { - "commander": "^2.19.0", - "moo": "^0.5.0", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6" - }, - "bin": { - "nearley-railroad": "bin/nearley-railroad.js", - "nearley-test": "bin/nearley-test.js", - "nearley-unparse": "bin/nearley-unparse.js", - "nearleyc": "bin/nearleyc.js" - }, - "funding": { - "type": "individual", - "url": "https://nearley.js.org/#give-to-nearley" - } - }, - "node_modules/nearley/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "license": "MIT" - }, - "node_modules/negotiator": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true, - "license": "MIT" - }, - "node_modules/node-abi": { - "version": "3.85.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.85.0.tgz", - "integrity": "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-addon-api": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", - "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/node-forge": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.2.tgz", - "integrity": "sha512-6xKiQ+cph9KImrRh0VsjH2d8/GXA4FIMlgU4B757iI1ApvcyA9VlouP0yZJha01V+huImO+kKMU7ih+2+E14fw==", - "dev": true, - "license": "(BSD-3-Clause OR GPL-2.0)", - "engines": { - "node": ">= 6.13.0" - } - }, - "node_modules/node-html-markdown": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/node-html-markdown/-/node-html-markdown-1.3.0.tgz", - "integrity": "sha512-OeFi3QwC/cPjvVKZ114tzzu+YoR+v9UXW5RwSXGUqGb0qCl0DvP406tzdL7SFn8pZrMyzXoisfG2zcuF9+zw4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "node-html-parser": "^6.1.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/node-html-parser": { - "version": "6.1.13", - "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.13.tgz", - "integrity": "sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==", - "dev": true, - "license": "MIT", - "dependencies": { - "css-select": "^5.1.0", - "he": "1.2.0" - } - }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/node-sarif-builder": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/node-sarif-builder/-/node-sarif-builder-3.3.1.tgz", - "integrity": "sha512-8z5dAbhpxmk/WRQHXlv4V0h+9Y4Ugk+w08lyhV/7E/CQX9yDdBc3025/EG+RSMJU2aPFh/IQ7XDV7Ti5TLt/TA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/sarif": "^2.1.7", - "fs-extra": "^11.1.1" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/normalize-package-data": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", - "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^7.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/normalize-package-data/node_modules/hosted-git-info": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", - "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", - "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^10.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/normalize-package-data/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.1.0.tgz", - "integrity": "sha512-X06Mfd/5aKsRHc0O0J5CUedwnPmnDtLF2+nq+KN9KSDlJHkPuh0JUviWjEWMe0SW/9TDdSLVPuk7L5gGTIA1/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", - "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0", - "has-symbols": "^1.1.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.values": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", - "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true, - "license": "MIT" - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", - "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "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/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", - "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", - "license": "MIT", - "dependencies": { - "default-browser": "^5.2.1", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "wsl-utils": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/opener": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", - "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", - "dev": true, - "license": "(WTFPL OR MIT)", - "bin": { - "opener": "bin/opener-bin.js" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ora": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", - "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^5.3.0", - "cli-cursor": "^5.0.0", - "cli-spinners": "^2.9.2", - "is-interactive": "^2.0.0", - "is-unicode-supported": "^2.0.0", - "log-symbols": "^6.0.0", - "stdin-discarder": "^0.2.2", - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ora/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "dev": true, - "license": "MIT" - }, - "node_modules/ora/node_modules/is-unicode-supported": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", - "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/log-symbols": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", - "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^5.3.0", - "is-unicode-supported": "^1.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/log-symbols/node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/own-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", - "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.6", - "object-keys": "^1.1.1", - "safe-push-apply": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/p-cancelable": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", - "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.20" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", - "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-retry": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz", - "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/retry": "0.12.2", - "is-network-error": "^1.0.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true, - "license": "BlueOak-1.0.0" + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" }, - "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/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" + "micromark-util-symbol": "^2.0.0" } }, - "node_modules/parse-entities": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", - "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "@types/unist": "^2.0.0", - "character-entities-legacy": "^3.0.0", - "character-reference-invalid": "^2.0.0", - "decode-named-character-reference": "^1.0.0", - "is-alphanumerical": "^2.0.0", - "is-decimal": "^2.0.0", - "is-hexadecimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "micromark-util-types": "^2.0.0" } }, - "node_modules/parse-entities/node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", - "license": "MIT" - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" } }, - "node_modules/parse-semver": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", - "integrity": "sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==", - "dev": true, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "semver": "^5.1.0" + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/parse-semver/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" }, - "node_modules/parse5": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", - "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "entities": "^6.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", - "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", "dependencies": { - "domhandler": "^5.0.3", - "parse5": "^7.0.0" + "braces": "^3.0.3", + "picomatch": "^2.3.1" }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "engines": { + "node": ">=8.6" } }, - "node_modules/parse5-parser-stream": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", - "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true, "license": "MIT", - "dependencies": { - "parse5": "^7.0.0" + "bin": { + "mime": "cli.js" }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "engines": { + "node": ">=4" } }, - "node_modules/parse5/node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "node": ">= 0.6" } }, - "node_modules/parseley": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.7.0.tgz", - "integrity": "sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw==", + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, "license": "MIT", "dependencies": { - "moo": "^0.5.1", - "nearley": "^2.20.1" + "mime-db": "1.52.0" }, - "funding": { - "url": "https://ko-fi.com/killymxi" + "engines": { + "node": ">= 0.6" } }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "node_modules/mime-types/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">= 0.6" } }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=6" } }, - "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==", + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "node_modules/mimic-response": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", + "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", "dev": true, - "license": "MIT" + "license": "ISC" }, - "node_modules/path-scurry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", - "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "ISC", "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "20 || >=22" + "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.2.tgz", - "integrity": "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==", - "dev": true, - "license": "ISC", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-type": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", - "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", - "dev": true, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "license": "MIT", - "engines": { - "node": ">=18" - }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true, - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, - "license": "ISC" + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", "dev": true, "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, "engines": { - "node": ">=8.6" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/pirates": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", - "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 6" - } + "optional": true }, - "node_modules/piscina": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.9.2.tgz", - "integrity": "sha512-Fq0FERJWFEUpB4eSY59wSNwXD4RYqR+nR/WiEVcZW8IWfVBxJJafcgTEZDQo8k3w0sUarJ8RyVbbUF4GQ2LGbQ==", + "node_modules/mocha": { + "version": "11.7.5", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz", + "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==", "dev": true, "license": "MIT", - "optionalDependencies": { - "@napi-rs/nice": "^1.0.1" + "dependencies": { + "browser-stdout": "^1.3.1", + "chokidar": "^4.0.1", + "debug": "^4.3.5", + "diff": "^7.0.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^10.4.5", + "he": "^1.2.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^9.0.5", + "ms": "^2.1.3", + "picocolors": "^1.1.1", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^9.2.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "node_modules/mocha-junit-reporter": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-2.2.1.tgz", + "integrity": "sha512-iDn2tlKHn8Vh8o4nCzcUVW4q7iXp7cC4EB78N0cDHIobLymyHNwe0XG8HEHHjc3hJlXm0Vy6zcrxaIhnI2fWmw==", "dev": true, "license": "MIT", "dependencies": { - "find-up": "^4.0.0" + "debug": "^4.3.4", + "md5": "^2.3.0", + "mkdirp": "^3.0.0", + "strip-ansi": "^6.0.1", + "xml": "^1.0.1" }, + "peerDependencies": { + "mocha": ">=2.2.5" + } + }, + "node_modules/mocha-junit-reporter/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/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/mocha-junit-reporter/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": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/mocha-multi-reporters": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/mocha-multi-reporters/-/mocha-multi-reporters-1.5.1.tgz", + "integrity": "sha512-Yb4QJOaGLIcmB0VY7Wif5AjvLMUFAdV57D2TWEva1Y0kU/3LjKpeRVmlMIfuO1SVbauve459kgtIizADqxMWPg==", "dev": true, "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "debug": "^4.1.1", + "lodash": "^4.17.15" }, "engines": { - "node": ">=8" + "node": ">=6.0.0" + }, + "peerDependencies": { + "mocha": ">=3.1.2" } }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/mocha/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, + "license": "Python-2.0" + }, + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" + "argparse": "^2.0.1" }, - "engines": { - "node": ">=8" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/possible-typed-array-names": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", - "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } + "node_modules/monaco-editor": { + "version": "0.52.2", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz", + "integrity": "sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==", + "license": "MIT" }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "node_modules/monaco-editor-webpack-plugin": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-7.1.1.tgz", + "integrity": "sha512-WxdbFHS3Wtz4V9hzhe/Xog5hQRSMxmDLkEEYZwqMDHgJlkZo00HVFZR0j5d0nKypjTUkkygH3dDSXERLG4757A==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" + "loader-utils": "^2.0.2" }, - "engines": { - "node": "^10 || ^12 || >=14" + "peerDependencies": { + "monaco-editor": ">= 0.31.0", + "webpack": "^4.5.0 || 5.x" } }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", - "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", - "dev": true, - "license": "ISC", + "node_modules/mongodb": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-7.0.0.tgz", + "integrity": "sha512-vG/A5cQrvGGvZm2mTnCSz1LUcbOPl83hfB6bxULKQ8oFZauyox/2xbZOoGNl+64m8VBrETkdGCDBdOsCr3F3jg==", + "license": "Apache-2.0", + "dependencies": { + "@mongodb-js/saslprep": "^1.3.0", + "bson": "^7.0.0", + "mongodb-connection-string-url": "^7.0.0" + }, "engines": { - "node": "^10 || ^12 || >= 14" + "node": ">=20.19.0" }, "peerDependencies": { - "postcss": "^8.1.0" + "@aws-sdk/credential-providers": "^3.806.0", + "@mongodb-js/zstd": "^7.0.0", + "gcp-metadata": "^7.0.1", + "kerberos": "^7.0.0", + "mongodb-client-encryption": ">=7.0.0 <7.1.0", + "snappy": "^7.3.2", + "socks": "^2.8.6" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } } }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", - "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", - "dev": true, + "node_modules/mongodb-connection-string-url": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz", + "integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==", + "license": "Apache-2.0", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^14.1.0 || ^13.0.0" + } + }, + "node_modules/mongodb-explain-compat": { + "version": "3.3.23", + "resolved": "https://registry.npmjs.org/mongodb-explain-compat/-/mongodb-explain-compat-3.3.23.tgz", + "integrity": "sha512-3OygQjzjHr0hsT3y0f91yP7Ylp+2bbEM3IPil2yv+9avmGhA9Ru+CcgTXI+IfkfNlbcly/w7alvHDk+dlX28QQ==", + "license": "SSPL" + }, + "node_modules/mongodb/node_modules/@types/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-N8WXpbE6Wgri7KUSvrmQcqrMllKZ9uxkYWMt+mCSGwNc0Hsw9VQTW7ApqI4XNrx6/SaM2QQJCzMPDEXE058s+Q==", "license": "MIT", "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^7.0.0", - "postcss-value-parser": "^4.1.0" + "@types/webidl-conversions": "*" + } + }, + "node_modules/mongodb/node_modules/mongodb-connection-string-url": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-7.0.0.tgz", + "integrity": "sha512-irhhjRVLE20hbkRl4zpAYLnDMM+zIZnp0IDB9akAFFUZp/3XdOfwwddc7y6cNvF2WCEtfTYRwYbIfYa2kVY0og==", + "license": "Apache-2.0", + "dependencies": { + "@types/whatwg-url": "^13.0.0", + "whatwg-url": "^14.1.0" }, "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "node": ">=20.19.0" } }, - "node_modules/postcss-modules-scope": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", - "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", + "node_modules/moo": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", + "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==", + "license": "BSD-3-Clause" + }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", "dev": true, - "license": "ISC", - "dependencies": { - "postcss-selector-parser": "^7.0.0" - }, + "license": "MIT", "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "node": ">=10" } }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "icss-utils": "^5.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" }, - "peerDependencies": { - "postcss": "^8.1.0" + "bin": { + "multicast-dns": "cli.js" } }, - "node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "dev": true, + "node_modules/multiple-select-vanilla": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/multiple-select-vanilla/-/multiple-select-vanilla-4.4.0.tgz", + "integrity": "sha512-QxZep610yATWMZhDMq0kzZWZSTb/Iffc0OdknY1El5SOjSm0o7CSHxN7CfOJRlbSyYGNv4TyFlL5A8FRN08F2A==", "license": "MIT", "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" + "@types/trusted-types": "^2.0.7" }, - "engines": { - "node": ">=4" + "funding": { + "type": "ko_fi", + "url": "https://ko-fi.com/ghiscoding" } }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true, - "license": "MIT" + "license": "ISC" }, - "node_modules/prebuild-install": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", - "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", - "optional": true, - "dependencies": { - "detect-libc": "^2.0.0", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^2.0.0", - "node-abi": "^3.3.0", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^4.0.0", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - }, "bin": { - "prebuild-install": "bin.js" + "nanoid": "bin/nanoid.cjs" }, "engines": { - "node": ">=10" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } + "optional": true }, - "node_modules/prettier": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", - "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", "dev": true, "license": "MIT", "bin": { - "prettier": "bin/prettier.cjs" + "napi-postinstall": "lib/cli.js" }, "engines": { - "node": ">=14" + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "url": "https://opencollective.com/napi-postinstall" } }, - "node_modules/prettier-plugin-organize-imports": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-4.3.0.tgz", - "integrity": "sha512-FxFz0qFhyBsGdIsb697f/EkvHzi5SZOhWAjxcx2dLt+Q532bAlhswcXGYB1yzjZ69kW8UoadFBw7TyNwlq96Iw==", + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, - "license": "MIT", - "peerDependencies": { - "prettier": ">=2.0", - "typescript": ">=2.9", - "vue-tsc": "^2.1.0 || 3" - }, - "peerDependenciesMeta": { - "vue-tsc": { - "optional": true - } - } + "license": "MIT" }, - "node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", - "dev": true, + "node_modules/nearley": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", + "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", "license": "MIT", "dependencies": { - "@jest/schemas": "30.0.5", - "ansi-styles": "^5.2.0", - "react-is": "^18.3.1" + "commander": "^2.19.0", + "moo": "^0.5.0", + "railroad-diagrams": "^1.0.0", + "randexp": "0.4.6" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" + "bin": { + "nearley-railroad": "bin/nearley-railroad.js", + "nearley-test": "bin/nearley-test.js", + "nearley-unparse": "bin/nearley-unparse.js", + "nearleyc": "bin/nearleyc.js" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "individual", + "url": "https://nearley.js.org/#give-to-nearley" } }, - "node_modules/pretty-format/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true, + "node_modules/nearley/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "license": "MIT" }, - "node_modules/priorityqueuejs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/priorityqueuejs/-/priorityqueuejs-2.0.0.tgz", - "integrity": "sha512-19BMarhgpq3x4ccvVi8k2QpJZcymo/iFUcrhPd4V96kYGovOdTsWwy7fxChYi4QY+m2EnGBWSX9Buakz+tWNQQ==", - "license": "MIT" + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true, "license": "MIT" }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "node_modules/node-abi": { + "version": "3.85.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.85.0.tgz", + "integrity": "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" + "semver": "^7.3.5" }, "engines": { - "node": ">= 6" + "node": ">=10" } }, - "node_modules/property-information": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", - "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", + "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "optional": true + }, + "node_modules/node-forge": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.2.tgz", + "integrity": "sha512-6xKiQ+cph9KImrRh0VsjH2d8/GXA4FIMlgU4B757iI1ApvcyA9VlouP0yZJha01V+huImO+kKMU7ih+2+E14fw==", + "dev": true, + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" } }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "node_modules/node-html-markdown": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/node-html-markdown/-/node-html-markdown-1.3.0.tgz", + "integrity": "sha512-OeFi3QwC/cPjvVKZ114tzzu+YoR+v9UXW5RwSXGUqGb0qCl0DvP406tzdL7SFn8pZrMyzXoisfG2zcuF9+zw4g==", "dev": true, "license": "MIT", "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" + "node-html-parser": "^6.1.1" }, "engines": { - "node": ">= 0.10" + "node": ">=10.0.0" } }, - "node_modules/proxy-addr/node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "node_modules/node-html-parser": { + "version": "6.1.13", + "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.13.tgz", + "integrity": "sha512-qIsTMOY4C/dAa5Q5vsobRpOOvPfC4pB61UVW2uSwZNUp0QU/jCekTal1vMmbO0DgdHeLUJpv/ARmDqErVxA3Sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-select": "^5.1.0", + "he": "1.2.0" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-sarif-builder": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/node-sarif-builder/-/node-sarif-builder-3.3.1.tgz", + "integrity": "sha512-8z5dAbhpxmk/WRQHXlv4V0h+9Y4Ugk+w08lyhV/7E/CQX9yDdBc3025/EG+RSMJU2aPFh/IQ7XDV7Ti5TLt/TA==", "dev": true, "license": "MIT", + "dependencies": { + "@types/sarif": "^2.1.7", + "fs-extra": "^11.1.1" + }, "engines": { - "node": ">= 0.10" + "node": ">=20" } }, - "node_modules/pseudo-localization": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/pseudo-localization/-/pseudo-localization-2.4.0.tgz", - "integrity": "sha512-ISYMOKY8+f+PmiXMFw2y6KLY74LBrv/8ml/VjjoVEV2k+MS+OJZz7ydciK5ntJwxPrKQPTU1+oXq9Mx2b0zEzg==", + "node_modules/normalize-package-data": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", + "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "flat": "^5.0.2", - "get-stdin": "^7.0.0", - "typescript": "^4.7.4", - "yargs": "^17.2.1" + "hosted-git-info": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" }, - "bin": { - "pseudo-localization": "bin/pseudo-localize" + "engines": { + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/pseudo-localization/node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "node_modules/normalize-package-data/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" }, "engines": { - "node": ">=4.2.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/pump": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", - "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "node_modules/normalize-package-data/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } + "license": "ISC" }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/punycode.js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "node_modules/normalize-url": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.1.0.tgz", + "integrity": "sha512-X06Mfd/5aKsRHc0O0J5CUedwnPmnDtLF2+nq+KN9KSDlJHkPuh0JUviWjEWMe0SW/9TDdSLVPuk7L5gGTIA1/w==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pure-rand": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz", - "integrity": "sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "license": "MIT" - }, - "node_modules/qs": { - "version": "6.14.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", - "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "side-channel": "^1.1.0" + "path-key": "^3.0.0" }, "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "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" + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==", - "license": "CC0-1.0" - }, - "node_modules/randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, "license": "MIT", - "dependencies": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" - }, "engines": { - "node": ">=0.12" + "node": ">= 0.4" } }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, "license": "MIT", "dependencies": { - "safe-buffer": "^5.1.0" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/raw-body": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", - "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, "license": "MIT", "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "unpipe": "~1.0.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" } }, - "node_modules/raw-body/node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, - "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true, + "license": "MIT" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dev": true, "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "ee-first": "1.1.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, - "node_modules/raw-body/node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" } }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "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": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "license": "ISC", "optional": true, "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" + "wrappy": "1" } }, - "node_modules/rc-config-loader": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/rc-config-loader/-/rc-config-loader-4.1.3.tgz", - "integrity": "sha512-kD7FqML7l800i6pS6pvLyIE2ncbk9Du8Q0gp/4hMPhJU6ZxApkoLcGD8ZeqgiAlfwZ6BlETq6qqe+12DUL207w==", + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "license": "MIT", "dependencies": { - "debug": "^4.3.4", - "js-yaml": "^4.1.0", - "json5": "^2.2.2", - "require-from-string": "^2.0.2" + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/rc-config-loader/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, - "license": "Python-2.0" - }, - "node_modules/rc-config-loader/node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", - "dev": true, + "node_modules/open": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", "license": "MIT", "dependencies": { - "argparse": "^2.0.1" + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "license": "MIT", - "optional": true, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/react": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", - "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "dev": true, + "license": "(WTFPL OR MIT)", + "bin": { + "opener": "bin/opener-bin.js" } }, - "node_modules/react-dom": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", - "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, "license": "MIT", "dependencies": { - "scheduler": "^0.27.0" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, - "peerDependencies": { - "react": "^19.2.0" - } - }, - "node_modules/react-hotkeys-hook": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-5.2.1.tgz", - "integrity": "sha512-xbKh6zJxd/vJHT4Bw4+0pBD662Fk20V+VFhLqciCg+manTVO4qlqRqiwFOYelfHN9dBvWj9vxaPkSS26ZSIJGg==", - "license": "MIT", - "workspaces": [ - "packages/*" - ], - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "license": "MIT" - }, - "node_modules/react-markdown": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz", - "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==", + "node_modules/ora": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", + "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", + "dev": true, "license": "MIT", "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "hast-util-to-jsx-runtime": "^2.0.0", - "html-url-attributes": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.0.0", - "unified": "^11.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" + "chalk": "^5.3.0", + "cli-cursor": "^5.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=18" }, - "peerDependencies": { - "@types/react": ">=18", - "react": ">=18" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/react-refresh": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", - "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "node_modules/ora/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", + "node_modules/ora/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", "dev": true, - "license": "ISC", - "dependencies": { - "mute-stream": "~0.0.4" - }, - "engines": { - "node": ">=0.8" - } + "license": "MIT" }, - "node_modules/read-pkg": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", - "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", + "node_modules/ora/node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", "dev": true, "license": "MIT", - "dependencies": { - "@types/normalize-package-data": "^2.4.3", - "normalize-package-data": "^6.0.0", - "parse-json": "^8.0.0", - "type-fest": "^4.6.0", - "unicorn-magic": "^0.1.0" - }, "engines": { "node": ">=18" }, @@ -18734,16 +16531,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg/node_modules/parse-json": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", - "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", + "node_modules/ora/node_modules/log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "index-to-position": "^1.1.0", - "type-fest": "^4.39.1" + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" }, "engines": { "node": ">=18" @@ -18752,25 +16548,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "node_modules/ora/node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "MIT", "engines": { - "node": ">=16" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg/node_modules/unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "node_modules/ora/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, "engines": { "node": ">=18" }, @@ -18778,351 +16579,310 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", "dev": true, "license": "MIT", "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true, - "license": "MIT", + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, "engines": { - "node": ">= 14.18.0" + "node": ">= 0.4" }, "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/rechoir": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", - "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "node_modules/p-cancelable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", "dev": true, "license": "MIT", - "dependencies": { - "resolve": "^1.20.0" - }, "engines": { - "node": ">= 10.13.0" + "node": ">=12.20" } }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", - "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.1", - "which-builtin-type": "^1.2.1" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "license": "MIT" - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", - "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "set-function-name": "^2.0.2" + "p-limit": "^3.0.2" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/remark-parse": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", - "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "node_modules/p-map": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", + "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unified": "^11.0.0" + "engines": { + "node": ">=18" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/remark-rehype": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", - "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", + "node_modules/p-retry": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz", + "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==", + "dev": true, "license": "MIT", "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "mdast-util-to-hast": "^13.0.0", - "unified": "^11.0.0", - "vfile": "^6.0.0" + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", + "retry": "^0.13.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/requireindex": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", - "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.5" - } + "license": "BlueOak-1.0.0" }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "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" + "license": "(MIT AND Zlib)" }, - "node_modules/resolve": { - "version": "1.22.11", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", - "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "license": "MIT", "dependencies": { - "is-core-module": "^2.16.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" + "callsites": "^3.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=6" + } + }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", "license": "MIT" }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "license": "MIT", "dependencies": { - "resolve-from": "^5.0.0" + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/resolve-cwd/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "node_modules/parse-semver": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", + "integrity": "sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "semver": "^5.1.0" } }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "node_modules/parse-semver/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" + "license": "ISC", + "bin": { + "semver": "bin/semver" } }, - "node_modules/resolve.exports": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", - "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/responselike": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", - "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", + "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", "dev": true, "license": "MIT", "dependencies": { - "lowercase-keys": "^3.0.0" - }, - "engines": { - "node": ">=14.16" + "domhandler": "^5.0.3", + "parse5": "^7.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/restore-cursor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", - "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "node_modules/parse5-parser-stream": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", + "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", "dev": true, "license": "MIT", "dependencies": { - "onetime": "^7.0.0", - "signal-exit": "^4.1.0" - }, - "engines": { - "node": ">=18" + "parse5": "^7.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/restore-cursor/node_modules/onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "dev": true, - "license": "MIT", - "dependencies": { - "mimic-function": "^5.0.0" - }, + "license": "BSD-2-Clause", "engines": { - "node": ">=18" + "node": ">=0.12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/restore-cursor/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" + "node_modules/parseley": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.7.0.tgz", + "integrity": "sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw==", + "license": "MIT", + "dependencies": { + "moo": "^0.5.1", + "nearley": "^2.20.1" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://ko-fi.com/killymxi" } }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, "license": "MIT", "engines": { - "node": ">=0.12" + "node": ">= 0.8" } }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "license": "MIT", "engines": { - "node": ">= 4" + "node": ">=8" } }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "license": "MIT", "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/rimraf": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.2.tgz", - "integrity": "sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==", + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", + "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { - "glob": "^13.0.0", - "package-json-from-dist": "^1.0.1" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" }, "engines": { "node": "20 || >=22" @@ -19131,1094 +16891,1236 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rtl-css-js": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz", - "integrity": "sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.1.2" - } - }, - "node_modules/run-applescript": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", - "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.2.tgz", + "integrity": "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==", "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": { - "queue-microtask": "^1.2.2" + "license": "ISC", + "engines": { + "node": "20 || >=22" } }, - "node_modules/run-script-os": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/run-script-os/-/run-script-os-1.1.6.tgz", - "integrity": "sha512-ql6P2LzhBTTDfzKts+Qo4H94VUKpxKDFz6QxxwaUZN0mwvi7L3lpOI7BqPCq7lgDh3XLl0dpeXwfcVIitlrYrw==", + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "dev": true, - "license": "MIT", - "bin": { - "run-os": "index.js", - "run-script-os": "index.js" - } + "license": "MIT" }, - "node_modules/safe-array-concat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", - "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "has-symbols": "^1.1.0", - "isarray": "^2.0.5" - }, + "node_modules/path-type": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", + "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=0.4" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/safe-array-concat/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "dev": true, "license": "MIT" }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "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/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" }, - "node_modules/safe-push-apply": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", - "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "isarray": "^2.0.5" - }, "engines": { - "node": ">= 0.4" + "node": ">=8.6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/safe-push-apply/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">= 6" + } }, - "node_modules/safe-regex-test": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "node_modules/piscina": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.9.2.tgz", + "integrity": "sha512-Fq0FERJWFEUpB4eSY59wSNwXD4RYqR+nR/WiEVcZW8IWfVBxJJafcgTEZDQo8k3w0sUarJ8RyVbbUF4GQ2LGbQ==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "@napi-rs/nice": "^1.0.1" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-regex": "^1.2.1" + "find-up": "^4.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/sass": { - "version": "1.94.2", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.94.2.tgz", - "integrity": "sha512-N+7WK20/wOr7CzA2snJcUSSNTCzeCGUTFY3OgeQP3mZ1aj9NMQ0mSTXwlrnd89j33zzQJGqIN52GIOmYrfq46A==", + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "license": "MIT", "dependencies": { - "chokidar": "^4.0.0", - "immutable": "^5.0.2", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" + "p-locate": "^4.1.0" }, "engines": { - "node": ">=14.0.0" - }, - "optionalDependencies": { - "@parcel/watcher": "^2.4.1" + "node": ">=8" } }, - "node_modules/sass-loader": { - "version": "16.0.6", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.6.tgz", - "integrity": "sha512-sglGzId5gmlfxNs4gK2U3h7HlVRfx278YK6Ono5lwzuvi1jxig80YiuHkaDBVsYIKFhx8wN7XSCI0M2IDS/3qA==", + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "license": "MIT", "dependencies": { - "neo-async": "^2.6.2" + "p-try": "^2.0.0" }, "engines": { - "node": ">= 18.12.0" + "node": ">=6" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", - "sass": "^1.3.0", - "sass-embedded": "*", - "webpack": "^5.0.0" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "webpack": { - "optional": true - } + "engines": { + "node": ">=8" } }, - "node_modules/sax": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz", - "integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==", + "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": "BlueOak-1.0.0" + "license": "MIT", + "engines": { + "node": ">=4" + } }, - "node_modules/scheduler": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", - "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", - "license": "MIT" + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } }, - "node_modules/schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { - "node": ">= 10.13.0" + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/secretlint": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/secretlint/-/secretlint-10.2.2.tgz", - "integrity": "sha512-xVpkeHV/aoWe4vP4TansF622nBEImzCY73y/0042DuJ29iKIaqgoJ8fGxre3rVSHHbxar4FdJobmTnLp9AU0eg==", + "node_modules/postcss-modules-local-by-default": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", + "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", "dev": true, "license": "MIT", "dependencies": { - "@secretlint/config-creator": "^10.2.2", - "@secretlint/formatter": "^10.2.2", - "@secretlint/node": "^10.2.2", - "@secretlint/profiler": "^10.2.2", - "debug": "^4.4.1", - "globby": "^14.1.0", - "read-pkg": "^9.0.1" - }, - "bin": { - "secretlint": "bin/secretlint.js" + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.1.0" }, "engines": { - "node": ">=20.0.0" + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/seek-bzip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-2.0.0.tgz", - "integrity": "sha512-SMguiTnYrhpLdk3PwfzHeotrcwi8bNV4iemL9tx9poR/yeaMYwB9VzR1w7b57DuWpuqR8n6oZboi0hj3AxZxQg==", + "node_modules/postcss-modules-scope": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", + "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "commander": "^6.0.0" + "postcss-selector-parser": "^7.0.0" }, - "bin": { - "seek-bunzip": "bin/seek-bunzip", - "seek-table": "bin/seek-bzip-table" + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/seek-bzip/node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "icss-utils": "^5.0.0" + }, "engines": { - "node": ">= 6" + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/selderee": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.6.0.tgz", - "integrity": "sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg==", + "node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "dev": true, "license": "MIT", "dependencies": { - "parseley": "^0.7.0" + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" }, - "funding": { - "url": "https://ko-fi.com/killymxi" + "engines": { + "node": ">=4" } }, - "node_modules/select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true, "license": "MIT" }, - "node_modules/selfsigned": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "@types/node-forge": "^1.3.0", - "node-forge": "^1" + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" }, "engines": { "node": ">=10" } }, - "node_modules/semaphore": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", - "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=0.8.0" + "node": ">= 0.8.0" } }, - "node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "license": "ISC", + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true, + "license": "MIT", "bin": { - "semver": "bin/semver.js" + "prettier": "bin/prettier.cjs" }, "engines": { - "node": ">=10" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/semver-regex": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-4.0.5.tgz", - "integrity": "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==", + "node_modules/prettier-plugin-organize-imports": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-4.3.0.tgz", + "integrity": "sha512-FxFz0qFhyBsGdIsb697f/EkvHzi5SZOhWAjxcx2dLt+Q532bAlhswcXGYB1yzjZ69kW8UoadFBw7TyNwlq96Iw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=12" + "peerDependencies": { + "prettier": ">=2.0", + "typescript": ">=2.9", + "vue-tsc": "^2.1.0 || 3" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependenciesMeta": { + "vue-tsc": { + "optional": true + } } }, - "node_modules/semver-truncate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-3.0.0.tgz", - "integrity": "sha512-LJWA9kSvMolR51oDE6PN3kALBNaUdkxzAGcexw8gjMA8xr5zUqK0JiR3CgARSqanYF3Z1YHvsErb1KDgh+v7Rg==", + "node_modules/pretty-format": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", + "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", "dev": true, "license": "MIT", "dependencies": { - "semver": "^7.3.5" + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, "engines": { - "node": ">= 0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/pretty-format/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } + "license": "MIT" }, - "node_modules/send/node_modules/debug/node_modules/ms": { + "node_modules/priorityqueuejs": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "resolved": "https://registry.npmjs.org/priorityqueuejs/-/priorityqueuejs-2.0.0.tgz", + "integrity": "sha512-19BMarhgpq3x4ccvVi8k2QpJZcymo/iFUcrhPd4V96kYGovOdTsWwy7fxChYi4QY+m2EnGBWSX9Buakz+tWNQQ==", + "license": "MIT" + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true, "license": "MIT" }, - "node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">= 0.10" } }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "node_modules/pseudo-localization": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/pseudo-localization/-/pseudo-localization-2.4.0.tgz", + "integrity": "sha512-ISYMOKY8+f+PmiXMFw2y6KLY74LBrv/8ml/VjjoVEV2k+MS+OJZz7ydciK5ntJwxPrKQPTU1+oXq9Mx2b0zEzg==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "randombytes": "^2.1.0" + "flat": "^5.0.2", + "get-stdin": "^7.0.0", + "typescript": "^4.7.4", + "yargs": "^17.2.1" + }, + "bin": { + "pseudo-localization": "bin/pseudo-localize" } }, - "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "node_modules/pseudo-localization/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": "MIT", - "dependencies": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" }, "engines": { - "node": ">= 0.8.0" + "node": ">=4.2.0" } }, - "node_modules/serve-index/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "ms": "2.0.0" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, - "node_modules/serve-index/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=6" } }, - "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", "dev": true, "license": "MIT", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, "engines": { - "node": ">= 0.6" + "node": ">=6" } }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "node_modules/pure-rand": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz", + "integrity": "sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==", "dev": true, - "license": "ISC" + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" }, - "node_modules/serve-index/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "node_modules/qs": { + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", "dev": true, - "license": "MIT" + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, - "license": "ISC" + "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/serve-index/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "dev": true, + "node_modules/railroad-diagrams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==", + "license": "CC0-1.0" + }, + "node_modules/randexp": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", "license": "MIT", "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" + "discontinuous-range": "1.0.0", + "ret": "~0.1.10" }, "engines": { - "node": ">= 0.8.0" + "node": ">=0.12" } }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "license": "MIT", "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" + "safe-buffer": "^5.1.0" } }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true, "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, "engines": { - "node": ">= 0.4" + "node": ">= 0.6" } }, - "node_modules/set-proto": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", - "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", "dev": true, "license": "MIT", "dependencies": { - "dunder-proto": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" }, "engines": { - "node": ">= 0.4" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true, - "license": "MIT" - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true, - "license": "ISC" + "node": ">= 0.8" + } }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "node_modules/raw-body/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "dev": true, "license": "MIT", "dependencies": { - "kind-of": "^6.0.2" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "engines": { - "node": ">=8" + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "license": "MIT", "dependencies": { - "shebang-regex": "^3.0.0" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "node_modules/raw-body/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 0.8" } }, - "node_modules/shell-quote": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", - "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "optional": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "rc": "cli.js" } }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "node_modules/rc-config-loader": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/rc-config-loader/-/rc-config-loader-4.1.3.tgz", + "integrity": "sha512-kD7FqML7l800i6pS6pvLyIE2ncbk9Du8Q0gp/4hMPhJU6ZxApkoLcGD8ZeqgiAlfwZ6BlETq6qqe+12DUL207w==", "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "debug": "^4.3.4", + "js-yaml": "^4.1.0", + "json5": "^2.2.2", + "require-from-string": "^2.0.2" } }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "node_modules/rc-config-loader/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, + "license": "Python-2.0" + }, + "node_modules/rc-config-loader/node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" + "argparse": "^2.0.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "dev": true, "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, + "optional": true, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dev": true, + "node_modules/react": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", + "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" + "node_modules/react-dom": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", + "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.0" + } }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "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" - } + "node_modules/react-hotkeys-hook": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-5.2.1.tgz", + "integrity": "sha512-xbKh6zJxd/vJHT4Bw4+0pBD662Fk20V+VFhLqciCg+manTVO4qlqRqiwFOYelfHN9dBvWj9vxaPkSS26ZSIJGg==", + "license": "MIT", + "workspaces": [ + "packages/*" ], + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, + "node_modules/react-markdown": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz", + "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==", "license": "MIT", - "optional": true + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "html-url-attributes": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=18", + "react": ">=18" + } }, - "node_modules/simple-get": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", "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", - "optional": true, - "dependencies": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/sirv": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", - "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", + "node_modules/read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@polka/url": "^1.0.0-next.24", - "mrmime": "^2.0.0", - "totalist": "^3.0.0" + "mute-stream": "~0.0.4" }, "engines": { - "node": ">= 10" + "node": ">=0.8" } }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true, - "license": "MIT" - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/read-pkg": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", + "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", "dev": true, "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.3", + "normalize-package-data": "^6.0.0", + "parse-json": "^8.0.0", + "type-fest": "^4.6.0", + "unicorn-magic": "^0.1.0" + }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "node_modules/read-pkg/node_modules/parse-json": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", + "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" + "@babel/code-frame": "^7.26.2", + "index-to-position": "^1.1.0", + "type-fest": "^4.39.1" }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/slickgrid-react": { - "version": "9.9.0", - "resolved": "https://registry.npmjs.org/slickgrid-react/-/slickgrid-react-9.9.0.tgz", - "integrity": "sha512-KUDIx3ErHGfYV4SzY4bkF7dseLM/jucc7PG+0ZoI6CsBySsUqaFhjZqBN9VUuxFRQJAzuB2KfQ5FvQyHylgyAg==", + "node_modules/read-pkg/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, "license": "MIT", - "dependencies": { - "@slickgrid-universal/common": "9.9.0", - "@slickgrid-universal/custom-footer-component": "9.9.0", - "@slickgrid-universal/empty-warning-component": "9.9.0", - "@slickgrid-universal/event-pub-sub": "9.9.0", - "@slickgrid-universal/pagination-component": "9.9.0", - "@slickgrid-universal/row-detail-view-plugin": "9.9.0", - "@slickgrid-universal/utils": "9.9.0", - "dequal": "^2.0.3", - "sortablejs": "^1.15.6" + "engines": { + "node": ">=18" }, - "peerDependencies": { - "react": ">=19.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "license": "MIT", "dependencies": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/sort-keys": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", - "integrity": "sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==", + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", "dev": true, "license": "MIT", "dependencies": { - "is-plain-obj": "^1.0.0" + "resolve": "^1.20.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 10.13.0" } }, - "node_modules/sort-keys-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", - "integrity": "sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==", + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, "license": "MIT", "dependencies": { - "sort-keys": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/sortablejs": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.6.tgz", - "integrity": "sha512-aNfiuwMEpfBM/CN6LY0ibyhxPfPbyFeBTYJKCvzkJ2GkUpazIt3H+QIPAMHwqQ7tMKaHz1Qj+rJJCqljnf4p3A==", + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", "license": "MIT" }, - "node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, "engines": { - "node": ">= 12" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, + "node_modules/remark-rehype": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", "license": "MIT", "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/space-separated-tokens": { + "node_modules/require-from-string": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "node_modules/requireindex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", + "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "dev": true, "license": "MIT", - "dependencies": { - "memory-pager": "^1.0.2" + "engines": { + "node": ">=0.10.5" } }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true, - "license": "Apache-2.0", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dev": true, + "license": "MIT", "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", "dev": true, - "license": "CC-BY-3.0" + "license": "MIT" }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, "license": "MIT", "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/spdx-license-ids": { - "version": "3.0.22", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", - "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, - "license": "CC0-1.0" + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "node_modules/spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "license": "MIT", - "dependencies": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - }, "engines": { - "node": ">=6.0.0" + "node": ">=4" } }, - "node_modules/spdy-transport": { + "node_modules/responselike": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", + "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", "dev": true, "license": "MIT", "dependencies": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" + "lowercase-keys": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/spdy-transport/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, "license": "MIT", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" }, "engines": { - "node": ">= 6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "node_modules/restore-cursor/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "dev": true, "license": "MIT", "dependencies": { - "escape-string-regexp": "^2.0.0" + "mimic-function": "^5.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/stackframe": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", - "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "license": "MIT" + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, - "node_modules/state-local": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz", - "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==", - "license": "MIT" + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "license": "MIT", + "engines": { + "node": ">=0.12" + } }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">= 4" } }, - "node_modules/stdin-discarder": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", - "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.2.tgz", + "integrity": "sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g==", "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "glob": "^13.0.0", + "package-json-from-dist": "^1.0.1" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rtl-css-js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz", + "integrity": "sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.1.2" + } + }, + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", "license": "MIT", "engines": { "node": ">=18" @@ -20227,1274 +18129,1245 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/stop-iteration-iterator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", - "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "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": { - "es-errors": "^1.3.0", - "internal-slot": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" + "queue-microtask": "^1.2.2" } }, - "node_modules/streamx": { - "version": "2.23.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", - "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", + "node_modules/run-script-os": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/run-script-os/-/run-script-os-1.1.6.tgz", + "integrity": "sha512-ql6P2LzhBTTDfzKts+Qo4H94VUKpxKDFz6QxxwaUZN0mwvi7L3lpOI7BqPCq7lgDh3XLl0dpeXwfcVIitlrYrw==", "dev": true, "license": "MIT", - "dependencies": { - "events-universal": "^1.0.0", - "fast-fifo": "^1.3.2", - "text-decoder": "^1.1.0" + "bin": { + "run-os": "index.js", + "run-script-os": "index.js" } }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, "license": "MIT", "dependencies": { - "safe-buffer": "~5.1.0" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true, "license": "MIT" }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "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/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", "dev": true, "license": "MIT", "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" + "es-errors": "^1.3.0", + "isarray": "^2.0.5" }, "engines": { - "node": ">=10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string-length/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==", + "node_modules/safe-push-apply/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string-length/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==", + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sass": { + "version": "1.94.2", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.94.2.tgz", + "integrity": "sha512-N+7WK20/wOr7CzA2snJcUSSNTCzeCGUTFY3OgeQP3mZ1aj9NMQ0mSTXwlrnd89j33zzQJGqIN52GIOmYrfq46A==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "chokidar": "^4.0.0", + "immutable": "^5.0.2", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" }, "engines": { - "node": ">=8" + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" } }, - "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==", + "node_modules/sass-loader": { + "version": "16.0.6", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.6.tgz", + "integrity": "sha512-sglGzId5gmlfxNs4gK2U3h7HlVRfx278YK6Ono5lwzuvi1jxig80YiuHkaDBVsYIKFhx8wN7XSCI0M2IDS/3qA==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "neo-async": "^2.6.2" }, "engines": { - "node": ">=8" + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "webpack": { + "optional": true + } } }, - "node_modules/string-width-cjs": { - "name": "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==", + "node_modules/sax": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz", + "integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/schema-utils": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" }, "engines": { - "node": ">=8" + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/string-width-cjs/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==", + "node_modules/secretlint": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/secretlint/-/secretlint-10.2.2.tgz", + "integrity": "sha512-xVpkeHV/aoWe4vP4TansF622nBEImzCY73y/0042DuJ29iKIaqgoJ8fGxre3rVSHHbxar4FdJobmTnLp9AU0eg==", "dev": true, "license": "MIT", + "dependencies": { + "@secretlint/config-creator": "^10.2.2", + "@secretlint/formatter": "^10.2.2", + "@secretlint/node": "^10.2.2", + "@secretlint/profiler": "^10.2.2", + "debug": "^4.4.1", + "globby": "^14.1.0", + "read-pkg": "^9.0.1" + }, + "bin": { + "secretlint": "bin/secretlint.js" + }, "engines": { - "node": ">=8" + "node": ">=20.0.0" } }, - "node_modules/string-width-cjs/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==", + "node_modules/seek-bzip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-2.0.0.tgz", + "integrity": "sha512-SMguiTnYrhpLdk3PwfzHeotrcwi8bNV4iemL9tx9poR/yeaMYwB9VzR1w7b57DuWpuqR8n6oZboi0hj3AxZxQg==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "commander": "^6.0.0" }, - "engines": { - "node": ">=8" + "bin": { + "seek-bunzip": "bin/seek-bunzip", + "seek-table": "bin/seek-bzip-table" } }, - "node_modules/string-width/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==", + "node_modules/seek-bzip/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/string-width/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, + "node_modules/selderee": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.6.0.tgz", + "integrity": "sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg==", "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "parseley": "^0.7.0" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://ko-fi.com/killymxi" } }, - "node_modules/string.prototype.trim": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", - "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true, + "license": "MIT" + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-data-property": "^1.1.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-object-atoms": "^1.0.0", - "has-property-descriptors": "^1.0.2" + "@types/node-forge": "^1.3.0", + "node-forge": "^1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10" } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", - "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, + "node_modules/semaphore": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", + "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.8.0" } }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10" } }, - "node_modules/stringify-entities": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", - "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "node_modules/semver-regex": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-4.0.5.tgz", + "integrity": "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==", + "dev": true, "license": "MIT", - "dependencies": { - "character-entities-html4": "^2.0.0", - "character-entities-legacy": "^3.0.0" + "engines": { + "node": ">=12" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "node_modules/semver-truncate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-3.0.0.tgz", + "integrity": "sha512-LJWA9kSvMolR51oDE6PN3kALBNaUdkxzAGcexw8gjMA8xr5zUqK0JiR3CgARSqanYF3Z1YHvsErb1KDgh+v7Rg==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "semver": "^7.3.5" }, "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" }, "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs/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": ">= 0.8.0" } }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-dirs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-3.0.0.tgz", - "integrity": "sha512-I0sdgcFTfKQlUPZyAqPJmSG3HLO9rWDFnxonnIbskYNM3DwFOeTNB5KzVq3dA1GdRAc/25b5Y7UO2TQfKWw4aQ==", - "dev": true, - "license": "ISC", "dependencies": { - "inspect-with-kind": "^1.0.5", - "is-plain-obj": "^1.1.0" + "ms": "2.0.0" } }, - "node_modules/strip-final-newline": { + "node_modules/send/node_modules/debug/node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 0.8" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" } }, - "node_modules/strtok3": { - "version": "10.3.4", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.4.tgz", - "integrity": "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==", + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", "dev": true, "license": "MIT", "dependencies": { - "@tokenizer/token": "^0.3.0" + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" }, "engines": { - "node": ">=18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" + "node": ">= 0.8.0" } }, - "node_modules/structured-source": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/structured-source/-/structured-source-4.0.0.tgz", - "integrity": "sha512-qGzRFNJDjFieQkl/sVOI2dUjHKRyL9dAJi2gCPGJLbJHBIkyOHxjuocpIEfbLioX+qSJpvbYdT49/YCdMznKxA==", + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "boundary": "^2.0.0" + "ms": "2.0.0" } }, - "node_modules/style-loader": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-4.0.0.tgz", - "integrity": "sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA==", + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", "dev": true, "license": "MIT", "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.27.0" + "node": ">= 0.6" } }, - "node_modules/style-to-js": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", - "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, "license": "MIT", "dependencies": { - "style-to-object": "1.0.14" + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" } }, - "node_modules/style-to-object": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", - "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", - "license": "MIT", - "dependencies": { - "inline-style-parser": "0.2.7" - } + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true, + "license": "ISC" }, - "node_modules/stylis": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", - "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, "license": "MIT" }, - "node_modules/supports-color": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", - "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">= 0.6" } }, - "node_modules/supports-hyperlinks": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", - "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" }, "engines": { - "node": ">=14.18" - }, - "funding": { - "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" + "node": ">= 0.8.0" } }, - "node_modules/supports-hyperlinks/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/swc-loader": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/swc-loader/-/swc-loader-0.2.6.tgz", - "integrity": "sha512-9Zi9UP2YmDpgmQVbyOPJClY0dwf58JDyDMQ7uRc4krmc72twNI2fvlBWHLqVekBpPc7h5NJkGVT1zNDxFrqhvg==", + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", "dev": true, "license": "MIT", "dependencies": { - "@swc/counter": "^0.1.3" + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" }, - "peerDependencies": { - "@swc/core": "^1.2.147", - "webpack": ">=2" + "engines": { + "node": ">= 0.4" } }, - "node_modules/synckit": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", - "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true, + "license": "MIT" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "dev": true, "license": "MIT", "dependencies": { - "@pkgr/core": "^0.2.9" + "kind-of": "^6.0.2" }, "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/synckit" + "node": ">=8" } }, - "node_modules/table": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", - "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" + "shebang-regex": "^3.0.0" }, "engines": { - "node": ">=10.0.0" + "node": ">=8" } }, - "node_modules/table/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==", + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/table/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==", + "node_modules/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, "engines": { - "node": ">=8" - } - }, - "node_modules/tabster": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/tabster/-/tabster-8.5.6.tgz", - "integrity": "sha512-2vfrRGrx8O9BjdrtSlVA5fvpmbq5HQBRN13XFRg6LAvZ1Fr3QdBnswgT4YgFS5Bhoo5nxwgjRaRueI2Us/dv7g==", - "license": "MIT", - "dependencies": { - "keyborg": "2.6.0", - "tslib": "^2.8.1" + "node": ">= 0.4" }, - "optionalDependencies": { - "@rollup/rollup-linux-x64-gnu": "4.40.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tar-fs": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", - "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tar-fs/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" }, "engines": { - "node": ">= 6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tar-fs/node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tar-stream": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", - "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true, - "license": "MIT", - "dependencies": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" - } + "license": "ISC" }, - "node_modules/tas-client": { - "version": "0.2.33", - "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.2.33.tgz", - "integrity": "sha512-V+uqV66BOQnWxvI6HjDnE4VkInmYZUQ4dgB7gzaDyFyFSK1i1nF/j7DpS9UbQAgV9NaF1XpcyuavnM1qOeiEIg==", - "license": "MIT" + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "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", + "optional": true }, - "node_modules/terminal-link": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-4.0.0.tgz", - "integrity": "sha512-lk+vH+MccxNqgVqSnkMVKx4VLJfnLjDBGzH16JVZjKE2DoxP57s6/vt6JmXV5I3jBcfGrxNrYtC+mPtU7WJztA==", + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", "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", + "optional": true, "dependencies": { - "ansi-escapes": "^7.0.0", - "supports-hyperlinks": "^3.2.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" } }, - "node_modules/terminal-link/node_modules/ansi-escapes": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.2.0.tgz", - "integrity": "sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==", + "node_modules/sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", "dev": true, "license": "MIT", "dependencies": { - "environment": "^1.0.0" + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 10" } }, - "node_modules/terser": { - "version": "5.44.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz", - "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.16", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", - "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", - "jest-worker": "^27.4.5", - "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", - "terser": "^5.31.1" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" }, "engines": { - "node": ">= 10.13.0" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slickgrid-react": { + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/slickgrid-react/-/slickgrid-react-9.9.0.tgz", + "integrity": "sha512-KUDIx3ErHGfYV4SzY4bkF7dseLM/jucc7PG+0ZoI6CsBySsUqaFhjZqBN9VUuxFRQJAzuB2KfQ5FvQyHylgyAg==", + "license": "MIT", + "dependencies": { + "@slickgrid-universal/common": "9.9.0", + "@slickgrid-universal/custom-footer-component": "9.9.0", + "@slickgrid-universal/empty-warning-component": "9.9.0", + "@slickgrid-universal/event-pub-sub": "9.9.0", + "@slickgrid-universal/pagination-component": "9.9.0", + "@slickgrid-universal/row-detail-view-plugin": "9.9.0", + "@slickgrid-universal/utils": "9.9.0", + "dequal": "^2.0.3", + "sortablejs": "^1.15.6" }, "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } + "react": ">=19.0.0" } }, - "node_modules/terser-webpack-plugin/node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-obj": "^1.0.0" }, "engines": { - "node": ">= 10.13.0" + "node": ">=0.10.0" } }, - "node_modules/terser-webpack-plugin/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/sort-keys-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", + "integrity": "sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "sort-keys": "^1.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, + "node_modules/sortablejs": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.6.tgz", + "integrity": "sha512-aNfiuwMEpfBM/CN6LY0ibyhxPfPbyFeBTYJKCvzkJ2GkUpazIt3H+QIPAMHwqQ7tMKaHz1Qj+rJJCqljnf4p3A==", "license": "MIT" }, - "node_modules/terser/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", "dev": true, "license": "BSD-3-Clause", "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/terser/node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "node": ">= 12" } }, - "node_modules/test-exclude": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", - "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^10.4.1", - "minimatch": "^9.0.4" - }, + "license": "BSD-3-Clause", "engines": { - "node": ">=18" + "node": ">=0.10.0" } }, - "node_modules/text-decoder": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", - "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "b4a": "^1.6.4" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true, - "license": "MIT" - }, - "node_modules/textextensions": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-6.11.0.tgz", - "integrity": "sha512-tXJwSr9355kFJI3lbCkPpUH5cP8/M0GGy2xLO34aZCjMXBaK3SoPnZwr/oWmo1FdCnELcs4npdCIOFtq9W3ruQ==", + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "license": "Artistic-2.0", - "dependencies": { - "editions": "^6.21.0" - }, + "license": "BSD-3-Clause", "engines": { - "node": ">=4" - }, - "funding": { - "url": "https://bevry.me/fund" + "node": ">=0.10.0" } }, - "node_modules/thingies": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.5.0.tgz", - "integrity": "sha512-s+2Bwztg6PhWUD7XMfeYm5qliDdSiZm7M7n8KjTkIsm3l/2lgVRc2/Gx/v+ZX8lT4FMA+i8aQvhcWylldc+ZNw==", - "dev": true, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", "license": "MIT", - "engines": { - "node": ">=10.18" - }, "funding": { "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "^2" + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true, - "license": "MIT" - }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", "license": "MIT", "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" + "memory-pager": "^1.0.2" } }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } + "license": "CC-BY-3.0" }, - "node_modules/tmp": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", - "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, "license": "MIT", - "engines": { - "node": ">=14.14" + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "node_modules/spdx-license-ids": { + "version": "3.0.22", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", + "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", "dev": true, - "license": "BSD-3-Clause" + "license": "CC0-1.0" }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", "dev": true, "license": "MIT", "dependencies": { - "is-number": "^7.0.0" + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" }, "engines": { - "node": ">=8.0" + "node": ">=6.0.0" } }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.6" + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" } }, - "node_modules/token-types": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.1.tgz", - "integrity": "sha512-kh9LVIWH5CnL63Ipf0jhlBIy0UsrMj/NJDfpsy1SqOXlLKEVyXXYrnFxFT1yOOYVGBSApeVnjPw/sBz5BfEjAQ==", + "node_modules/spdy-transport/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "license": "MIT", "dependencies": { - "@borewit/text-codec": "^0.1.0", - "@tokenizer/token": "^0.3.0", - "ieee754": "^1.2.1" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, "engines": { - "node": ">=14.16" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" + "node": ">= 6" } }, - "node_modules/totalist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", - "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } + "license": "BSD-3-Clause" }, - "node_modules/tr46": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", - "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, "license": "MIT", "dependencies": { - "punycode": "^2.3.1" + "escape-string-regexp": "^2.0.0" }, "engines": { - "node": ">=18" + "node": ">=10" } }, - "node_modules/tree-dump": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.1.0.tgz", - "integrity": "sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==", + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/trim-lines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", - "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } + "license": "MIT" }, - "node_modules/trough": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", - "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } + "node_modules/state-local": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz", + "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==", + "license": "MIT" }, - "node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" + "node": ">= 0.8" } }, - "node_modules/ts-jest": { - "version": "29.4.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.5.tgz", - "integrity": "sha512-HO3GyiWn2qvTQA4kTgjDcXiMwYQt68a1Y8+JuLRVpdIzm+UOLSHgl/XqR4c6nzJkq5rOkjc02O2I7P7l/Yof0Q==", + "node_modules/stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", "dev": true, "license": "MIT", - "dependencies": { - "bs-logger": "^0.2.6", - "fast-json-stable-stringify": "^2.1.0", - "handlebars": "^4.7.8", - "json5": "^2.2.3", - "lodash.memoize": "^4.1.2", - "make-error": "^1.3.6", - "semver": "^7.7.3", - "type-fest": "^4.41.0", - "yargs-parser": "^21.1.1" - }, - "bin": { - "ts-jest": "cli.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/transform": "^29.0.0 || ^30.0.0", - "@jest/types": "^29.0.0 || ^30.0.0", - "babel-jest": "^29.0.0 || ^30.0.0", - "jest": "^29.0.0 || ^30.0.0", - "jest-util": "^29.0.0 || ^30.0.0", - "typescript": ">=4.3 <6" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@jest/transform": { - "optional": true - }, - "@jest/types": { - "optional": true - }, - "babel-jest": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "jest-util": { - "optional": true - } - } - }, - "node_modules/ts-jest/node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", "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" + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" }, - "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": ">= 0.4" } }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "node_modules/streamx": { + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", + "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", "dev": true, "license": "MIT", "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" } }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "license": "MIT", "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" + "safe-buffer": "~5.1.0" } }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", "dev": true, "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, "engines": { - "node": ">=4" + "node": ">=10" } }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "node_modules/string-length/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": ">=0.6.11 <=0.7.0 || >=0.7.3" + "node": ">=8" } }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "node_modules/string-length/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": "Apache-2.0", - "optional": true, + "license": "MIT", "dependencies": { - "safe-buffer": "^5.0.1" + "ansi-regex": "^5.0.1" }, "engines": { - "node": "*" + "node": ">=8" } }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "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": { - "prelude-ls": "^1.2.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "node_modules/string-width-cjs": { + "name": "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": ">=4" + "node": ">=8" } }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "node_modules/string-width-cjs/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 OR CC0-1.0)", + "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "node_modules/string-width-cjs/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": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/typed-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "node_modules/string-width/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/string-width/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": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=8" } }, - "node_modules/typed-array-byte-length": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", - "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.14" + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -21503,20 +19376,17 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", - "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.15", - "reflect.getprototypeof": "^1.0.9" + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -21525,19 +19395,16 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typed-array-length": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", - "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0", - "reflect.getprototypeof": "^1.0.6" + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -21546,600 +19413,578 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typed-rest-client": { - "version": "1.8.11", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.11.tgz", - "integrity": "sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==", - "dev": true, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", "license": "MIT", "dependencies": { - "qs": "^6.9.1", - "tunnel": "0.0.6", - "underscore": "^1.12.1" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" }, - "engines": { - "node": ">=14.17" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/typescript-eslint": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.47.0.tgz", - "integrity": "sha512-Lwe8i2XQ3WoMjua/r1PHrCTpkubPYJCAfOurtn+mtTzqB6jNd+14n9UN1bJ4s3F49x9ixAm0FLflB/JzQ57M8Q==", + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.47.0", - "@typescript-eslint/parser": "8.47.0", - "@typescript-eslint/typescript-estree": "8.47.0", - "@typescript-eslint/utils": "8.47.0" + "ansi-regex": "^6.0.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/project-service": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.47.0.tgz", - "integrity": "sha512-2X4BX8hUeB5JcA1TQJ7GjcgulXQ+5UkNb0DL8gHsHUHdFoiCTJoYLTpib3LtSDPZsRET5ygN4qqIWrHyYIKERA==", + "node_modules/strip-ansi-cjs": { + "name": "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": { - "@typescript-eslint/tsconfig-utils": "^8.47.0", - "@typescript-eslint/types": "^8.47.0", - "debug": "^4.3.4" + "ansi-regex": "^5.0.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/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/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" } }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/scope-manager": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.47.0.tgz", - "integrity": "sha512-a0TTJk4HXMkfpFkL9/WaGTNuv7JWfFTQFJd6zS9dVAjKsojmv9HT55xzbEpnZoY+VUb+YXLMp+ihMLz/UlZfDg==", + "node_modules/strip-dirs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-3.0.0.tgz", + "integrity": "sha512-I0sdgcFTfKQlUPZyAqPJmSG3HLO9rWDFnxonnIbskYNM3DwFOeTNB5KzVq3dA1GdRAc/25b5Y7UO2TQfKWw4aQ==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@typescript-eslint/types": "8.47.0", - "@typescript-eslint/visitor-keys": "8.47.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "inspect-with-kind": "^1.0.5", + "is-plain-obj": "^1.1.0" } }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.47.0.tgz", - "integrity": "sha512-ybUAvjy4ZCL11uryalkKxuT3w3sXJAuWhOoGS3T/Wu+iUu1tGJmk5ytSY8gbdACNARmcYEB0COksD2j6hfGK2g==", + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" + "node": ">=6" } }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/types": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.47.0.tgz", - "integrity": "sha512-nHAE6bMKsizhA2uuYZbEbmp5z2UpffNrPEqiKIeN7VsV6UY/roxanWfoRrf6x/k9+Obf+GQdkm0nPU+vnMXo9A==", + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=8" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.47.0.tgz", - "integrity": "sha512-k6ti9UepJf5NpzCjH31hQNLHQWupTRPhZ+KFF8WtTuTpy7uHPfeg2NM7cP27aCGajoEplxJDFVCEm9TGPYyiVg==", + "node_modules/strtok3": { + "version": "10.3.4", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.4.tgz", + "integrity": "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.47.0", - "@typescript-eslint/tsconfig-utils": "8.47.0", - "@typescript-eslint/types": "8.47.0", - "@typescript-eslint/visitor-keys": "8.47.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" + "@tokenizer/token": "^0.3.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" + "type": "github", + "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.47.0.tgz", - "integrity": "sha512-g7XrNf25iL4TJOiPqatNuaChyqt49a/onq5YsJ9+hXeugK+41LVg7AxikMfM02PC6jbNtZLCJj6AUcQXJS/jGQ==", + "node_modules/structured-source": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/structured-source/-/structured-source-4.0.0.tgz", + "integrity": "sha512-qGzRFNJDjFieQkl/sVOI2dUjHKRyL9dAJi2gCPGJLbJHBIkyOHxjuocpIEfbLioX+qSJpvbYdT49/YCdMznKxA==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.47.0", - "@typescript-eslint/types": "8.47.0", - "@typescript-eslint/typescript-estree": "8.47.0" - }, + "boundary": "^2.0.0" + } + }, + "node_modules/style-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-4.0.0.tgz", + "integrity": "sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA==", + "dev": true, + "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" + "webpack": "^5.27.0" } }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.47.0.tgz", - "integrity": "sha512-SIV3/6eftCy1bNzCQoPmbWsRLujS8t5iDIZ4spZOBHqrM+yfX2ogg8Tt3PDTAVKw3sSCiUgg30uOAvK2r9zGjQ==", - "dev": true, + "node_modules/style-to-js": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", + "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.47.0", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "style-to-object": "1.0.14" } }, - "node_modules/uc.micro": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "dev": true, - "license": "MIT" - }, - "node_modules/uglify-js": { - "version": "3.19.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", - "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", - "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" + "node_modules/style-to-object": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", + "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.7" } }, - "node_modules/uint8array-extras": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz", - "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==", + "node_modules/stylis": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", + "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", "dev": true, "license": "MIT", "engines": { "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/un-flatten-tree": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/un-flatten-tree/-/un-flatten-tree-2.0.12.tgz", - "integrity": "sha512-E7v59ADEqVQs9gTZYxoe3uGs6Jj/a3gJ7lSJaTIBTc5w0+B3PJ/kVjs/Y/A26NBWEW8WAo556PpRatH4XHZR1w==", - "license": "MIT" - }, - "node_modules/unbox-primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", - "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "node_modules/supports-hyperlinks": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", + "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "has-bigints": "^1.0.2", - "has-symbols": "^1.1.0", - "which-boxed-primitive": "^1.1.1" + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=14.18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" } }, - "node_modules/unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { - "buffer": "^5.2.1", - "through": "^2.3.8" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/underscore": { - "version": "1.13.7", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", - "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", - "dev": true, - "license": "MIT" - }, - "node_modules/undici": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.16.0.tgz", - "integrity": "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==", + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, "license": "MIT", "engines": { - "node": ">=20.18.1" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "node_modules/swc-loader": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/swc-loader/-/swc-loader-0.2.6.tgz", + "integrity": "sha512-9Zi9UP2YmDpgmQVbyOPJClY0dwf58JDyDMQ7uRc4krmc72twNI2fvlBWHLqVekBpPc7h5NJkGVT1zNDxFrqhvg==", "dev": true, - "license": "MIT" - }, - "node_modules/unicorn-magic": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", - "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "license": "MIT", + "dependencies": { + "@swc/counter": "^0.1.3" + }, + "peerDependencies": { + "@swc/core": "^1.2.147", + "webpack": ">=2" + } + }, + "node_modules/synckit": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", + "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", "dev": true, "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.2.9" + }, "engines": { - "node": ">=18" + "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/synckit" } }, - "node_modules/unified": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", - "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", - "license": "MIT", + "node_modules/table": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", + "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@types/unist": "^3.0.0", - "bail": "^2.0.0", - "devlop": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^6.0.0" + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=10.0.0" } }, - "node_modules/unified/node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "node_modules/table/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": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/unist-util-is": { + "node_modules/table/node_modules/strip-ansi": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", - "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0" + "ansi-regex": "^5.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=8" } }, - "node_modules/unist-util-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", - "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "node_modules/tabster": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/tabster/-/tabster-8.5.6.tgz", + "integrity": "sha512-2vfrRGrx8O9BjdrtSlVA5fvpmbq5HQBRN13XFRg6LAvZ1Fr3QdBnswgT4YgFS5Bhoo5nxwgjRaRueI2Us/dv7g==", "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0" + "keyborg": "2.6.0", + "tslib": "^2.8.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "optionalDependencies": { + "@rollup/rollup-linux-x64-gnu": "4.40.0" } }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "node_modules/tapable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" + "engines": { + "node": ">=6" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/webpack" } }, - "node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" } }, - "node_modules/unist-util-visit-parents": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", - "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "node_modules/tar-fs/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">= 6" } }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "node_modules/tar-fs/node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "dev": true, "license": "MIT", + "optional": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, "engines": { - "node": ">= 10.0.0" + "node": ">=6" } }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/tas-client": { + "version": "0.2.33", + "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.2.33.tgz", + "integrity": "sha512-V+uqV66BOQnWxvI6HjDnE4VkInmYZUQ4dgB7gzaDyFyFSK1i1nF/j7DpS9UbQAgV9NaF1XpcyuavnM1qOeiEIg==", + "license": "MIT" + }, + "node_modules/terminal-link": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-4.0.0.tgz", + "integrity": "sha512-lk+vH+MccxNqgVqSnkMVKx4VLJfnLjDBGzH16JVZjKE2DoxP57s6/vt6JmXV5I3jBcfGrxNrYtC+mPtU7WJztA==", "dev": true, "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "supports-hyperlinks": "^3.2.0" + }, "engines": { - "node": ">= 0.8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/unrs-resolver": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", - "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "node_modules/terminal-link/node_modules/ansi-escapes": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.2.0.tgz", + "integrity": "sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==", "dev": true, - "hasInstallScript": true, "license": "MIT", "dependencies": { - "napi-postinstall": "^0.3.0" + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" }, "funding": { - "url": "https://opencollective.com/unrs-resolver" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser": { + "version": "5.44.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz", + "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" }, - "optionalDependencies": { - "@unrs/resolver-binding-android-arm-eabi": "1.11.1", - "@unrs/resolver-binding-android-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-x64": "1.11.1", - "@unrs/resolver-binding-freebsd-x64": "1.11.1", - "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", - "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", - "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-musl": "1.11.1", - "@unrs/resolver-binding-wasm32-wasi": "1.11.1", - "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", - "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", - "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" } }, - "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "node_modules/terser-webpack-plugin": { + "version": "5.3.16", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", + "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "serialize-javascript": "^6.0.2", + "terser": "^5.31.1" }, - "bin": { - "update-browserslist-db": "cli.js" + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "browserslist": ">= 4.21.0" + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "node_modules/terser-webpack-plugin/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "punycode": "^2.1.0" + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" } }, - "node_modules/url-join": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", - "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "node_modules/terser-webpack-plugin/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, - "license": "MIT" - }, - "node_modules/use-sync-external-store": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", - "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", "license": "MIT", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "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==", + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, "license": "MIT" }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "node_modules/terser/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "engines": { - "node": ">= 0.4.0" + "node": ">=0.10.0" } }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "node_modules/terser/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, - "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", - "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "node_modules/test-exclude": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", + "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", "dev": true, "license": "ISC", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" + "@istanbuljs/schema": "^0.1.2", + "glob": "^10.4.1", + "minimatch": "^9.0.4" }, "engines": { - "node": ">=10.12.0" + "node": ">=18" } }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "node_modules/text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/vanilla-calendar-pro": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/vanilla-calendar-pro/-/vanilla-calendar-pro-3.0.5.tgz", - "integrity": "sha512-4X9bmTo1/KzbZrB7B6mZXtvVXIhcKxaVSnFZuaVtps7tshKJDxgaIElkgdia6IjB5qWetWuu7kZ+ZaV1sPxy6w==", - "license": "MIT", - "funding": { - "type": "individual", - "url": "https://buymeacoffee.com/uvarov" + "b4a": "^1.6.4" } }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } + "license": "MIT" }, - "node_modules/version-range": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/version-range/-/version-range-4.15.0.tgz", - "integrity": "sha512-Ck0EJbAGxHwprkzFO966t4/5QkRuzh+/I1RxhLgUKKwEn+Cd8NwM60mE3AqBZg5gYODoXW0EFsQvbZjRlvdqbg==", + "node_modules/textextensions": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-6.11.0.tgz", + "integrity": "sha512-tXJwSr9355kFJI3lbCkPpUH5cP8/M0GGy2xLO34aZCjMXBaK3SoPnZwr/oWmo1FdCnELcs4npdCIOFtq9W3ruQ==", "dev": true, "license": "Artistic-2.0", + "dependencies": { + "editions": "^6.21.0" + }, "engines": { "node": ">=4" }, @@ -22147,724 +19992,772 @@ "url": "https://bevry.me/fund" } }, - "node_modules/vfile": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", - "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "node_modules/thingies": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.5.0.tgz", + "integrity": "sha512-s+2Bwztg6PhWUD7XMfeYm5qliDdSiZm7M7n8KjTkIsm3l/2lgVRc2/Gx/v+ZX8lT4FMA+i8aQvhcWylldc+ZNw==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" + "engines": { + "node": ">=10.18" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-message": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", - "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" + "type": "github", + "url": "https://github.com/sponsors/streamich" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "peerDependencies": { + "tslib": "^2" } }, - "node_modules/vscode-json-languageservice": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-5.6.3.tgz", - "integrity": "sha512-UDF7sJF5t7mzUzXL6dsClkvnHS4xnDL/gOMKGQiizRHmswlk/xSPGZxEvAtszWQF0ImNcJ0j9l+rHuefGzit1w==", - "license": "MIT", - "dependencies": { - "@vscode/l10n": "^0.0.18", - "jsonc-parser": "^3.3.1", - "vscode-languageserver-textdocument": "^1.0.12", - "vscode-languageserver-types": "^3.17.5", - "vscode-uri": "^3.1.0" - } + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true, + "license": "MIT" }, - "node_modules/vscode-jsonrpc": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", - "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true, + "license": "MIT" }, - "node_modules/vscode-languageclient": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz", - "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==", + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, "license": "MIT", "dependencies": { - "minimatch": "^5.1.0", - "semver": "^7.3.7", - "vscode-languageserver-protocol": "3.17.5" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { - "vscode": "^1.82.0" - } - }, - "node_modules/vscode-languageclient/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" + "node": ">=12.0.0" }, - "engines": { - "node": ">=10" + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/vscode-languageserver": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", - "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, "license": "MIT", - "dependencies": { - "vscode-languageserver-protocol": "3.17.5" + "engines": { + "node": ">=12.0.0" }, - "bin": { - "installServerIntoExtension": "bin/installServerIntoExtension" + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "node_modules/vscode-languageserver-protocol": { - "version": "3.17.5", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", - "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, "license": "MIT", - "dependencies": { - "vscode-jsonrpc": "8.2.0", - "vscode-languageserver-types": "3.17.5" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", - "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", - "license": "MIT" - }, - "node_modules/vscode-languageserver-types": { - "version": "3.17.5", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", - "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", - "license": "MIT" - }, - "node_modules/vscode-tas-client": { - "version": "0.1.84", - "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.84.tgz", - "integrity": "sha512-rUTrUopV+70hvx1hW5ebdw1nd6djxubkLvVxjGdyD/r5v/wcVF41LIfiAtbm5qLZDtQdsMH1IaCuDoluoIa88w==", + "node_modules/tmp": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "dev": true, "license": "MIT", - "dependencies": { - "tas-client": "0.2.33" - }, "engines": { - "vscode": "^1.85.0" + "node": ">=14.14" } }, - "node_modules/vscode-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", - "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", - "license": "MIT" - }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "makeerror": "1.0.12" - } + "license": "BSD-3-Clause" }, - "node_modules/watchpack": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", - "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "license": "MIT", "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" + "is-number": "^7.0.0" }, "engines": { - "node": ">=10.13.0" + "node": ">=8.0" } }, - "node_modules/wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true, "license": "MIT", - "dependencies": { - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/web-tree-sitter": { - "version": "0.20.8", - "resolved": "https://registry.npmjs.org/web-tree-sitter/-/web-tree-sitter-0.20.8.tgz", - "integrity": "sha512-weOVgZ3aAARgdnb220GqYuh7+rZU0Ka9k9yfKtGAzEYMa6GgiCzW9JjQRJyCJakvibQW+dfjJdihjInKuuCAUQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "license": "BSD-2-Clause", "engines": { - "node": ">=12" + "node": ">=0.6" } }, - "node_modules/webpack": { - "version": "5.105.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.0.tgz", - "integrity": "sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw==", + "node_modules/token-types": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.1.tgz", + "integrity": "sha512-kh9LVIWH5CnL63Ipf0jhlBIy0UsrMj/NJDfpsy1SqOXlLKEVyXXYrnFxFT1yOOYVGBSApeVnjPw/sBz5BfEjAQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.8", - "@types/json-schema": "^7.0.15", - "@webassemblyjs/ast": "^1.14.1", - "@webassemblyjs/wasm-edit": "^1.14.1", - "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.15.0", - "acorn-import-phases": "^1.0.3", - "browserslist": "^4.28.1", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.19.0", - "es-module-lexer": "^2.0.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.3.1", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^4.3.3", - "tapable": "^2.3.0", - "terser-webpack-plugin": "^5.3.16", - "watchpack": "^2.5.1", - "webpack-sources": "^3.3.3" - }, - "bin": { - "webpack": "bin/webpack.js" + "@borewit/text-codec": "^0.1.0", + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" }, "engines": { - "node": ">=10.13.0" + "node": ">=14.16" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } + "type": "github", + "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/webpack-bundle-analyzer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-5.0.1.tgz", - "integrity": "sha512-PUp3YFOHysSw8t+13rcF+8o5SGaP/AZ5KnIF3qJfFodv4xJkmixnfcyy+LOwNadpzvyrEKpaMlewAG2sFUfdpw==", + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", "dev": true, "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "license": "MIT", "dependencies": { - "@discoveryjs/json-ext": "0.5.7", - "acorn": "^8.0.4", - "acorn-walk": "^8.0.0", - "commander": "^7.2.0", - "debounce": "^1.2.1", - "escape-string-regexp": "^4.0.0", - "html-escaper": "^2.0.2", - "opener": "^1.5.2", - "picocolors": "^1.0.0", - "sirv": "^2.0.3", - "ws": "^7.3.1" - }, - "bin": { - "webpack-bundle-analyzer": "lib/bin/analyzer.js" + "punycode": "^2.3.1" }, "engines": { - "node": ">= 20.9.0" + "node": ">=18" } }, - "node_modules/webpack-bundle-analyzer/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "node_modules/tree-dump": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.1.0.tgz", + "integrity": "sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==", "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", "license": "MIT", - "engines": { - "node": ">= 10" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/webpack-bundle-analyzer/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">=18.12" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "typescript": ">=4.8.4" } }, - "node_modules/webpack-cli": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-6.0.1.tgz", - "integrity": "sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw==", + "node_modules/ts-jest": { + "version": "29.4.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.5.tgz", + "integrity": "sha512-HO3GyiWn2qvTQA4kTgjDcXiMwYQt68a1Y8+JuLRVpdIzm+UOLSHgl/XqR4c6nzJkq5rOkjc02O2I7P7l/Yof0Q==", "dev": true, "license": "MIT", "dependencies": { - "@discoveryjs/json-ext": "^0.6.1", - "@webpack-cli/configtest": "^3.0.1", - "@webpack-cli/info": "^3.0.1", - "@webpack-cli/serve": "^3.0.1", - "colorette": "^2.0.14", - "commander": "^12.1.0", - "cross-spawn": "^7.0.3", - "envinfo": "^7.14.0", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^3.1.1", - "rechoir": "^0.8.0", - "webpack-merge": "^6.0.1" + "bs-logger": "^0.2.6", + "fast-json-stable-stringify": "^2.1.0", + "handlebars": "^4.7.8", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.7.3", + "type-fest": "^4.41.0", + "yargs-parser": "^21.1.1" }, "bin": { - "webpack-cli": "bin/cli.js" + "ts-jest": "cli.js" }, "engines": { - "node": ">=18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" }, "peerDependencies": { - "webpack": "^5.82.0" + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0 || ^30.0.0", + "@jest/types": "^29.0.0 || ^30.0.0", + "babel-jest": "^29.0.0 || ^30.0.0", + "jest": "^29.0.0 || ^30.0.0", + "jest-util": "^29.0.0 || ^30.0.0", + "typescript": ">=4.3 <6" }, "peerDependenciesMeta": { - "webpack-bundle-analyzer": { + "@babel/core": { "optional": true }, - "webpack-dev-server": { + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jest-util": { "optional": true } } }, - "node_modules/webpack-cli/node_modules/@discoveryjs/json-ext": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.3.tgz", - "integrity": "sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.17.0" - } - }, - "node_modules/webpack-cli/node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "node_modules/ts-jest/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", "dev": true, - "license": "MIT", + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=18" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/webpack-dev-middleware": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.5.tgz", - "integrity": "sha512-uxQ6YqGdE4hgDKNf7hUiPXOdtkXvBJXrfEGYSx7P7LC8hnUYGK70X6xQXUvXeNyBDDcsiQXpG2m3G9vxowaEuA==", + "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": { - "colorette": "^2.0.10", - "memfs": "^4.43.1", - "mime-types": "^3.0.1", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 18.12.0" + "@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" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "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": { - "webpack": "^5.0.0" + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" }, "peerDependenciesMeta": { - "webpack": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { "optional": true } } }, - "node_modules/webpack-dev-middleware/node_modules/mime-types": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", - "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "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/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "license": "MIT", "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" } }, - "node_modules/webpack-dev-server": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.2.tgz", - "integrity": "sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg==", + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, "license": "MIT", "dependencies": { - "@types/bonjour": "^3.5.13", - "@types/connect-history-api-fallback": "^1.5.4", - "@types/express": "^4.17.21", - "@types/express-serve-static-core": "^4.17.21", - "@types/serve-index": "^1.9.4", - "@types/serve-static": "^1.15.5", - "@types/sockjs": "^0.3.36", - "@types/ws": "^8.5.10", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.2.1", - "chokidar": "^3.6.0", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "express": "^4.21.2", - "graceful-fs": "^4.2.6", - "http-proxy-middleware": "^2.0.9", - "ipaddr.js": "^2.1.0", - "launch-editor": "^2.6.1", - "open": "^10.0.3", - "p-retry": "^6.2.0", - "schema-utils": "^4.2.0", - "selfsigned": "^2.4.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^7.4.2", - "ws": "^8.18.0" + "minimist": "^1.2.0" }, "bin": { - "webpack-dev-server": "bin/webpack-dev-server.js" - }, + "json5": "lib/cli.js" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "safe-buffer": "^5.0.1" }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - }, - "webpack-cli": { - "optional": true - } + "engines": { + "node": "*" } }, - "node_modules/webpack-dev-server/node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "license": "MIT", "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "prelude-ls": "^1.2.1" }, "engines": { - "node": ">= 8.10.0" + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" }, "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/webpack-dev-server/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, "license": "MIT", "dependencies": { - "picomatch": "^2.2.1" + "media-typer": "0.3.0", + "mime-types": "~2.1.24" }, "engines": { - "node": ">=8.10.0" + "node": ">= 0.6" } }, - "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "engines": { + "node": ">= 0.4" } }, - "node_modules/webpack-merge": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", - "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, "license": "MIT", "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.1" + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" }, "engines": { - "node": ">=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/webpack-sources": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, "engines": { - "node": ">=10.13.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/webpack/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" }, "engines": { - "node": ">=8.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/webpack/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "node_modules/typed-rest-client": { + "version": "1.8.11", + "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.11.tgz", + "integrity": "sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", + "dependencies": { + "qs": "^6.9.1", + "tunnel": "0.0.6", + "underscore": "^1.12.1" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, "engines": { - "node": ">=4.0" + "node": ">=14.17" } }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "node_modules/typescript-eslint": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.47.0.tgz", + "integrity": "sha512-Lwe8i2XQ3WoMjua/r1PHrCTpkubPYJCAfOurtn+mtTzqB6jNd+14n9UN1bJ4s3F49x9ixAm0FLflB/JzQ57M8Q==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" + "@typescript-eslint/eslint-plugin": "8.47.0", + "@typescript-eslint/parser": "8.47.0", + "@typescript-eslint/typescript-estree": "8.47.0", + "@typescript-eslint/utils": "8.47.0" }, "engines": { - "node": ">=0.8.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/project-service": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.47.0.tgz", + "integrity": "sha512-2X4BX8hUeB5JcA1TQJ7GjcgulXQ+5UkNb0DL8gHsHUHdFoiCTJoYLTpib3LtSDPZsRET5ygN4qqIWrHyYIKERA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.47.0", + "@typescript-eslint/types": "^8.47.0", + "debug": "^4.3.4" + }, "engines": { - "node": ">=0.8.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/whatwg-encoding": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", - "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/scope-manager": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.47.0.tgz", + "integrity": "sha512-a0TTJk4HXMkfpFkL9/WaGTNuv7JWfFTQFJd6zS9dVAjKsojmv9HT55xzbEpnZoY+VUb+YXLMp+ihMLz/UlZfDg==", "dev": true, "license": "MIT", "dependencies": { - "iconv-lite": "0.6.3" + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/visitor-keys": "8.47.0" }, "engines": { - "node": ">=18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/whatwg-mimetype": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", - "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.47.0.tgz", + "integrity": "sha512-ybUAvjy4ZCL11uryalkKxuT3w3sXJAuWhOoGS3T/Wu+iUu1tGJmk5ytSY8gbdACNARmcYEB0COksD2j6hfGK2g==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/whatwg-url": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", - "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/types": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.47.0.tgz", + "integrity": "sha512-nHAE6bMKsizhA2uuYZbEbmp5z2UpffNrPEqiKIeN7VsV6UY/roxanWfoRrf6x/k9+Obf+GQdkm0nPU+vnMXo9A==", + "dev": true, "license": "MIT", - "dependencies": { - "tr46": "^5.1.0", - "webidl-conversions": "^7.0.0" - }, "engines": { - "node": ">=18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.47.0.tgz", + "integrity": "sha512-k6ti9UepJf5NpzCjH31hQNLHQWupTRPhZ+KFF8WtTuTpy7uHPfeg2NM7cP27aCGajoEplxJDFVCEm9TGPYyiVg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" + "@typescript-eslint/project-service": "8.47.0", + "@typescript-eslint/tsconfig-utils": "8.47.0", + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/visitor-keys": "8.47.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" }, "engines": { - "node": ">= 8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/which-boxed-primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", - "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.47.0.tgz", + "integrity": "sha512-g7XrNf25iL4TJOiPqatNuaChyqt49a/onq5YsJ9+hXeugK+41LVg7AxikMfM02PC6jbNtZLCJj6AUcQXJS/jGQ==", "dev": true, "license": "MIT", "dependencies": { - "is-bigint": "^1.1.0", - "is-boolean-object": "^1.2.1", - "is-number-object": "^1.1.1", - "is-string": "^1.1.1", - "is-symbol": "^1.1.1" + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.47.0", + "@typescript-eslint/types": "8.47.0", + "@typescript-eslint/typescript-estree": "8.47.0" }, "engines": { - "node": ">= 0.4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/which-builtin-type": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", - "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "node_modules/typescript-eslint/node_modules/@typescript-eslint/visitor-keys": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.47.0.tgz", + "integrity": "sha512-SIV3/6eftCy1bNzCQoPmbWsRLujS8t5iDIZ4spZOBHqrM+yfX2ogg8Tt3PDTAVKw3sSCiUgg30uOAvK2r9zGjQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "function.prototype.name": "^1.1.6", - "has-tostringtag": "^1.0.2", - "is-async-function": "^2.0.0", - "is-date-object": "^1.1.0", - "is-finalizationregistry": "^1.1.0", - "is-generator-function": "^1.0.10", - "is-regex": "^1.2.1", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.1.0", - "which-collection": "^1.0.2", - "which-typed-array": "^1.1.16" + "@typescript-eslint/types": "8.47.0", + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": ">= 0.4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/which-builtin-type/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", "dev": true, "license": "MIT" }, - "node_modules/which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "dev": true, - "license": "MIT", - "dependencies": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" }, "engines": { - "node": ">= 0.4" + "node": ">=0.8.0" + } + }, + "node_modules/uint8array-extras": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz", + "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/which-typed-array": { - "version": "1.1.19", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", - "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "node_modules/un-flatten-tree": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/un-flatten-tree/-/un-flatten-tree-2.0.12.tgz", + "integrity": "sha512-E7v59ADEqVQs9gTZYxoe3uGs6Jj/a3gJ7lSJaTIBTc5w0+B3PJ/kVjs/Y/A26NBWEW8WAo556PpRatH4XHZR1w==", + "license": "MIT" + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "for-each": "^0.3.5", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2" + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" }, "engines": { "node": ">= 0.4" @@ -22873,1593 +20766,1468 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/wildcard": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", - "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "buffer": "^5.2.1", + "through": "^2.3.8" } }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "node_modules/underscore": { + "version": "1.13.7", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", + "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", "dev": true, "license": "MIT" }, - "node_modules/workerpool": { - "version": "9.3.4", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz", - "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==", + "node_modules/undici": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.16.0.tgz", + "integrity": "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==", "dev": true, - "license": "Apache-2.0" + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } }, - "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/wrap-ansi-cjs": { - "name": "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, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/wrap-ansi-cjs/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, + "node_modules/unified/node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "node_modules/unist-util-is": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "@types/unist": "^3.0.0" }, - "engines": { - "node": ">=8" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "@types/unist": "^3.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", "license": "MIT", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" + "@types/unist": "^3.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "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/write-file-atomic": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", - "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", - "dev": true, - "license": "ISC", + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "license": "MIT", "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/write-file-atomic/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "node": ">= 10.0.0" } }, - "node_modules/wsl-utils": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", - "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, "license": "MIT", - "dependencies": { - "is-wsl": "^3.1.0" - }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8" } }, - "node_modules/xml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", - "dev": true, - "license": "MIT" - }, - "node_modules/xml2js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", - "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", "dev": true, + "hasInstallScript": true, "license": "MIT", "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" + "napi-postinstall": "^0.3.0" }, - "engines": { - "node": ">=4.0.0" + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" } }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", - "engines": { - "node": ">=4.0" + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" } }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", "dev": true, - "license": "ISC" + "license": "MIT" }, - "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, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", "license": "MIT", - "dependencies": { - "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" + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "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==", + "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, - "license": "ISC", - "engines": { - "node": ">=12" - } + "license": "MIT" }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "dev": true, "license": "MIT", - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, "engines": { - "node": ">=10" + "node": ">= 0.4.0" } }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/yargs-unparser/node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "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", + "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", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, "engines": { - "node": ">=8" + "node": ">=10.12.0" } }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, - "node_modules/yazl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", - "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", - "dev": true, + "node_modules/vanilla-calendar-pro": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/vanilla-calendar-pro/-/vanilla-calendar-pro-3.0.5.tgz", + "integrity": "sha512-4X9bmTo1/KzbZrB7B6mZXtvVXIhcKxaVSnFZuaVtps7tshKJDxgaIElkgdia6IjB5qWetWuu7kZ+ZaV1sPxy6w==", "license": "MIT", - "dependencies": { - "buffer-crc32": "~0.2.3" + "funding": { + "type": "individual", + "url": "https://buymeacoffee.com/uvarov" } }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 0.8" } }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "node_modules/version-range": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/version-range/-/version-range-4.15.0.tgz", + "integrity": "sha512-Ck0EJbAGxHwprkzFO966t4/5QkRuzh+/I1RxhLgUKKwEn+Cd8NwM60mE3AqBZg5gYODoXW0EFsQvbZjRlvdqbg==", "dev": true, - "license": "MIT", + "license": "Artistic-2.0", "engines": { - "node": ">=10" + "node": ">=4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://bevry.me/fund" } }, - "node_modules/zod": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.13.tgz", - "integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==", + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, "funding": { - "url": "https://github.com/sponsors/colinhacks" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "packages/documentdb-constants": { - "name": "@vscode-documentdb/documentdb-constants", - "version": "1.0.0", + "node_modules/vscode-json-languageservice": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-5.6.3.tgz", + "integrity": "sha512-UDF7sJF5t7mzUzXL6dsClkvnHS4xnDL/gOMKGQiizRHmswlk/xSPGZxEvAtszWQF0ImNcJ0j9l+rHuefGzit1w==", "license": "MIT", - "devDependencies": { - "@types/jest": "^29.5.14", - "jest": "^29.7.0", - "prettier": "~3.6.2", - "ts-jest": "^29.3.4", - "ts-node": "^10.9.2" + "dependencies": { + "@vscode/l10n": "^0.0.18", + "jsonc-parser": "^3.3.1", + "vscode-languageserver-textdocument": "^1.0.12", + "vscode-languageserver-types": "^3.17.5", + "vscode-uri": "^3.1.0" } }, - "packages/documentdb-constants/node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true, - "license": "MIT" + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } }, - "packages/documentdb-constants/node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", - "dev": true, + "node_modules/vscode-languageclient": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz", + "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==", "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" + "minimatch": "^5.1.0", + "semver": "^7.3.7", + "vscode-languageserver-protocol": "3.17.5" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "vscode": "^1.82.0" } }, - "packages/documentdb-constants/node_modules/@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", - "dev": true, - "license": "MIT", + "node_modules/vscode-languageclient/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": ">=10" } }, - "packages/documentdb-constants/node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "dev": true, + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", "license": "MIT", "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" + "vscode-languageserver-protocol": "3.17.5" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" } }, - "packages/documentdb-constants/node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", - "dev": true, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", "license": "MIT", "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" } }, - "packages/documentdb-constants/node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", - "dev": true, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", + "license": "MIT" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "license": "MIT" + }, + "node_modules/vscode-tas-client": { + "version": "0.1.84", + "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.84.tgz", + "integrity": "sha512-rUTrUopV+70hvx1hW5ebdw1nd6djxubkLvVxjGdyD/r5v/wcVF41LIfiAtbm5qLZDtQdsMH1IaCuDoluoIa88w==", "license": "MIT", "dependencies": { - "jest-get-type": "^29.6.3" + "tas-client": "0.2.33" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "vscode": "^1.85.0" + } + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "license": "MIT" + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" } }, - "packages/documentdb-constants/node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "node_modules/watchpack": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10.13.0" } }, - "packages/documentdb-constants/node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - }, + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/web-tree-sitter": { + "version": "0.20.8", + "resolved": "https://registry.npmjs.org/web-tree-sitter/-/web-tree-sitter-0.20.8.tgz", + "integrity": "sha512-weOVgZ3aAARgdnb220GqYuh7+rZU0Ka9k9yfKtGAzEYMa6GgiCzW9JjQRJyCJakvibQW+dfjJdihjInKuuCAUQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "packages/documentdb-constants/node_modules/@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "node_modules/webpack": { + "version": "5.105.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.0.tgz", + "integrity": "sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw==", "dev": true, "license": "MIT", "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.15.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.28.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.19.0", + "es-module-lexer": "^2.0.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.3.1", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "terser-webpack-plugin": "^5.3.16", + "watchpack": "^2.5.1", + "webpack-sources": "^3.3.3" + }, + "bin": { + "webpack": "bin/webpack.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10.13.0" }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, "peerDependenciesMeta": { - "node-notifier": { + "webpack-cli": { "optional": true } } }, - "packages/documentdb-constants/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/webpack-bundle-analyzer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-5.0.1.tgz", + "integrity": "sha512-PUp3YFOHysSw8t+13rcF+8o5SGaP/AZ5KnIF3qJfFodv4xJkmixnfcyy+LOwNadpzvyrEKpaMlewAG2sFUfdpw==", "dev": true, "license": "MIT", "dependencies": { - "@sinclair/typebox": "^0.27.8" + "@discoveryjs/json-ext": "0.5.7", + "acorn": "^8.0.4", + "acorn-walk": "^8.0.0", + "commander": "^7.2.0", + "debounce": "^1.2.1", + "escape-string-regexp": "^4.0.0", + "html-escaper": "^2.0.2", + "opener": "^1.5.2", + "picocolors": "^1.0.0", + "sirv": "^2.0.3", + "ws": "^7.3.1" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "packages/documentdb-constants/node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" + "bin": { + "webpack-bundle-analyzer": "lib/bin/analyzer.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 20.9.0" } }, - "packages/documentdb-constants/node_modules/@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "node_modules/webpack-bundle-analyzer/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 10" } }, - "packages/documentdb-constants/node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "node_modules/webpack-bundle-analyzer/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/documentdb-constants/node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "node_modules/webpack-cli": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-6.0.1.tgz", + "integrity": "sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" + "@discoveryjs/json-ext": "^0.6.1", + "@webpack-cli/configtest": "^3.0.1", + "@webpack-cli/info": "^3.0.1", + "@webpack-cli/serve": "^3.0.1", + "colorette": "^2.0.14", + "commander": "^12.1.0", + "cross-spawn": "^7.0.3", + "envinfo": "^7.14.0", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^6.0.1" + }, + "bin": { + "webpack-cli": "bin/cli.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.82.0" + }, + "peerDependenciesMeta": { + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } } }, - "packages/documentdb-constants/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/webpack-cli/node_modules/@discoveryjs/json-ext": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.3.tgz", + "integrity": "sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "packages/documentdb-constants/node_modules/@sinclair/typebox": { - "version": "0.27.10", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", - "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==", - "dev": true, - "license": "MIT" - }, - "packages/documentdb-constants/node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.0" + "node": ">=14.17.0" } }, - "packages/documentdb-constants/node_modules/@types/jest": { - "version": "29.5.14", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", - "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", + "node_modules/webpack-cli/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", "dev": true, "license": "MIT", - "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" + "engines": { + "node": ">=18" } }, - "packages/documentdb-constants/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==", + "node_modules/webpack-dev-middleware": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.5.tgz", + "integrity": "sha512-uxQ6YqGdE4hgDKNf7hUiPXOdtkXvBJXrfEGYSx7P7LC8hnUYGK70X6xQXUvXeNyBDDcsiQXpG2m3G9vxowaEuA==", "dev": true, "license": "MIT", + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^4.43.1", + "mime-types": "^3.0.1", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, "engines": { - "node": ">=8" + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } } }, - "packages/documentdb-constants/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "node_modules/webpack-dev-middleware/node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "dev": true, "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "packages/documentdb-constants/node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "node_modules/webpack-dev-server": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.2.tgz", + "integrity": "sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" + "@types/bonjour": "^3.5.13", + "@types/connect-history-api-fallback": "^1.5.4", + "@types/express": "^4.17.21", + "@types/express-serve-static-core": "^4.17.21", + "@types/serve-index": "^1.9.4", + "@types/serve-static": "^1.15.5", + "@types/sockjs": "^0.3.36", + "@types/ws": "^8.5.10", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.2.1", + "chokidar": "^3.6.0", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "express": "^4.21.2", + "graceful-fs": "^4.2.6", + "http-proxy-middleware": "^2.0.9", + "ipaddr.js": "^2.1.0", + "launch-editor": "^2.6.1", + "open": "^10.0.3", + "p-retry": "^6.2.0", + "schema-utils": "^4.2.0", + "selfsigned": "^2.4.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^7.4.2", + "ws": "^8.18.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "@babel/core": "^7.8.0" + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } } }, - "packages/documentdb-constants/node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "node_modules/webpack-dev-server/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" }, "engines": { - "node": ">=8" + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "packages/documentdb-constants/node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "node_modules/webpack-dev-server/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" + "picomatch": "^2.2.1" }, "engines": { - "node": ">=8" + "node": ">=8.10.0" } }, - "packages/documentdb-constants/node_modules/babel-plugin-istanbul/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/webpack-dev-server/node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "packages/documentdb-constants/node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18.0.0" } }, - "packages/documentdb-constants/node_modules/babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "node_modules/webpack-sources": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", + "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", "dev": true, "license": "MIT", - "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=10.13.0" } }, - "packages/documentdb-constants/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" } }, - "packages/documentdb-constants/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4.0" } }, - "packages/documentdb-constants/node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", + "license": "Apache-2.0", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, "engines": { - "node": ">=8" + "node": ">=0.8.0" } }, - "packages/documentdb-constants/node_modules/cjs-module-lexer": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", - "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", "dev": true, - "license": "MIT" + "license": "Apache-2.0", + "engines": { + "node": ">=0.8.0" + } }, - "packages/documentdb-constants/node_modules/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" + "iconv-lite": "0.6.3" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18" } }, - "packages/documentdb-constants/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", "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" - }, + "license": "MIT", "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=18" } }, - "packages/documentdb-constants/node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "license": "BSD-3-Clause", + "node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "license": "MIT", "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "packages/documentdb-constants/node_modules/jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@jest/core": "^29.7.0", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" + "isexe": "^2.0.0" }, "bin": { - "jest": "bin/jest.js" + "node-which": "bin/node-which" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": ">= 8" } }, - "packages/documentdb-constants/node_modules/jest-changed-files": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", - "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", "dev": true, "license": "MIT", "dependencies": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "packages/documentdb-constants/node_modules/jest-circus": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", - "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.7.0", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.7.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "packages/documentdb-constants/node_modules/jest-cli": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", - "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "node_modules/which-builtin-type/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/core": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "create-jest": "^29.7.0", - "exit": "^0.1.2", - "import-local": "^3.0.2", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "packages/documentdb-constants/node_modules/jest-config": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "packages/documentdb-constants/node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } + "license": "MIT" }, - "packages/documentdb-constants/node_modules/jest-docblock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", - "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "license": "MIT", - "dependencies": { - "detect-newline": "^3.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "packages/documentdb-constants/node_modules/jest-each": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", - "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "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/workerpool": { + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz", + "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "packages/documentdb-constants/node_modules/jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "node_modules/wrap-ansi-cjs": { + "name": "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": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "packages/documentdb-constants/node_modules/jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "node_modules/wrap-ansi-cjs/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", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" + "node": ">=8" } }, - "packages/documentdb-constants/node_modules/jest-leak-detector": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", - "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "node_modules/wrap-ansi-cjs/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": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "packages/documentdb-constants/node_modules/jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "packages/documentdb-constants/node_modules/jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/documentdb-constants/node_modules/jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "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": "MIT", + "license": "ISC", + "optional": true + }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "license": "ISC", "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "packages/documentdb-constants/node_modules/jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "node_modules/write-file-atomic/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "license": "MIT", + "license": "ISC", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "packages/documentdb-constants/node_modules/jest-resolve": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", - "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "dev": true, "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "packages/documentdb-constants/node_modules/jest-resolve-dependencies": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", - "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", - "dev": true, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", "license": "MIT", "dependencies": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" + "is-wsl": "^3.1.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/documentdb-constants/node_modules/jest-runner": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "node_modules/xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", + "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", + "dev": true, + "license": "MIT" + }, + "node_modules/xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "^29.7.0", - "@jest/environment": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-leak-detector": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-resolve": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-util": "^29.7.0", - "jest-watcher": "^29.7.0", - "jest-worker": "^29.7.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=4.0.0" } }, - "packages/documentdb-constants/node_modules/jest-runtime": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=4.0" } }, - "packages/documentdb-constants/node_modules/jest-snapshot": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" - }, + "license": "ISC", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" } }, - "packages/documentdb-constants/node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "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": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "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": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "packages/documentdb-constants/node_modules/jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "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": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" - }, + "license": "ISC", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "packages/documentdb-constants/node_modules/jest-watcher": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" } }, - "packages/documentdb-constants/node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "node_modules/yargs-unparser/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "license": "MIT", - "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/documentdb-constants/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/yargs-unparser/node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "MIT", "engines": { - "node": "*" + "node": ">=8" } }, - "packages/documentdb-constants/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", "dev": true, "license": "MIT", "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" } }, - "packages/documentdb-constants/node_modules/pure-rand": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", - "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "license": "MIT" - }, - "packages/documentdb-constants/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true, - "license": "MIT" - }, - "packages/documentdb-constants/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3" } }, - "packages/documentdb-constants/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==", + "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", - "dependencies": { - "ansi-regex": "^5.0.1" - }, "engines": { - "node": ">=8" + "node": ">=6" } }, - "packages/documentdb-constants/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/documentdb-constants/node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" + "node_modules/zod": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.13.tgz", + "integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" } }, - "packages/documentdb-constants/node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, + "packages/documentdb-constants": { + "name": "@vscode-documentdb/documentdb-constants", + "version": "1.0.0", + "license": "MIT" + }, "packages/schema-analyzer": { "name": "@vscode-documentdb/schema-analyzer", "version": "1.0.0", From 23dd1eb319c459de9ec6876b74b4c6995cf4ece2 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 23 Feb 2026 18:44:32 +0000 Subject: [PATCH 054/128] fix: prettier-fix --- .../documentdb-constants/scripts/scrape-operator-docs.ts | 5 +---- packages/documentdb-constants/src/index.ts | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/documentdb-constants/scripts/scrape-operator-docs.ts b/packages/documentdb-constants/scripts/scrape-operator-docs.ts index c1a6026ee..e374eafe2 100644 --- a/packages/documentdb-constants/scripts/scrape-operator-docs.ts +++ b/packages/documentdb-constants/scripts/scrape-operator-docs.ts @@ -932,16 +932,13 @@ async function main(): Promise { // doc pages and do not abort the run. const networkFailures = failureDetails.filter((f) => f.reason.startsWith('NetworkError:')); if (networkFailures.length > 0) { - console.error( - `ERROR: ${networkFailures.length} operator(s) failed due to network errors (not 404). Aborting.`, - ); + console.error(`ERROR: ${networkFailures.length} operator(s) failed due to network errors (not 404). Aborting.`); for (const f of networkFailures) { console.error(` - ${f.operator} (${f.category}): ${f.reason}`); } process.exit(1); } - // Phase 3: Generate dump console.log(' Phase 3: Generating scraped/operator-reference.md...'); const dump = generateDump(operators); diff --git a/packages/documentdb-constants/src/index.ts b/packages/documentdb-constants/src/index.ts index 29d68eb90..d888fcf6b 100644 --- a/packages/documentdb-constants/src/index.ts +++ b/packages/documentdb-constants/src/index.ts @@ -61,7 +61,7 @@ export { PROJECTION_COMPLETION_META, STAGE_COMPLETION_META, UPDATE_COMPLETION_META, - WINDOW_COMPLETION_META + WINDOW_COMPLETION_META, } from './metaTags'; // -- Consumer API -- From a985c16511654aab3f9abb8500a4689966541da8 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 23 Feb 2026 18:58:11 +0000 Subject: [PATCH 055/128] fix: escape backslashes before pipes in escapeTableCell Resolves CodeQL 'Incomplete string escaping or encoding' alert by escaping backslash characters before escaping pipe characters. --- packages/documentdb-constants/scripts/scrape-operator-docs.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/documentdb-constants/scripts/scrape-operator-docs.ts b/packages/documentdb-constants/scripts/scrape-operator-docs.ts index e374eafe2..a4780a1d8 100644 --- a/packages/documentdb-constants/scripts/scrape-operator-docs.ts +++ b/packages/documentdb-constants/scripts/scrape-operator-docs.ts @@ -315,6 +315,7 @@ function extractSyntax(markdown: string): string | undefined { function escapeTableCell(text: string): string { return text .replace(/\r\n|\r|\n/g, ' ') + .replace(/\\/g, '\\\\') .replace(/\|/g, '\\|') .replace(/\s+/g, ' ') .trim(); From 5c5bc1edb984b40fc937c584f8345bd86e458a4a Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Wed, 25 Feb 2026 10:33:35 +0000 Subject: [PATCH 056/128] POC: Register documentdb-query custom language for Monaco editors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements the architecture POC from docs/plan/03.5-finalize-architecture.md: - Register 'documentdb-query' custom language ID with Monaco - Import JS Monarch tokenizer from basic-languages/javascript for syntax highlighting (relaxed quoting, BSON constructors, regex literals) - Custom CompletionItemProvider using documentdb-constants package (query operators, BSON constructors — no JS globals noise) - URI-based routing for editor context (filter/project/sort/aggregation) - Wire QueryEditor filter, project, sort editors to use new language - Remove old JSON schema pipeline (setJsonSchema, basicFindQuerySchema, 2-second delay hack) — replaced by static documentdb-constants completions - 41 Jest tests covering languageConfig and completion provider logic Does NOT include: - Dynamic field completions (Step 4) - acorn validation/squiggles (Step 4) - Aggregation pipeline support (Step 8) POC Pass Criteria (requires manual verification): 1. Highlights { unquoted: 1, 'single': 2, "double": 3 } without squiggles 2. Highlights ObjectId("...") as function call 3. Ctrl+Space shows only DocumentDB operators (no JS globals) 4. Webpack bundle builds successfully (verified: no ts.worker.js loaded) --- l10n/bundle.l10n.json | 3 +- .../collectionView/CollectionView.tsx | 16 +- .../collectionView/collectionViewContext.ts | 1 - .../components/queryEditor/QueryEditor.tsx | 89 +---- .../documentdbQueryCompletionProvider.test.ts | 345 ++++++++++++++++++ .../documentdbQueryCompletionProvider.ts | 125 +++++++ src/webviews/documentdbQuery/index.ts | 26 ++ .../documentdbQuery/languageConfig.test.ts | 112 ++++++ .../documentdbQuery/languageConfig.ts | 67 ++++ .../documentdbQuery/registerLanguage.ts | 106 ++++++ 10 files changed, 794 insertions(+), 96 deletions(-) create mode 100644 src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts create mode 100644 src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts create mode 100644 src/webviews/documentdbQuery/index.ts create mode 100644 src/webviews/documentdbQuery/languageConfig.test.ts create mode 100644 src/webviews/documentdbQuery/languageConfig.ts create mode 100644 src/webviews/documentdbQuery/registerLanguage.ts diff --git a/l10n/bundle.l10n.json b/l10n/bundle.l10n.json index ef1cd63d9..d3e07a648 100644 --- a/l10n/bundle.l10n.json +++ b/l10n/bundle.l10n.json @@ -415,7 +415,6 @@ "Error running process: ": "Error running process: ", "Error saving the document": "Error saving the document", "Error validating collection name availability: {0}": "Error validating collection name availability: {0}", - "Error while loading the autocompletion data": "Error while loading the autocompletion data", "Error while loading the data": "Error while loading the data", "Error while loading the document": "Error while loading the document", "Error while refreshing the document": "Error while refreshing the document", @@ -521,7 +520,7 @@ "Failed to validate source collection: {0}": "Failed to validate source collection: {0}", "Failed with code \"{0}\".": "Failed with code \"{0}\".", "Fair": "Fair", - "Filter: Enter the DocumentDB query filter in JSON format": "Filter: Enter the DocumentDB query filter in JSON format", + "Filter: Enter the DocumentDB query filter": "Filter: Enter the DocumentDB query filter", "Find Query": "Find Query", "Finished importing": "Finished importing", "Folder name cannot be empty": "Folder name cannot be empty", diff --git a/src/webviews/documentdb/collectionView/CollectionView.tsx b/src/webviews/documentdb/collectionView/CollectionView.tsx index 23908bb93..89de231d1 100644 --- a/src/webviews/documentdb/collectionView/CollectionView.tsx +++ b/src/webviews/documentdb/collectionView/CollectionView.tsx @@ -351,18 +351,10 @@ export const CollectionView = (): JSX.Element => { } function updateAutoCompletionData(): void { - trpcClient.mongoClusters.collectionView.getAutocompletionSchema - .query() - .then(async (schema) => { - void (await currentContextRef.current.queryEditor?.setJsonSchema(schema)); - }) - .catch((error) => { - void trpcClient.common.displayErrorMessage.mutate({ - message: l10n.t('Error while loading the autocompletion data'), - modal: false, - cause: error instanceof Error ? error.message : String(error), - }); - }); + // TODO: Step 4 — Replace with field-completion-data push via tRPC subscription. + // The old JSON schema pipeline (getAutocompletionSchema + setJsonSchema) has been + // removed as part of the documentdb-query language POC. Static completions from + // documentdb-constants are used until dynamic field data is wired up. } function handleDeleteDocumentRequest(): void { diff --git a/src/webviews/documentdb/collectionView/collectionViewContext.ts b/src/webviews/documentdb/collectionView/collectionViewContext.ts index 435396ce6..e3a64fa63 100644 --- a/src/webviews/documentdb/collectionView/collectionViewContext.ts +++ b/src/webviews/documentdb/collectionView/collectionViewContext.ts @@ -97,7 +97,6 @@ export type CollectionViewContextType = { skip: number; limit: number; }; - setJsonSchema(schema: object): Promise; //monacoEditor.languages.json.DiagnosticsOptions, but we don't want to import monacoEditor here }; isAiRowVisible: boolean; // Controls visibility of the AI prompt row in QueryEditor queryInsights: QueryInsightsState; // Query insights state for progressive loading diff --git a/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx b/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx index b03e5e9bb..d35ccc952 100644 --- a/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx +++ b/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx @@ -10,9 +10,8 @@ import { useContext, useEffect, useRef, useState, type JSX } from 'react'; import { InputWithProgress } from '../../../../components/InputWithProgress'; // eslint-disable-next-line import/no-internal-modules import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; -// eslint-disable-next-line import/no-internal-modules -import basicFindQuerySchema from '../../../../../utils/json/data-api/autocomplete/basicMongoFindFilterSchema.json'; import { useConfiguration } from '../../../../api/webview-client/useConfiguration'; +import { LANGUAGE_ID, registerDocumentDBQueryLanguage } from '../../../../documentdbQuery'; import { type CollectionViewWebviewConfigurationType } from '../../collectionViewController'; import { ArrowResetRegular, SendRegular, SettingsFilled, SettingsRegular } from '@fluentui/react-icons'; @@ -46,7 +45,6 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element // AI prompt history (survives hide/show of AI input) const [aiPromptHistory, setAiPromptHistory] = useState([]); - const schemaAbortControllerRef = useRef(null); const aiGenerationAbortControllerRef = useRef(null); const aiInputRef = useRef(null); @@ -63,6 +61,9 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element // Store the filter editor reference filterEditorRef.current = editor; + // Register the documentdb-query language (idempotent — safe to call on every mount) + void registerDocumentDBQueryLanguage(monaco); + const getCurrentQueryFunction = () => ({ filter: filterValue, project: projectValue, @@ -76,78 +77,8 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element ...prev, queryEditor: { getCurrentQuery: getCurrentQueryFunction, - /** - * Dynamically sets the JSON schema for the Monaco editor's validation and autocompletion. - * - * NOTE: This function can encounter network errors if called immediately after the - * editor mounts, as the underlying JSON web worker may not have finished loading. - * To mitigate this, a delay is introduced before attempting to set the schema. - * - * A more robust long-term solution should be implemented to programmatically - * verify that the JSON worker is initialized before this function proceeds. - * - * An AbortController is used to prevent race conditions when this function is - * called in quick succession (e.g., rapid "refresh" clicks). It ensures that - * any pending schema update is cancelled before a new one begins, guaranteeing - * a clean, predictable state and allowing the Monaco worker to initialize correctly. - */ - setJsonSchema: async (schema) => { - // Use the ref to cancel the previous operation - if (schemaAbortControllerRef.current) { - schemaAbortControllerRef.current.abort(); - } - - // Create and store the new AbortController in the ref - const abortController = new AbortController(); - schemaAbortControllerRef.current = abortController; - const signal = abortController.signal; - - try { - // Wait for 2 seconds to give the worker time to initialize - await new Promise((resolve) => setTimeout(resolve, 2000)); - - // If the operation was cancelled during the delay, abort early - if (signal.aborted) { - return; - } - - // Check if JSON language features are available and set the schema - if (monaco.languages.json?.jsonDefaults) { - monaco.languages.json.jsonDefaults.setDiagnosticsOptions({ - validate: false, - schemas: [ - { - uri: 'mongodb-filter-query-schema.json', - fileMatch: ['*'], - schema: schema, - }, - ], - }); - } - } catch (error) { - // The error is likely an uncaught exception in the worker, - // but we catch here just in case. - console.warn('Error setting JSON schema:', error); - } - }, }, })); - - // initialize the monaco editor with the schema that's basic - // as we don't know the schema of the collection available - // this is a fallback for the case when the autocompletion feature fails. - monaco.languages.json.jsonDefaults.setDiagnosticsOptions({ - validate: true, - schemas: [ - { - uri: 'mongodb-filter-query-schema.json', // Unique identifier - fileMatch: ['*'], // Apply to all JSON files or specify as needed - - schema: basicFindQuerySchema, - // schema: generateMongoFindJsonSchema(fieldEntries) - }, - ], - }); }; const monacoOptions: editor.IStandaloneEditorConstructionOptions = { @@ -176,10 +107,6 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element // Cleanup any pending operations when component unmounts useEffect(() => { return () => { - if (schemaAbortControllerRef.current) { - schemaAbortControllerRef.current.abort(); - schemaAbortControllerRef.current = null; - } if (aiGenerationAbortControllerRef.current) { aiGenerationAbortControllerRef.current.abort(); aiGenerationAbortControllerRef.current = null; @@ -397,7 +324,7 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element @@ -508,7 +435,7 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element { + describe('getCompletionKindForMeta', () => { + const kinds = mockCompletionItemKind; + + test('maps query operators to Operator kind', () => { + expect(getCompletionKindForMeta('query', kinds)).toBe(kinds.Operator); + expect(getCompletionKindForMeta('query:comparison', kinds)).toBe(kinds.Operator); + expect(getCompletionKindForMeta('query:logical', kinds)).toBe(kinds.Operator); + }); + + test('maps expression operators to Function kind', () => { + expect(getCompletionKindForMeta('expr:arith', kinds)).toBe(kinds.Function); + expect(getCompletionKindForMeta('expr:string', kinds)).toBe(kinds.Function); + }); + + test('maps BSON constructors to Constructor kind', () => { + expect(getCompletionKindForMeta('bson', kinds)).toBe(kinds.Constructor); + }); + + test('maps stages to Module kind', () => { + expect(getCompletionKindForMeta('stage', kinds)).toBe(kinds.Module); + }); + + test('maps accumulators to Method kind', () => { + expect(getCompletionKindForMeta('accumulator', kinds)).toBe(kinds.Method); + }); + + test('maps update operators to Property kind', () => { + expect(getCompletionKindForMeta('update', kinds)).toBe(kinds.Property); + }); + + test('maps variables to Variable kind', () => { + expect(getCompletionKindForMeta('variable', kinds)).toBe(kinds.Variable); + }); + + test('maps window operators to Event kind', () => { + expect(getCompletionKindForMeta('window', kinds)).toBe(kinds.Event); + }); + + test('maps field identifiers to Field kind', () => { + expect(getCompletionKindForMeta('field:identifier', kinds)).toBe(kinds.Field); + }); + + test('maps unknown meta to Text kind', () => { + expect(getCompletionKindForMeta('unknown', kinds)).toBe(kinds.Text); + }); + }); + + describe('mapOperatorToCompletionItem', () => { + const mockMonaco = createMockMonaco(); + + test('maps a simple operator entry without snippet', () => { + const entry: OperatorEntry = { + value: '$eq', + meta: 'query:comparison', + description: 'Matches values equal to a specified value.', + }; + + const item = mapOperatorToCompletionItem(entry, testRange, mockMonaco); + + expect(item.label).toBe('$eq'); + expect(item.kind).toBe(mockCompletionItemKind.Operator); + expect(item.insertText).toBe('$eq'); + expect(item.insertTextRules).toBeUndefined(); + expect(item.detail).toBe('Matches values equal to a specified value.'); + expect(item.documentation).toBeUndefined(); // no link + expect(item.range).toBe(testRange); + }); + + test('maps an operator entry with snippet', () => { + const entry: OperatorEntry = { + value: '$gt', + meta: 'query:comparison', + description: 'Greater than', + snippet: '{ $gt: ${1:value} }', + }; + + const item = mapOperatorToCompletionItem(entry, testRange, mockMonaco); + + expect(item.label).toBe('$gt'); + expect(item.insertText).toBe('{ $gt: ${1:value} }'); + expect(item.insertTextRules).toBe(mockInsertTextRule.InsertAsSnippet); + }); + + test('maps a BSON constructor with link', () => { + const entry: OperatorEntry = { + value: 'ObjectId', + meta: 'bson', + description: 'Creates a new ObjectId value.', + snippet: 'ObjectId("${1:hex}")', + link: 'https://docs.example.com/objectid', + }; + + const item = mapOperatorToCompletionItem(entry, testRange, mockMonaco); + + expect(item.label).toBe('ObjectId'); + expect(item.kind).toBe(mockCompletionItemKind.Constructor); + expect(item.insertText).toBe('ObjectId("${1:hex}")'); + expect(item.insertTextRules).toBe(mockInsertTextRule.InsertAsSnippet); + expect(item.documentation).toEqual({ + value: '[DocumentDB Docs](https://docs.example.com/objectid)', + }); + }); + + test('uses the provided range', () => { + const customRange: monacoEditor.IRange = { + startLineNumber: 3, + endLineNumber: 3, + startColumn: 5, + endColumn: 10, + }; + + const entry: OperatorEntry = { + value: '$in', + meta: 'query:comparison', + description: 'Matches any value in an array.', + }; + + const item = mapOperatorToCompletionItem(entry, customRange, mockMonaco); + expect(item.range).toBe(customRange); + }); + }); + + describe('getMetaTagsForEditorType', () => { + test('returns FILTER_COMPLETION_META for Filter editor type', () => { + const tags = getMetaTagsForEditorType(EditorType.Filter); + expect(tags).toBe(FILTER_COMPLETION_META); + }); + + test('returns PROJECTION_COMPLETION_META for Project editor type', () => { + const tags = getMetaTagsForEditorType(EditorType.Project); + expect(tags).toBe(PROJECTION_COMPLETION_META); + }); + + test('returns PROJECTION_COMPLETION_META for Sort editor type', () => { + const tags = getMetaTagsForEditorType(EditorType.Sort); + expect(tags).toBe(PROJECTION_COMPLETION_META); + }); + + test('returns FILTER_COMPLETION_META for undefined (fallback)', () => { + const tags = getMetaTagsForEditorType(undefined); + expect(tags).toBe(FILTER_COMPLETION_META); + }); + }); + + describe('createCompletionItems', () => { + const mockMonaco = createMockMonaco(); + + test('returns items for filter context using documentdb-constants', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + }); + + // Should return the filter completions from documentdb-constants + expect(items.length).toBeGreaterThan(0); + + // All items should have required CompletionItem properties + for (const item of items) { + expect(item.label).toBeDefined(); + expect(typeof item.label).toBe('string'); + expect(item.kind).toBeDefined(); + expect(item.insertText).toBeDefined(); + expect(item.range).toBe(testRange); + } + }); + + test('filter completions include query operators like $eq, $gt, $match', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + }); + + const labels = items.map((item) => item.label); + expect(labels).toContain('$eq'); + expect(labels).toContain('$gt'); + expect(labels).toContain('$in'); + }); + + test('filter completions include BSON constructors like ObjectId', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + }); + + const labels = items.map((item) => item.label); + expect(labels).toContain('ObjectId'); + expect(labels).toContain('UUID'); + expect(labels).toContain('ISODate'); + }); + + test('filter completions do NOT include JS globals like console, Math, function', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + }); + + const labels = items.map((item) => item.label); + expect(labels).not.toContain('console'); + expect(labels).not.toContain('Math'); + expect(labels).not.toContain('function'); + expect(labels).not.toContain('window'); + expect(labels).not.toContain('document'); + expect(labels).not.toContain('Array'); + expect(labels).not.toContain('Object'); + expect(labels).not.toContain('String'); + }); + + test('filter completions do NOT include aggregation stages', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + }); + + const labels = items.map((item) => item.label); + // $match is a query operator AND a stage, but $group/$unwind are stage-only + expect(labels).not.toContain('$group'); + expect(labels).not.toContain('$unwind'); + expect(labels).not.toContain('$lookup'); + }); + + test('filter completions match getFilteredCompletions count for FILTER_COMPLETION_META', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + }); + + const expected = getFilteredCompletions({ meta: [...FILTER_COMPLETION_META] }); + expect(items).toHaveLength(expected.length); + }); + + test('default (undefined editor type) matches filter completions', () => { + const filterItems = createCompletionItems({ + editorType: EditorType.Filter, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + }); + + const defaultItems = createCompletionItems({ + editorType: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + }); + + expect(defaultItems).toHaveLength(filterItems.length); + }); + }); +}); diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts new file mode 100644 index 000000000..8c68a5fea --- /dev/null +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts @@ -0,0 +1,125 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Completion provider logic for the `documentdb-query` language. + * + * This module is structured for testability: the core mapping function + * (`mapOperatorToCompletionItem`) and the item-building function + * (`createCompletionItems`) are pure functions that receive their Monaco + * dependency through parameters rather than imports. + * + * Context routing uses the model URI to determine which completions to show: + * - `documentdb://filter/*` → query operators + BSON constructors + * - `documentdb://project/*` → field identifiers (future) + * - `documentdb://sort/*` → field identifiers (future) + */ + +import { + FILTER_COMPLETION_META, + getFilteredCompletions, + PROJECTION_COMPLETION_META, + type OperatorEntry, +} from '@vscode-documentdb/documentdb-constants'; +// eslint-disable-next-line import/no-internal-modules +import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; +import { EditorType } from './languageConfig'; + +/** + * Maps a meta tag category to a Monaco CompletionItemKind. + * + * This mapping is extracted as a pure function for testability. + */ +export function getCompletionKindForMeta( + meta: string, + kinds: typeof monacoEditor.languages.CompletionItemKind, +): number { + if (meta.startsWith('query')) return kinds.Operator; + if (meta.startsWith('expr')) return kinds.Function; + if (meta === 'bson') return kinds.Constructor; + if (meta === 'stage') return kinds.Module; + if (meta === 'accumulator') return kinds.Method; + if (meta === 'update') return kinds.Property; + if (meta === 'variable') return kinds.Variable; + if (meta === 'window') return kinds.Event; + if (meta === 'field:identifier') return kinds.Field; + return kinds.Text; +} + +/** + * Maps an OperatorEntry from documentdb-constants to a Monaco CompletionItem. + * + * This is a pure function with no side effects — safe for unit testing + * without a Monaco runtime. + */ +export function mapOperatorToCompletionItem( + entry: OperatorEntry, + range: monacoEditor.IRange, + monaco: typeof monacoEditor, +): monacoEditor.languages.CompletionItem { + const hasSnippet = !!entry.snippet; + + return { + label: entry.value, + kind: getCompletionKindForMeta(entry.meta, monaco.languages.CompletionItemKind), + insertText: hasSnippet ? entry.snippet! : entry.value, + insertTextRules: hasSnippet ? monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet : undefined, + detail: entry.description, + documentation: entry.link + ? { + value: `[DocumentDB Docs](${entry.link})`, + } + : undefined, + range, + }; +} + +/** + * Parameters for creating completion items. + */ +export interface CreateCompletionItemsParams { + /** The editor type parsed from the model URI (undefined if URI doesn't match). */ + editorType: EditorType | undefined; + /** The range to insert completions at. */ + range: monacoEditor.IRange; + /** Whether the cursor is immediately after a '$' character. */ + isDollarPrefix: boolean; + /** The Monaco editor API. */ + monaco: typeof monacoEditor; +} + +/** + * Returns the completion meta tags appropriate for the given editor type. + * + * Exported for testing. + */ +export function getMetaTagsForEditorType(editorType: EditorType | undefined): readonly string[] { + switch (editorType) { + case EditorType.Filter: + return FILTER_COMPLETION_META; + case EditorType.Project: + case EditorType.Sort: + return PROJECTION_COMPLETION_META; + default: + // Default to filter completions for unknown/unmatched URIs + return FILTER_COMPLETION_META; + } +} + +/** + * Creates Monaco completion items based on the editor context. + * + * This function is the main entry point called by the CompletionItemProvider. + * It delegates to `documentdb-constants` for the operator data and maps + * each entry to a Monaco CompletionItem. + */ +export function createCompletionItems(params: CreateCompletionItemsParams): monacoEditor.languages.CompletionItem[] { + const { editorType, range, monaco } = params; + + const metaTags = getMetaTagsForEditorType(editorType); + const entries = getFilteredCompletions({ meta: [...metaTags] }); + + return entries.map((entry) => mapOperatorToCompletionItem(entry, range, monaco)); +} diff --git a/src/webviews/documentdbQuery/index.ts b/src/webviews/documentdbQuery/index.ts new file mode 100644 index 000000000..d36b6b619 --- /dev/null +++ b/src/webviews/documentdbQuery/index.ts @@ -0,0 +1,26 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * DocumentDB Query Language for Monaco Editor. + * + * This module provides the `documentdb-query` custom language that reuses + * the JavaScript Monarch tokenizer for syntax highlighting while providing + * custom completions from the `documentdb-constants` package. + * + * Usage: + * ```typescript + * import { registerDocumentDBQueryLanguage, LANGUAGE_ID } from './documentdbQuery'; + * + * // During Monaco initialization: + * await registerDocumentDBQueryLanguage(monaco); + * + * // In editor props: + * + * ``` + */ + +export { EditorType, LANGUAGE_ID, URI_SCHEME, buildEditorUri, parseEditorUri } from './languageConfig'; +export { registerDocumentDBQueryLanguage } from './registerLanguage'; diff --git a/src/webviews/documentdbQuery/languageConfig.test.ts b/src/webviews/documentdbQuery/languageConfig.test.ts new file mode 100644 index 000000000..97f276b52 --- /dev/null +++ b/src/webviews/documentdbQuery/languageConfig.test.ts @@ -0,0 +1,112 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { buildEditorUri, EditorType, LANGUAGE_ID, parseEditorUri, URI_SCHEME } from './languageConfig'; + +describe('languageConfig', () => { + describe('constants', () => { + test('LANGUAGE_ID is "documentdb-query"', () => { + expect(LANGUAGE_ID).toBe('documentdb-query'); + }); + + test('URI_SCHEME is "documentdb"', () => { + expect(URI_SCHEME).toBe('documentdb'); + }); + }); + + describe('EditorType', () => { + test('has expected enum values', () => { + expect(EditorType.Filter).toBe('filter'); + expect(EditorType.Project).toBe('project'); + expect(EditorType.Sort).toBe('sort'); + expect(EditorType.Aggregation).toBe('aggregation'); + }); + }); + + describe('buildEditorUri', () => { + test('builds filter URI with session ID', () => { + const uri = buildEditorUri(EditorType.Filter, 'session-abc-123'); + expect(uri).toBe('documentdb://filter/session-abc-123'); + }); + + test('builds project URI with session ID', () => { + const uri = buildEditorUri(EditorType.Project, 'my-session'); + expect(uri).toBe('documentdb://project/my-session'); + }); + + test('builds sort URI with session ID', () => { + const uri = buildEditorUri(EditorType.Sort, 'sess-1'); + expect(uri).toBe('documentdb://sort/sess-1'); + }); + + test('builds aggregation URI with session ID', () => { + const uri = buildEditorUri(EditorType.Aggregation, 'agg-session'); + expect(uri).toBe('documentdb://aggregation/agg-session'); + }); + }); + + describe('parseEditorUri', () => { + test('parses valid filter URI', () => { + const result = parseEditorUri('documentdb://filter/session-abc-123'); + expect(result).toEqual({ + editorType: EditorType.Filter, + sessionId: 'session-abc-123', + }); + }); + + test('parses valid project URI', () => { + const result = parseEditorUri('documentdb://project/my-session'); + expect(result).toEqual({ + editorType: EditorType.Project, + sessionId: 'my-session', + }); + }); + + test('parses valid sort URI', () => { + const result = parseEditorUri('documentdb://sort/sess-1'); + expect(result).toEqual({ + editorType: EditorType.Sort, + sessionId: 'sess-1', + }); + }); + + test('parses valid aggregation URI', () => { + const result = parseEditorUri('documentdb://aggregation/agg-123'); + expect(result).toEqual({ + editorType: EditorType.Aggregation, + sessionId: 'agg-123', + }); + }); + + test('returns undefined for unrecognized scheme', () => { + const result = parseEditorUri('vscode://filter/session-1'); + expect(result).toBeUndefined(); + }); + + test('returns undefined for unknown editor type', () => { + const result = parseEditorUri('documentdb://unknown/session-1'); + expect(result).toBeUndefined(); + }); + + test('returns undefined for malformed URI (no session)', () => { + const result = parseEditorUri('documentdb://filter'); + expect(result).toBeUndefined(); + }); + + test('returns undefined for empty string', () => { + const result = parseEditorUri(''); + expect(result).toBeUndefined(); + }); + + test('roundtrips with buildEditorUri', () => { + for (const editorType of Object.values(EditorType)) { + const sessionId = `test-session-${editorType}`; + const uri = buildEditorUri(editorType, sessionId); + const parsed = parseEditorUri(uri); + expect(parsed).toEqual({ editorType, sessionId }); + } + }); + }); +}); diff --git a/src/webviews/documentdbQuery/languageConfig.ts b/src/webviews/documentdbQuery/languageConfig.ts new file mode 100644 index 000000000..5ad101a25 --- /dev/null +++ b/src/webviews/documentdbQuery/languageConfig.ts @@ -0,0 +1,67 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Constants and configuration for the `documentdb-query` custom Monaco language. + * + * This language reuses the JavaScript Monarch tokenizer for syntax highlighting + * but does NOT attach the TypeScript/JavaScript language service worker. + * Completions are driven entirely by custom providers using `documentdb-constants`. + */ + +/** The language identifier registered with Monaco. */ +export const LANGUAGE_ID = 'documentdb-query'; + +/** URI scheme used for query editor models. */ +export const URI_SCHEME = 'documentdb'; + +/** + * Known editor types for URI-based routing. + * The completion provider inspects `model.uri` to determine which + * completions to offer. + */ +export enum EditorType { + Filter = 'filter', + Project = 'project', + Sort = 'sort', + Aggregation = 'aggregation', +} + +/** + * Builds a Monaco model URI for a given editor type and session. + * + * @param editorType - the type of query editor (filter, project, sort) + * @param sessionId - unique session identifier for this editor instance + * @returns a URI string like `documentdb://filter/session-abc-123` + */ +export function buildEditorUri(editorType: EditorType, sessionId: string): string { + return `${URI_SCHEME}://${editorType}/${sessionId}`; +} + +/** + * Parses a Monaco model URI to extract the editor type. + * + * @param uri - the URI string (e.g., `documentdb://filter/session-abc-123`) + * @returns the EditorType or undefined if the URI doesn't match + */ +export function parseEditorUri(uri: string): { editorType: EditorType; sessionId: string } | undefined { + // Handle both URI objects and strings + const uriString = typeof uri === 'string' ? uri : String(uri); + + const match = uriString.match(new RegExp(`^${URI_SCHEME}://([^/]+)/(.+)$`)); + if (!match) { + return undefined; + } + + const editorType = match[1] as EditorType; + const sessionId = match[2]; + + // Validate that it's a known editor type + if (!Object.values(EditorType).includes(editorType)) { + return undefined; + } + + return { editorType, sessionId }; +} diff --git a/src/webviews/documentdbQuery/registerLanguage.ts b/src/webviews/documentdbQuery/registerLanguage.ts new file mode 100644 index 000000000..832ef1473 --- /dev/null +++ b/src/webviews/documentdbQuery/registerLanguage.ts @@ -0,0 +1,106 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Registers the `documentdb-query` custom language with Monaco Editor. + * + * This module: + * 1. Registers the language ID with Monaco + * 2. Imports the JavaScript Monarch tokenizer for syntax highlighting + * 3. Registers a custom CompletionItemProvider scoped to `documentdb-query` + * + * The JS tokenizer provides correct highlighting for: + * - Unquoted identifiers: `{ name: 1 }` + * - Single-quoted strings: `{ 'name': 1 }` + * - Double-quoted strings: `{ "name": 1 }` + * - BSON constructors: `ObjectId("...")` + * - Regex literals: `/^alice/i` + * - Comments, template literals, function bodies (for future $function support) + * + * Because this is a custom language ID, the TypeScript worker is NOT loaded, + * keeping the bundle ~400-600 KB lighter and ensuring a clean completion slate. + */ + +// eslint-disable-next-line import/no-internal-modules +import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; +import { createCompletionItems } from './documentdbQueryCompletionProvider'; +import { LANGUAGE_ID, parseEditorUri } from './languageConfig'; + +/** Tracks whether the language has already been registered (idempotent guard). */ +let isRegistered = false; + +/** + * Registers the `documentdb-query` language with Monaco. + * + * Safe to call multiple times — subsequent calls are no-ops. + * + * @param monaco - the Monaco editor API instance + */ +export async function registerDocumentDBQueryLanguage(monaco: typeof monacoEditor): Promise { + if (isRegistered) { + return; + } + + // Step 1: Register the language ID + monaco.languages.register({ id: LANGUAGE_ID }); + + // Step 2: Import the JS Monarch tokenizer + // This path has been stable since Monaco 0.20 and exports { conf, language } + // eslint-disable-next-line import/no-internal-modules + const jsLanguage = (await import('monaco-editor/esm/vs/basic-languages/javascript/javascript.js')) as { + language: monacoEditor.languages.IMonarchLanguage; + conf: monacoEditor.languages.LanguageConfiguration; + }; + + // Step 3: Apply the JS tokenizer and language configuration to our custom language + monaco.languages.setMonarchTokensProvider(LANGUAGE_ID, jsLanguage.language); + monaco.languages.setLanguageConfiguration(LANGUAGE_ID, jsLanguage.conf); + + // Step 4: Register the completion provider + monaco.languages.registerCompletionItemProvider(LANGUAGE_ID, { + triggerCharacters: ['$', '"', "'", '{', '.'], + provideCompletionItems: ( + model: monacoEditor.editor.ITextModel, + position: monacoEditor.Position, + ): monacoEditor.languages.CompletionList => { + // Parse the model URI to determine editor context + const uriString = model.uri.toString(); + const parsed = parseEditorUri(uriString); + + // Get the word at the current position for range calculation + const wordInfo = model.getWordUntilPosition(position); + const range: monacoEditor.IRange = { + startLineNumber: position.lineNumber, + endLineNumber: position.lineNumber, + startColumn: wordInfo.startColumn, + endColumn: wordInfo.endColumn, + }; + + // Check if cursor is preceded by '$' (for operator completions) + const lineContent = model.getLineContent(position.lineNumber); + const charBefore = lineContent[wordInfo.startColumn - 2]; // -2 because columns are 1-based + + // Build completion items based on context + const items = createCompletionItems({ + editorType: parsed?.editorType, + range, + isDollarPrefix: charBefore === '$', + monaco, + }); + + return { suggestions: items }; + }, + }); + + isRegistered = true; +} + +/** + * Resets the registration state. For testing only. + * @internal + */ +export function _resetRegistration(): void { + isRegistered = false; +} From b7f65a66db9033b74df8ca2dd142fcdede68236c Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Wed, 25 Feb 2026 12:41:50 +0000 Subject: [PATCH 057/128] feat: Enhance documentdb-query completion and validation features - Implemented dynamic field completions using a completion store. - Added mapping function for field completion items to improve sorting and display. - Introduced hover provider for inline documentation on operators and BSON constructors. - Developed a comprehensive validator for documentdb-query expressions, including syntax error detection and typo suggestions for BSON constructors. - Created unit tests for completion store, hover provider, and query validator to ensure functionality and reliability. - Updated existing completion provider to integrate new features and improve overall performance. --- l10n/bundle.l10n.json | 6 +- package-lock.json | 50 ++- package.json | 5 +- src/documentdb/ClusterSession.ts | 11 +- src/documentdb/ClustersClient.ts | 25 +- src/documentdb/utils/toFilterQuery.test.ts | 291 +++++++++--------- src/documentdb/utils/toFilterQuery.ts | 223 +------------- .../basicMongoFindFilterSchema.json | 173 ----------- .../generateMongoFindJsonSchema.ts | 270 ---------------- .../collectionView/CollectionView.tsx | 14 +- .../collectionView/collectionViewRouter.ts | 19 +- .../components/queryEditor/QueryEditor.tsx | 134 +++++++- .../documentdbQuery/completionStore.test.ts | 126 ++++++++ .../documentdbQuery/completionStore.ts | 36 +++ .../documentdbQueryCompletionProvider.test.ts | 168 ++++++++++ .../documentdbQueryCompletionProvider.ts | 43 ++- .../documentdbQueryHoverProvider.test.ts | 73 +++++ .../documentdbQueryHoverProvider.ts | 50 +++ .../documentdbQueryValidator.test.ts | 157 ++++++++++ .../documentdbQueryValidator.ts | 227 ++++++++++++++ src/webviews/documentdbQuery/index.ts | 2 + .../documentdbQuery/registerLanguage.ts | 41 ++- 22 files changed, 1269 insertions(+), 875 deletions(-) delete mode 100644 src/utils/json/data-api/autocomplete/basicMongoFindFilterSchema.json delete mode 100644 src/utils/json/data-api/autocomplete/generateMongoFindJsonSchema.ts create mode 100644 src/webviews/documentdbQuery/completionStore.test.ts create mode 100644 src/webviews/documentdbQuery/completionStore.ts create mode 100644 src/webviews/documentdbQuery/documentdbQueryHoverProvider.test.ts create mode 100644 src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts create mode 100644 src/webviews/documentdbQuery/documentdbQueryValidator.test.ts create mode 100644 src/webviews/documentdbQuery/documentdbQueryValidator.ts diff --git a/l10n/bundle.l10n.json b/l10n/bundle.l10n.json index d3e07a648..bb1c93d7d 100644 --- a/l10n/bundle.l10n.json +++ b/l10n/bundle.l10n.json @@ -615,7 +615,7 @@ "Invalid Connection String: {error}": "Invalid Connection String: {error}", "Invalid connection type selected.": "Invalid connection type selected.", "Invalid document ID: {0}": "Invalid document ID: {0}", - "Invalid filter syntax: {0}. Please use valid JSON, for example: { \"name\": \"value\" }": "Invalid filter syntax: {0}. Please use valid JSON, for example: { \"name\": \"value\" }", + "Invalid filter syntax: {0}. Please use valid JSON or a DocumentDB API expression, for example: { name: \"value\" }": "Invalid filter syntax: {0}. Please use valid JSON or a DocumentDB API expression, for example: { name: \"value\" }", "Invalid folder type.": "Invalid folder type.", "Invalid mongoShell command format": "Invalid mongoShell command format", "Invalid node type.": "Invalid node type.", @@ -623,10 +623,10 @@ "Invalid payload for drop index action": "Invalid payload for drop index action", "Invalid payload for modify index action": "Invalid payload for modify index action", "Invalid projection syntax: {0}": "Invalid projection syntax: {0}", - "Invalid projection syntax: {0}. Please use valid JSON, for example: { \"fieldName\": 1 }": "Invalid projection syntax: {0}. Please use valid JSON, for example: { \"fieldName\": 1 }", + "Invalid projection syntax: {0}. Please use valid JSON or a DocumentDB API expression, for example: { fieldName: 1 }": "Invalid projection syntax: {0}. Please use valid JSON or a DocumentDB API expression, for example: { fieldName: 1 }", "Invalid semver \"{0}\".": "Invalid semver \"{0}\".", "Invalid sort syntax: {0}": "Invalid sort syntax: {0}", - "Invalid sort syntax: {0}. Please use valid JSON, for example: { \"fieldName\": 1 }": "Invalid sort syntax: {0}. Please use valid JSON, for example: { \"fieldName\": 1 }", + "Invalid sort syntax: {0}. Please use valid JSON or a DocumentDB API expression, for example: { fieldName: 1 }": "Invalid sort syntax: {0}. Please use valid JSON or a DocumentDB API expression, for example: { fieldName: 1 }", "It could be better": "It could be better", "It looks like there aren't any other folders to move these items into.\nYou might want to create a new folder first.\n\nNote: You can't move items between 'DocumentDB Local' and regular connections.": "It looks like there aren't any other folders to move these items into.\nYou might want to create a new folder first.\n\nNote: You can't move items between 'DocumentDB Local' and regular connections.", "item": "item", diff --git a/package-lock.json b/package-lock.json index 010535649..82db6002d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,11 +27,14 @@ "@microsoft/vscode-azureresources-api": "~2.5.0", "@monaco-editor/react": "~4.7.0", "@mongodb-js/explain-plan-helper": "1.4.24", + "@mongodb-js/shell-bson-parser": "^1.5.6", "@trpc/client": "~11.10.0", "@trpc/server": "~11.10.0", "@vscode-documentdb/documentdb-constants": "*", "@vscode-documentdb/schema-analyzer": "*", "@vscode/l10n": "~0.0.18", + "acorn": "^8.16.0", + "acorn-walk": "^8.3.5", "antlr4ts": "^0.5.0-alpha.4", "bson": "~7.0.0", "denque": "~2.1.0", @@ -4227,28 +4230,6 @@ "mongodb-explain-compat": "^3.3.23" } }, - "node_modules/@mongodb-js/explain-plan-helper/node_modules/@mongodb-js/shell-bson-parser": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@mongodb-js/shell-bson-parser/-/shell-bson-parser-1.4.0.tgz", - "integrity": "sha512-3HO90liE6pmEuUMi7SWR1HooVk23/jfx5iaBZHo250iYyF5uaqssepBGRF7J/14pmgTSwIGrrDd5rQtBYrY7wA==", - "license": "Apache-2.0", - "dependencies": { - "acorn": "^8.14.1" - }, - "peerDependencies": { - "bson": "^4.6.3 || ^5 || ^6" - } - }, - "node_modules/@mongodb-js/explain-plan-helper/node_modules/bson": { - "version": "6.10.4", - "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.4.tgz", - "integrity": "sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==", - "license": "Apache-2.0", - "peer": true, - "engines": { - "node": ">=16.20.1" - } - }, "node_modules/@mongodb-js/saslprep": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.3.2.tgz", @@ -4258,6 +4239,18 @@ "sparse-bitfield": "^3.0.3" } }, + "node_modules/@mongodb-js/shell-bson-parser": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/@mongodb-js/shell-bson-parser/-/shell-bson-parser-1.5.6.tgz", + "integrity": "sha512-yzVLeOkRSE+r8scrDMJjL9zTSzypU/TLxF+INQLs3yQX9a2R6IfBDDqdSVFyHVWv1FhZN0lVeqEWTsX+Iz5BaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.1" + }, + "peerDependencies": { + "bson": "^4.6.3 || ^5 || ^6.10.3 || ^7.0.0" + } + }, "node_modules/@napi-rs/nice": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@napi-rs/nice/-/nice-1.1.1.tgz", @@ -8085,9 +8078,9 @@ } }, "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -8120,10 +8113,9 @@ } }, "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, + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", "license": "MIT", "dependencies": { "acorn": "^8.11.0" diff --git a/package.json b/package.json index a823a6616..801be5d80 100644 --- a/package.json +++ b/package.json @@ -167,11 +167,14 @@ "@microsoft/vscode-azureresources-api": "~2.5.0", "@monaco-editor/react": "~4.7.0", "@mongodb-js/explain-plan-helper": "1.4.24", + "@mongodb-js/shell-bson-parser": "^1.5.6", "@trpc/client": "~11.10.0", "@trpc/server": "~11.10.0", - "@vscode/l10n": "~0.0.18", "@vscode-documentdb/documentdb-constants": "*", "@vscode-documentdb/schema-analyzer": "*", + "@vscode/l10n": "~0.0.18", + "acorn": "^8.16.0", + "acorn-walk": "^8.3.5", "antlr4ts": "^0.5.0-alpha.4", "bson": "~7.0.0", "denque": "~2.1.0", diff --git a/src/documentdb/ClusterSession.ts b/src/documentdb/ClusterSession.ts index 27ae9b8e4..432d53581 100644 --- a/src/documentdb/ClusterSession.ts +++ b/src/documentdb/ClusterSession.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { ParseMode, parse as parseShellBSON } from '@mongodb-js/shell-bson-parser'; import { SchemaAnalyzer, getPropertyNamesAtLevel, @@ -540,7 +541,7 @@ export class ClusterSession { * @remarks * This method uses the same BSON parsing logic as ClustersClient.runFindQuery(): * - filter is parsed with toFilterQueryObj() which handles UUID(), Date(), MinKey(), MaxKey() constructors - * - projection and sort are parsed with EJSON.parse() + * - projection and sort are parsed with parseShellBSON() in Loose mode * * Use this method when you need the actual MongoDB Document objects for query execution. * Use getCurrentFindQueryParams() when you only need the string representations. @@ -555,7 +556,9 @@ export class ClusterSession { let projectionObj: Document | undefined; if (stringParams.project && stringParams.project.trim() !== '{}') { try { - projectionObj = EJSON.parse(stringParams.project) as Document; + projectionObj = parseShellBSON(stringParams.project, { + mode: ParseMode.Loose, + }) as Document; } catch (error) { throw new Error( l10n.t('Invalid projection syntax: {0}', error instanceof Error ? error.message : String(error)), @@ -567,7 +570,9 @@ export class ClusterSession { let sortObj: Document | undefined; if (stringParams.sort && stringParams.sort.trim() !== '{}') { try { - sortObj = EJSON.parse(stringParams.sort) as Document; + sortObj = parseShellBSON(stringParams.sort, { + mode: ParseMode.Loose, + }) as Document; } catch (error) { throw new Error( l10n.t('Invalid sort syntax: {0}', error instanceof Error ? error.message : String(error)), diff --git a/src/documentdb/ClustersClient.ts b/src/documentdb/ClustersClient.ts index bc28cff61..2adb398f6 100644 --- a/src/documentdb/ClustersClient.ts +++ b/src/documentdb/ClustersClient.ts @@ -10,6 +10,7 @@ */ import { appendExtensionUserAgent, callWithTelemetryAndErrorHandling, parseError } from '@microsoft/vscode-azext-utils'; +import { ParseMode, parse as parseShellBSON } from '@mongodb-js/shell-bson-parser'; import * as l10n from '@vscode/l10n'; import { EJSON } from 'bson'; import { @@ -513,13 +514,15 @@ export class ClustersClient { // Parse and add projection if provided if (queryParams.project && queryParams.project.trim() !== '{}') { try { - options.projection = EJSON.parse(queryParams.project) as Document; + options.projection = parseShellBSON(queryParams.project, { + mode: ParseMode.Loose, + }) as Document; } catch (error) { const cause = error instanceof Error ? error : new Error(String(error)); throw new QueryError( 'INVALID_PROJECTION', l10n.t( - 'Invalid projection syntax: {0}. Please use valid JSON, for example: { "fieldName": 1 }', + 'Invalid projection syntax: {0}. Please use valid JSON or a DocumentDB API expression, for example: { fieldName: 1 }', cause.message, ), cause, @@ -530,13 +533,15 @@ export class ClustersClient { // Parse and add sort if provided if (queryParams.sort && queryParams.sort.trim() !== '{}') { try { - options.sort = EJSON.parse(queryParams.sort) as Document; + options.sort = parseShellBSON(queryParams.sort, { + mode: ParseMode.Loose, + }) as Document; } catch (error) { const cause = error instanceof Error ? error : new Error(String(error)); throw new QueryError( 'INVALID_SORT', l10n.t( - 'Invalid sort syntax: {0}. Please use valid JSON, for example: { "fieldName": 1 }', + 'Invalid sort syntax: {0}. Please use valid JSON or a DocumentDB API expression, for example: { fieldName: 1 }', cause.message, ), cause, @@ -662,13 +667,15 @@ export class ClustersClient { // Parse and add projection if provided if (queryParams.project && queryParams.project.trim() !== '{}') { try { - options.projection = EJSON.parse(queryParams.project) as Document; + options.projection = parseShellBSON(queryParams.project, { + mode: ParseMode.Loose, + }) as Document; } catch (error) { const cause = error instanceof Error ? error : new Error(String(error)); throw new QueryError( 'INVALID_PROJECTION', l10n.t( - 'Invalid projection syntax: {0}. Please use valid JSON, for example: { "fieldName": 1 }', + 'Invalid projection syntax: {0}. Please use valid JSON or a DocumentDB API expression, for example: { fieldName: 1 }', cause.message, ), cause, @@ -679,13 +686,15 @@ export class ClustersClient { // Parse and add sort if provided if (queryParams.sort && queryParams.sort.trim() !== '{}') { try { - options.sort = EJSON.parse(queryParams.sort) as Document; + options.sort = parseShellBSON(queryParams.sort, { + mode: ParseMode.Loose, + }) as Document; } catch (error) { const cause = error instanceof Error ? error : new Error(String(error)); throw new QueryError( 'INVALID_SORT', l10n.t( - 'Invalid sort syntax: {0}. Please use valid JSON, for example: { "fieldName": 1 }', + 'Invalid sort syntax: {0}. Please use valid JSON or a DocumentDB API expression, for example: { fieldName: 1 }', cause.message, ), cause, diff --git a/src/documentdb/utils/toFilterQuery.test.ts b/src/documentdb/utils/toFilterQuery.test.ts index ca8ff0352..a19caa7ef 100644 --- a/src/documentdb/utils/toFilterQuery.test.ts +++ b/src/documentdb/utils/toFilterQuery.test.ts @@ -3,7 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { MaxKey, MinKey, UUID } from 'mongodb'; +import { Binary, Decimal128, Int32, Long, ObjectId, Timestamp } from 'bson'; +import { MaxKey, MinKey } from 'mongodb'; import { QueryError } from '../errors/QueryError'; import { toFilterQueryObj } from './toFilterQuery'; @@ -29,175 +30,164 @@ jest.mock('../../extensionVariables', () => ({ }, })); -// Basic query examples -const basicQueries = [ - { input: '{ }', expected: {} }, - { input: '{ "name": "John" }', expected: { name: 'John' } }, - { input: '{ "name": "John", "age": { "$gt": 30 } }', expected: { name: 'John', age: { $gt: 30 } } }, -]; - -// BSON function examples with different variations -const bsonFunctionTestCases = [ - // UUID cases - { - type: 'UUID', - input: '{ "id": UUID("123e4567-e89b-12d3-a456-426614174000") }', - property: 'id', - expectedClass: UUID, - expectedValue: '123e4567-e89b-12d3-a456-426614174000', - }, - { - type: 'UUID with new', - input: '{ "userId": new UUID("550e8400-e29b-41d4-a716-446655440000") }', - property: 'userId', - expectedClass: UUID, - expectedValue: '550e8400-e29b-41d4-a716-446655440000', - }, - { - type: 'UUID with single quotes', - input: '{ "id": UUID(\'123e4567-e89b-12d3-a456-426614174000\') }', - property: 'id', - expectedClass: UUID, - expectedValue: '123e4567-e89b-12d3-a456-426614174000', - }, - // MinKey cases - { - type: 'MinKey', - input: '{ "start": MinKey() }', - property: 'start', - expectedClass: MinKey, - }, - { - type: 'MinKey with new', - input: '{ "min": new MinKey() }', - property: 'min', - expectedClass: MinKey, - }, - // MaxKey cases - { - type: 'MaxKey', - input: '{ "end": MaxKey() }', - property: 'end', - expectedClass: MaxKey, - }, - { - type: 'MaxKey with new', - input: '{ "max": new MaxKey() }', - property: 'max', - expectedClass: MaxKey, - }, - // Date cases - { - type: 'Date', - input: '{ "created": new Date("2023-01-01") }', - property: 'created', - expectedClass: Date, - expectedValue: '2023-01-01T00:00:00.000Z', - }, - { - type: 'Date without new', - input: '{ "updated": Date("2023-12-31T23:59:59.999Z") }', - property: 'updated', - expectedClass: Date, - expectedValue: '2023-12-31T23:59:59.999Z', - }, -]; +describe('toFilterQuery', () => { + describe('basic queries', () => { + test('empty string returns empty object', () => { + expect(toFilterQueryObj('')).toEqual({}); + }); -// Examples of mixed BSON types -const mixedQuery = - '{ "id": UUID("123e4567-e89b-12d3-a456-426614174000"), "start": MinKey(), "end": MaxKey(), "created": new Date("2023-01-01") }'; + test('whitespace-only returns empty object', () => { + expect(toFilterQueryObj(' ')).toEqual({}); + }); -// Complex nested query -const complexQuery = - '{ "range": { "start": MinKey(), "end": MaxKey() }, "timestamp": new Date("2023-01-01"), "ids": [UUID("123e4567-e89b-12d3-a456-426614174000")] }'; + test('empty object returns empty object', () => { + expect(toFilterQueryObj('{ }')).toEqual({}); + }); -// String that contains BSON function syntax but should be treated as plain text -const textWithFunctionSyntax = '{ "userName": "A user with UUID()name and Date() format", "status": "active" }'; + test('simple string filter', () => { + expect(toFilterQueryObj('{ "name": "John" }')).toEqual({ name: 'John' }); + }); -// Error test cases -const errorTestCases = [ - { description: 'invalid JSON', input: '{ invalid json }' }, - { description: 'invalid UUID', input: '{ "id": UUID("invalid-uuid") }' }, - { description: 'invalid Date', input: '{ "date": new Date("invalid-date") }' }, - { description: 'missing parameter', input: '{ "key": UUID() }' }, -]; + test('filter with query operator', () => { + expect(toFilterQueryObj('{ "age": { "$gt": 30 } }')).toEqual({ age: { $gt: 30 } }); + }); -describe('toFilterQuery', () => { - it('converts basic query strings to objects', () => { - basicQueries.forEach((testCase) => { - expect(toFilterQueryObj(testCase.input)).toEqual(testCase.expected); + test('combined filter', () => { + expect(toFilterQueryObj('{ "name": "John", "age": { "$gt": 30 } }')).toEqual({ + name: 'John', + age: { $gt: 30 }, + }); }); }); - describe('BSON function support', () => { - test.each(bsonFunctionTestCases)('converts $type', ({ input, property, expectedClass, expectedValue }) => { - const result = toFilterQueryObj(input); - - expect(result).toHaveProperty(property); - expect(result[property]).toBeInstanceOf(expectedClass); - - if (expectedValue) { - if (result[property] instanceof UUID) { - // eslint-disable-next-line jest/no-conditional-expect - expect(result[property].toString()).toBe(expectedValue); - } else if (result[property] instanceof Date) { - // eslint-disable-next-line jest/no-conditional-expect - expect(result[property].toISOString()).toBe(expectedValue); - } - } + describe('relaxed syntax (new with shell-bson-parser)', () => { + test('unquoted keys', () => { + expect(toFilterQueryObj('{ count: 42 }')).toEqual({ count: 42 }); }); - }); - it('handles mixed BSON types in the same query', () => { - const result = toFilterQueryObj(mixedQuery); + test('single-quoted strings', () => { + expect(toFilterQueryObj("{ name: 'Alice' }")).toEqual({ name: 'Alice' }); + }); + + test('Math.min expression', () => { + const result = toFilterQueryObj('{ rating: Math.min(1.7, 2) }'); + expect(result).toEqual({ rating: 1.7 }); + }); - expect(result.id).toBeInstanceOf(UUID); - expect(result.start).toBeInstanceOf(MinKey); - expect(result.end).toBeInstanceOf(MaxKey); - expect(result.created).toBeInstanceOf(Date); + test('unquoted keys with nested operators', () => { + expect(toFilterQueryObj('{ age: { $gt: 25 } }')).toEqual({ age: { $gt: 25 } }); + }); - expect((result.id as UUID).toString()).toBe('123e4567-e89b-12d3-a456-426614174000'); - expect((result.created as Date).toISOString()).toBe('2023-01-01T00:00:00.000Z'); + test('mixed quoted and unquoted keys', () => { + expect(toFilterQueryObj('{ name: "Alice", "age": 30 }')).toEqual({ name: 'Alice', age: 30 }); + }); }); - it('handles complex nested queries with multiple BSON types', () => { - const result = toFilterQueryObj(complexQuery); + describe('BSON constructor support', () => { + test('UUID constructor', () => { + const result = toFilterQueryObj('{ id: UUID("123e4567-e89b-12d3-a456-426614174000") }'); + expect(result).toHaveProperty('id'); + // shell-bson-parser returns Binary subtype 4 for UUID + expect(result.id).toBeInstanceOf(Binary); + expect((result.id as Binary).sub_type).toBe(Binary.SUBTYPE_UUID); + }); - expect(result.range.start).toBeInstanceOf(MinKey); - expect(result.range.end).toBeInstanceOf(MaxKey); - expect(result.timestamp).toBeInstanceOf(Date); - expect(result.ids[0]).toBeInstanceOf(UUID); - }); + test('UUID with new keyword', () => { + const result = toFilterQueryObj('{ userId: new UUID("550e8400-e29b-41d4-a716-446655440000") }'); + expect(result).toHaveProperty('userId'); + expect(result.userId).toBeInstanceOf(Binary); + expect((result.userId as Binary).sub_type).toBe(Binary.SUBTYPE_UUID); + }); + + test('MinKey constructor', () => { + const result = toFilterQueryObj('{ start: MinKey() }'); + expect(result).toHaveProperty('start'); + expect(result.start).toBeInstanceOf(MinKey); + }); - it('does not process BSON function calls within string values', () => { - const result = toFilterQueryObj(textWithFunctionSyntax); - expect(result).toEqual({ - userName: 'A user with UUID()name and Date() format', - status: 'active', + test('MaxKey constructor', () => { + const result = toFilterQueryObj('{ end: MaxKey() }'); + expect(result).toHaveProperty('end'); + expect(result.end).toBeInstanceOf(MaxKey); + }); + + test('Date constructor', () => { + const result = toFilterQueryObj('{ created: new Date("2023-01-01") }'); + expect(result).toHaveProperty('created'); + expect(result.created).toBeInstanceOf(Date); + expect((result.created as Date).toISOString()).toBe('2023-01-01T00:00:00.000Z'); + }); + + test('ObjectId constructor', () => { + const result = toFilterQueryObj('{ _id: ObjectId("507f1f77bcf86cd799439011") }'); + expect(result).toHaveProperty('_id'); + expect(result._id).toBeInstanceOf(ObjectId); + }); + + test('ISODate constructor', () => { + const result = toFilterQueryObj('{ ts: ISODate("2024-01-01") }'); + expect(result).toHaveProperty('ts'); + expect(result.ts).toBeInstanceOf(Date); + }); + + test('Decimal128 constructor', () => { + const result = toFilterQueryObj('{ val: Decimal128("1.23") }'); + expect(result).toHaveProperty('val'); + expect(result.val).toBeInstanceOf(Decimal128); + }); + + test('NumberInt constructor', () => { + const result = toFilterQueryObj('{ n: NumberInt(42) }'); + expect(result).toHaveProperty('n'); + expect(result.n).toBeInstanceOf(Int32); + }); + + test('NumberLong constructor', () => { + const result = toFilterQueryObj('{ n: NumberLong(42) }'); + expect(result).toHaveProperty('n'); + expect(result.n).toBeInstanceOf(Long); + }); + + test('Timestamp constructor', () => { + const result = toFilterQueryObj('{ ts: Timestamp(1, 1) }'); + expect(result).toHaveProperty('ts'); + expect(result.ts).toBeInstanceOf(Timestamp); }); }); - describe('error handling', () => { - test.each(errorTestCases)('throws QueryError for $description', ({ input }) => { - expect(() => toFilterQueryObj(input)).toThrow(QueryError); + describe('mixed BSON types', () => { + test('multiple BSON constructors in one query', () => { + const result = toFilterQueryObj( + '{ id: UUID("123e4567-e89b-12d3-a456-426614174000"), start: MinKey(), end: MaxKey(), created: new Date("2023-01-01") }', + ); + + expect(result.id).toBeInstanceOf(Binary); + expect((result.id as Binary).sub_type).toBe(Binary.SUBTYPE_UUID); + expect(result.start).toBeInstanceOf(MinKey); + expect(result.end).toBeInstanceOf(MaxKey); + expect(result.created).toBeInstanceOf(Date); }); - it('throws QueryError with INVALID_FILTER code for invalid JSON', () => { - let thrownError: QueryError | undefined; - try { - toFilterQueryObj('{ invalid json }'); - } catch (error) { - thrownError = error as QueryError; - } - expect(thrownError).toBeDefined(); - expect(thrownError?.name).toBe('QueryError'); - expect(thrownError?.code).toBe('INVALID_FILTER'); + test('nested BSON constructors', () => { + const result = toFilterQueryObj( + '{ range: { start: MinKey(), end: MaxKey() }, timestamp: new Date("2023-01-01") }', + ); + + expect(result.range.start).toBeInstanceOf(MinKey); + expect(result.range.end).toBeInstanceOf(MaxKey); + expect(result.timestamp).toBeInstanceOf(Date); + }); + }); + + describe('error handling', () => { + test('throws QueryError for invalid syntax', () => { + expect(() => toFilterQueryObj('{ invalid json }')).toThrow(QueryError); }); - it('throws QueryError with INVALID_FILTER code for invalid UUID', () => { + test('throws QueryError with INVALID_FILTER code', () => { let thrownError: QueryError | undefined; try { - toFilterQueryObj('{ "id": UUID("invalid-uuid") }'); + toFilterQueryObj('not valid at all'); } catch (error) { thrownError = error as QueryError; } @@ -206,10 +196,10 @@ describe('toFilterQuery', () => { expect(thrownError?.code).toBe('INVALID_FILTER'); }); - it('includes original error message in QueryError message', () => { + test('error message contains "Invalid filter syntax"', () => { let thrownError: QueryError | undefined; try { - toFilterQueryObj('{ invalid json }'); + toFilterQueryObj('not valid'); } catch (error) { thrownError = error as QueryError; } @@ -217,16 +207,15 @@ describe('toFilterQuery', () => { expect(thrownError?.message).toContain('Invalid filter syntax'); }); - it('includes helpful JSON example in error message', () => { + test('error message contains helpful example', () => { let thrownError: QueryError | undefined; try { - toFilterQueryObj('{ invalid json }'); + toFilterQueryObj('not valid'); } catch (error) { thrownError = error as QueryError; } expect(thrownError).toBeDefined(); - expect(thrownError?.message).toContain('Please use valid JSON'); - expect(thrownError?.message).toContain('"name": "value"'); + expect(thrownError?.message).toContain('name: "value"'); }); }); }); diff --git a/src/documentdb/utils/toFilterQuery.ts b/src/documentdb/utils/toFilterQuery.ts index 807f18858..1cbb67a15 100644 --- a/src/documentdb/utils/toFilterQuery.ts +++ b/src/documentdb/utils/toFilterQuery.ts @@ -3,227 +3,38 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { EJSON } from 'bson'; -import { UUID, type Document, type Filter } from 'mongodb'; +import { ParseMode, parse as parseShellBSON } from '@mongodb-js/shell-bson-parser'; +import { type Document, type Filter } from 'mongodb'; import * as vscode from 'vscode'; import { QueryError } from '../errors/QueryError'; +/** + * Parses a user-provided filter query string into a DocumentDB filter object. + * + * Uses `@mongodb-js/shell-bson-parser` in Loose mode, which supports: + * - Unquoted keys: `{ name: 1 }` + * - Single-quoted strings: `{ name: 'Alice' }` + * - BSON constructors: `ObjectId("...")`, `UUID("...")`, `ISODate("...")`, etc. + * - JS expressions: `Math.min(1.7, 2)`, `Date.now()`, arithmetic + * - MongoDB Extended JSON: `{ "$oid": "..." }` + * + * Replaces the previous hand-rolled regex-based converter + EJSON.parse pipeline. + */ export function toFilterQueryObj(queryString: string): Filter { try { - // Convert pseudo-JavaScript style BSON constructor calls into Extended JSON that EJSON can parse. - // Example: { "id": UUID("...") } -> { "id": {"$uuid":"..."} } - const extendedJsonQuery = convertToExtendedJson(queryString); - // EJSON.parse will turn Extended JSON into native BSON/JS types (UUID, Date, etc.). - return EJSON.parse(extendedJsonQuery) as Filter; - } catch (error) { if (queryString.trim().length === 0) { return {} as Filter; } - + return parseShellBSON(queryString, { mode: ParseMode.Loose }) as Filter; + } catch (error) { const cause = error instanceof Error ? error : new Error(String(error)); throw new QueryError( 'INVALID_FILTER', vscode.l10n.t( - 'Invalid filter syntax: {0}. Please use valid JSON, for example: { "name": "value" }', + 'Invalid filter syntax: {0}. Please use valid JSON or a DocumentDB API expression, for example: { name: "value" }', cause.message, ), cause, ); } } - -/** - * Walks the raw query text and rewrites BSON-like constructor calls (UUID, MinKey, MaxKey, Date) - * into MongoDB Extended JSON fragments while deliberately skipping anything that appears inside - * string literals (so user text containing e.g. "UUID(" is not transformed). - * - * This is intentionally lightweight and avoids a full JS / JSON parser to keep latency low inside - * the query input UX. Future improvements may replace this with a tokenizer / parser for richer - * validation and diagnostics. - */ -function convertToExtendedJson(query: string): string { - // Phase 1: Precompute which character positions are inside a (single or double quoted) string. - // This lets the replacement pass stay simple and branchless for non‑string regions. - const isInString = markStringLiterals(query); - - // Phase 2: Scan + rewrite BSON-like calls only when not inside a string literal. - let result = ''; - let i = 0; - while (i < query.length) { - if (isInString[i]) { - // Inside a user string literal – copy verbatim. - result += query[i]; - i += 1; - continue; - } - - const remaining = query.slice(i); - - // UUID(...) - const uuidMatch = matchUUID(remaining); - if (uuidMatch) { - const { raw, uuidString } = uuidMatch; - try { - // Validate early so we fail fast instead of producing malformed Extended JSON. - // (Instantiation is enough to validate format.) - new UUID(uuidString); - } catch { - throw new Error(`Invalid UUID: ${uuidString}`); - } - result += `{"$uuid":"${uuidString}"}`; - i += raw.length; - continue; - } - - // MinKey() - const minKeyMatch = matchMinKey(remaining); - if (minKeyMatch) { - result += '{"$minKey":1}'; - i += minKeyMatch.raw.length; - continue; - } - - // MaxKey() - const maxKeyMatch = matchMaxKey(remaining); - if (maxKeyMatch) { - result += '{"$maxKey":1}'; - i += maxKeyMatch.raw.length; - continue; - } - - // Date("...") - const dateMatch = matchDate(remaining); - if (dateMatch) { - const { raw, dateString } = dateMatch; - const date = new Date(dateString); - if (Number.isNaN(date.getTime())) { - throw new Error(`Invalid date: ${dateString}`); - } - result += `{"$date":"${dateString}"}`; - i += raw.length; - continue; - } - - // Fallback: copy one character. - result += query[i]; - i += 1; - } - - return result; -} - -/** - * markStringLiterals - * - * Lightweight pass to flag which character indices are inside a quoted string. - * - * Supported: - * - Single quotes '...' - * - Double quotes "..." - * - Escapes inside those strings via backslash (\" or \') - * - * Not a full JSON validator: - * - Does not detect malformed / unclosed strings (those will just mark to end) - * - Does not handle template literals (not valid JSON anyway) - * - * Rationale: - * This is intentionally simple and fast. It exists to prevent accidental rewriting of text - * inside user-provided string values (e.g. "note: call UUID('x') later") while we still accept - * a relaxed JSON-ish syntax for convenience. If the query authoring experience is expanded - * (linting, richer autocomplete, tolerant recovery) we can replace this with a proper tokenizer. - */ -function markStringLiterals(input: string): boolean[] { - const isInString: boolean[] = new Array(input.length).fill(false) as boolean[]; - let inString = false; - let currentQuote: '"' | "'" | null = null; - let escapeNext = false; - - for (let i = 0; i < input.length; i++) { - const ch = input[i]; - - if (escapeNext) { - // Current char is escaped; treat it as plain content inside the string. - isInString[i] = inString; - escapeNext = false; - continue; - } - - if (inString) { - // Inside a string: mark and handle escapes / termination. - isInString[i] = true; - if (ch === '\\') { - escapeNext = true; - } else if (ch === currentQuote) { - inString = false; - currentQuote = null; - } - continue; - } - - // Not currently in a string – only a quote can start one. - if (ch === '"' || ch === "'") { - inString = true; - currentQuote = ch as '"' | "'"; - isInString[i] = true; - continue; - } - - // Outside of strings. - isInString[i] = false; - } - - return isInString; -} - -// --- Regex constants for BSON-like constructor calls --- - -/** - * Matches UUID constructor calls, e.g. UUID("...") or new UUID('...'), case-insensitive. - * Captures the quoted UUID string. - * Pattern details: - * - Optional "new" prefix with whitespace: (?:new\s+)? - * - "uuid" keyword, case-insensitive - * - Optional whitespace before and inside parentheses - * - Quoted string (single or double quotes) as argument, captured in group 1 - */ -const UUID_REGEX = /^(?:new\s+)?uuid\s*\(\s*["']([^"']+)["']\s*\)/i; - -/** - * Matches MinKey constructor calls, e.g. MinKey() or new MinKey(), case-insensitive. - * No arguments. - */ -const MIN_KEY_REGEX = /^(?:new\s+)?minkey\s*\(\s*\)/i; - -/** - * Matches MaxKey constructor calls, e.g. MaxKey() or new MaxKey(), case-insensitive. - * No arguments. - */ -const MAX_KEY_REGEX = /^(?:new\s+)?maxkey\s*\(\s*\)/i; - -/** - * Matches Date constructor calls, e.g. Date("...") or new Date('...'), case-insensitive. - * Captures the quoted date string. - * Pattern details: - * - Optional "new" prefix with whitespace: (?:new\s+)? - * - "date" keyword, case-insensitive - * - Optional whitespace before and inside parentheses - * - Quoted string (single or double quotes) as argument, captured in group 1 - */ -const DATE_REGEX = /^(?:new\s+)?date\s*\(\s*["']([^"']+)["']\s*\)/i; - -function matchUUID(src: string): { raw: string; uuidString: string } | undefined { - const m = UUID_REGEX.exec(src); - return m ? { raw: m[0], uuidString: m[1] } : undefined; -} -function matchMinKey(src: string): { raw: string } | undefined { - const m = MIN_KEY_REGEX.exec(src); - return m ? { raw: m[0] } : undefined; -} -function matchMaxKey(src: string): { raw: string } | undefined { - const m = MAX_KEY_REGEX.exec(src); - return m ? { raw: m[0] } : undefined; -} -function matchDate(src: string): { raw: string; dateString: string } | undefined { - const m = DATE_REGEX.exec(src); - return m ? { raw: m[0], dateString: m[1] } : undefined; -} diff --git a/src/utils/json/data-api/autocomplete/basicMongoFindFilterSchema.json b/src/utils/json/data-api/autocomplete/basicMongoFindFilterSchema.json deleted file mode 100644 index a886411a4..000000000 --- a/src/utils/json/data-api/autocomplete/basicMongoFindFilterSchema.json +++ /dev/null @@ -1,173 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "mongodb-generic-filter-schema", - "title": "MongoDB Generic Find Filter Schema", - "type": "object", - "additionalProperties": { - "oneOf": [ - { - "title": "Direct Value", - "description": "A direct value for equality matching on any field.", - "examples": ["example", 42, true, null] - }, - { - "title": "Operator-Based Query", - "$ref": "#/definitions/operatorObject", - "examples": [ - { "$gt": 10 }, - { "$lt": 100 }, - { "$gte": 5 }, - { "$lte": 50 }, - { "$in": ["red", "blue", "green"] }, - { "$nin": ["yellow", "purple"] }, - { "$exists": false }, - { "$regex": "^start.*end$" }, - { "$gt": 10, "$lt": 20 }, - { "$in": [1, 2, 3], "$nin": [4, 5] } - ] - } - ] - }, - "properties": { - "$or": { - "type": "array", - "items": { "$ref": "#" }, - "description": "Joins query clauses with a logical OR.", - "examples": [ - [{ "status": "A" }, { "qty": { "$lt": 30 } }], - [{ "age": { "$gte": 18 } }, { "membership": "gold" }], - [{ "category": { "$in": ["electronics", "books"] } }, { "onSale": true }] - ] - }, - "$and": { - "type": "array", - "items": { "$ref": "#" }, - "description": "Joins query clauses with a logical AND.", - "examples": [ - [{ "status": "A" }, { "qty": { "$gt": 20, "$lt": 50 } }], - [{ "verified": true }, { "email": { "$exists": true } }], - [{ "price": { "$gte": 100 } }, { "stock": { "$lte": 500 } }] - ] - }, - "$not": { - "oneOf": [{ "$ref": "#" }], - "description": "Inverts the effect of a query expression.", - "examples": [ - { "price": { "$gt": 100 } }, - { "status": { "$eq": "inactive" } }, - { "category": { "$in": ["outdated", "discontinued"] } } - ] - }, - "$nor": { - "type": "array", - "items": { "$ref": "#" }, - "description": "Joins query clauses with a logical NOR.", - "examples": [ - [{ "price": 1.99 }, { "qty": { "$lt": 20 } }], - [{ "status": "A" }, { "onSale": true }], - [{ "rating": { "$gte": 4.5 } }, { "reviews": { "$gt": 100 } }] - ] - } - }, - "definitions": { - "operatorObject": { - "type": "object", - "properties": { - "$eq": { - "description": "Matches values that are equal to a specified value.", - "examples": ["active", 100, true] - }, - "$ne": { - "description": "Matches all values that are not equal to a specified value.", - "examples": ["inactive", 0, false] - }, - "$gt": { - "description": "Matches values that are greater than a specified value.", - "examples": [10, 100] - }, - "$gte": { - "description": "Matches values that are greater than or equal to a specified value.", - "examples": [5, 50] - }, - "$lt": { - "description": "Matches values that are less than a specified value.", - "examples": [20, 80] - }, - "$lte": { - "description": "Matches values that are less than or equal to a specified value.", - "examples": [15, 75] - }, - "$in": { - "type": "array", - "description": "Matches any of the values specified in an array.", - "examples": [ - ["red", "green", "blue"], - [1, 2, 3], - ["small", "medium", "large"] - ] - }, - "$nin": { - "type": "array", - "description": "Matches none of the values specified in an array.", - "examples": [ - ["yellow", "purple"], - [4, 5, 6], - ["extra-large", "xxl"] - ] - }, - "$exists": { - "type": "boolean", - "description": "Matches documents that have the specified field.", - "examples": [true, false] - }, - "$regex": { - "description": "Provides regular expression capabilities for pattern matching strings.", - "examples": ["^start", "end$", ".*pattern.*", "^[A-Z]{3}[0-9]{2}$"] - }, - "$size": { - "type": "integer", - "description": "Matches any array with the specified number of elements.", - "examples": [0, 5, 10] - }, - "$type": { - "description": "Matches values based on their BSON type.", - "examples": [1, "string", "object"] - }, - "$all": { - "type": "array", - "description": "Matches arrays that contain all elements specified in the query.", - "examples": [ - ["red", "blue"], - [10, 20], - ["feature1", "feature2"] - ] - }, - "$elemMatch": { - "type": "object", - "description": "Matches documents that contain an array field with at least one element that matches the specified query criteria.", - "examples": [ - { "score": { "$gt": 80 } }, - { "dimensions": { "$lt": 50, "$gt": 20 } }, - { "attributes": { "color": "red", "size": "M" } } - ] - } - }, - "additionalProperties": false, - "description": "An object containing MongoDB query operators and their corresponding values.", - "minProperties": 1, - "examples": [ - { "$gt": 10 }, - { "$lt": 100 }, - { "$gte": 5 }, - { "$lte": 50 }, - { "$in": ["value1", "value2"] }, - { "$gt": 10, "$lt": 20 }, - { "$exists": true }, - { "$regex": "^[a-z]+$" }, - { "$in": [1, 2, 3], "$nin": [4, 5, 6] }, - { "$elemMatch": { "score": { "$gte": 80 } } } - ] - } - }, - "description": "Generic schema for MongoDB find query filters without knowledge of specific fields." -} diff --git a/src/utils/json/data-api/autocomplete/generateMongoFindJsonSchema.ts b/src/utils/json/data-api/autocomplete/generateMongoFindJsonSchema.ts deleted file mode 100644 index edaa8a64a..000000000 --- a/src/utils/json/data-api/autocomplete/generateMongoFindJsonSchema.ts +++ /dev/null @@ -1,270 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { type FieldEntry } from '@vscode-documentdb/schema-analyzer'; - -/** - * Generates a JSON schema for MongoDB find filter queries. - * - * This function is a short-term solution for providing autocompletion for MongoDB find filter queries. - * A MongoDB find filter query is a JSON document that can range from simple to complex structures. - * Basic autocompletion can be provided using a modified JSON schema, which is what we've done here. - * - * The long-term plan is to provide a more sophisticated auto-completion using, for example, - * the suggestion API that Monaco provides. This will be looked at in the future. - * - * @param fieldEntries - An array of field entries where each entry contains: - * - path: A string representing the full path of the field in the dataset (e.g., "age", "address.city"). - * - type: The most common or expected data type for that field (e.g., "number", "string"). - * - * The data provided is supposed to contain all known data paths from the expected dataset, - * focusing only on leaf nodes. - * - * The returned JSON schema can be directly added to the Monaco editor to activate autocompletion. - * - * @returns A JSON schema object that can be used for autocompletion in the Monaco editor. - */ -export function generateMongoFindJsonSchema(fieldEntries: FieldEntry[]) { - // Initialize the base schema object - const schema = { - $schema: 'http://json-schema.org/draft-07/schema#', - $id: 'mongodb-filter-schema', - title: 'MongoDB Find Filter Schema', - type: 'object', - properties: {}, - additionalProperties: { - oneOf: [ - { - title: 'Direct Value', - description: 'A direct value for equality matching on an unknown field.', - examples: ['value', 123, true, null], - }, - { - title: 'Operator-Based Query', - $ref: '#/definitions/operatorObjectUnknown', - examples: [{ $ne: 'inactive' }, { $exists: true }], - }, - ], - }, - definitions: { - operatorObject: { - type: 'object', - properties: { - $eq: { - description: 'Matches values that are equal to a specified value.', - examples: [21, 'active', true], - }, - $ne: { - description: 'Matches all values that are not equal to a specified value.', - examples: [30, 'inactive', false], - }, - $gt: { - description: 'Matches values that are greater than a specified value.', - examples: [25, 100], - }, - $gte: { - description: 'Matches values that are greater than or equal to a specified value.', - examples: [18, 50], - }, - $lt: { - description: 'Matches values that are less than a specified value.', - examples: [65, 100], - }, - $lte: { - description: 'Matches values that are less than or equal to a specified value.', - examples: [30, 75], - }, - $in: { - type: 'array', - description: 'Matches any of the values specified in an array.', - examples: [ - ['red', 'blue'], - [21, 30, 40], - ], - }, - $nin: { - type: 'array', - description: 'Matches none of the values specified in an array.', - examples: [['green'], [50, 60]], - }, - $exists: { - type: 'boolean', - description: 'Matches documents that have the specified field.', - examples: [true, false], - }, - $regex: { - description: 'Provides regular expression capabilities for pattern matching strings.', - examples: ['^re', '.*blue$', '^[A-Z]+'], - }, - }, - additionalProperties: false, - description: 'An object containing a MongoDB query operator and its corresponding value.', - minProperties: 1, - }, - operatorObjectUnknown: { - $ref: '#/definitions/operatorObject', - }, - }, - description: - 'Schema for MongoDB find query filters, supporting known fields with various operators for querying documents.', - }; - - // Set to collect all full paths - const fullPathsSet = new Set(); - - // Function to generate examples based on type - function generateExamples(type: string): unknown[] { - let examples; - if (type === 'number') { - examples = [42, 100]; - // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access - examples.push(false); // odd type - // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access - examples.push(null); - } else if (type === 'string') { - examples = ['red', 'blue']; - // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access - examples.push(null); - } else if (type === 'boolean') { - examples = [true, false]; - // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access - examples.push(null); - } else { - examples = ['value', 123, true, null]; - } - return examples as []; - } - - // Function to generate examples for operator-based queries - function generateOperatorExamples(type: string): unknown[] { - let examples; - if (type === 'number') { - examples = [{ $gt: 25 }, { $in: [20, 30, 40] }]; - } else if (type === 'string') { - examples = [{ $regex: '^re' }, { $ne: 'blue' }]; - } else if (type === 'boolean') { - examples = [{ $eq: true }, { $ne: false }]; - } else { - examples = [{ $exists: true }]; - } - return examples as []; - } - - // Function to create nested properties based on path components - function createNestedProperty( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - obj: any, - pathComponents: string[], - type: string, - currentPath: string = '', - ) { - const fieldName = pathComponents[0]; - const newPath = currentPath ? `${currentPath}.${fieldName}` : fieldName; - - fullPathsSet.add(newPath); - - if (pathComponents.length === 1) { - // Leaf node - const examples = generateExamples(type); - const operatorExamples = generateOperatorExamples(type); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - obj[fieldName] = { - oneOf: [ - { - title: 'Direct Value', - description: `A direct value for equality matching on the '${fieldName}' field.`, - examples: examples, - }, - { - title: 'Operator-Based Query', - $ref: '#/definitions/operatorObject', - examples: operatorExamples, - }, - ], - }; - } else { - // Nested object - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (!obj[fieldName]) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - obj[fieldName] = { - type: 'object', - properties: {}, - additionalProperties: false, - description: `Embedded '${fieldName}' object containing fields.`, - }; - } - createNestedProperty( - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - obj[fieldName]['properties'], - pathComponents.slice(1), - type, - newPath, - ); - } - } - - // Process each fieldEntry - for (const fieldEntry of fieldEntries) { - const pathComponents = fieldEntry.path.split('.'); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - createNestedProperty(schema['properties'], pathComponents, fieldEntry.type); - } - - // Function to get type for a full path - function getTypeForFullPath(fullPath: string): string | undefined { - for (const fieldEntry of fieldEntries) { - if (fieldEntry.path === fullPath) { - return fieldEntry.type; - } - } - return undefined; - } - - // Create properties with full paths at the root level - for (const fullPath of fullPathsSet) { - const type = getTypeForFullPath(fullPath) || 'string'; - const examples = generateExamples(type); - const operatorExamples = generateOperatorExamples(type); - - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - schema['properties'][fullPath] = { - oneOf: [ - { - title: 'Direct Value', - description: `A direct value for equality matching on the '${fullPath}' field.`, - examples: examples, - }, - { - title: 'Operator-Based Query', - $ref: '#/definitions/operatorObject', - examples: operatorExamples, - }, - ], - }; - } - - // Add logical operators - const logicalOperators = ['$or', '$and', '$not', '$nor']; - for (const operator of logicalOperators) { - if (operator === '$not') { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - schema['properties'][operator] = { - oneOf: [{ $ref: '#' }], - description: `Inverts the effect of a query expression.`, - }; - } else { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - schema['properties'][operator] = { - type: 'array', - items: { $ref: '#' }, - description: `Joins query clauses with a logical ${operator.toUpperCase().substring(1)}.`, - }; - } - } - - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return schema; -} diff --git a/src/webviews/documentdb/collectionView/CollectionView.tsx b/src/webviews/documentdb/collectionView/CollectionView.tsx index 89de231d1..ef05ace0c 100644 --- a/src/webviews/documentdb/collectionView/CollectionView.tsx +++ b/src/webviews/documentdb/collectionView/CollectionView.tsx @@ -12,6 +12,7 @@ import { Announcer } from '../../api/webview-client/accessibility'; import { useConfiguration } from '../../api/webview-client/useConfiguration'; import { useTrpcClient } from '../../api/webview-client/useTrpcClient'; import { useSelectiveContextMenuPrevention } from '../../api/webview-client/utils/useSelectiveContextMenuPrevention'; +import { setCompletionContext } from '../../documentdbQuery'; import './collectionView.scss'; import { CollectionViewContext, @@ -351,10 +352,15 @@ export const CollectionView = (): JSX.Element => { } function updateAutoCompletionData(): void { - // TODO: Step 4 — Replace with field-completion-data push via tRPC subscription. - // The old JSON schema pipeline (getAutocompletionSchema + setJsonSchema) has been - // removed as part of the documentdb-query language POC. Static completions from - // documentdb-constants are used until dynamic field data is wired up. + trpcClient.mongoClusters.collectionView.getFieldCompletionData + .query() + .then((fields) => { + setCompletionContext(configuration.sessionId, { fields }); + }) + .catch((error) => { + console.debug('Failed to update field completion data:', error); + // Non-blocking — completion will work without fields + }); } function handleDeleteDocumentRequest(): void { diff --git a/src/webviews/documentdb/collectionView/collectionViewRouter.ts b/src/webviews/documentdb/collectionView/collectionViewRouter.ts index 62ef2f476..8e00cfa70 100644 --- a/src/webviews/documentdb/collectionView/collectionViewRouter.ts +++ b/src/webviews/documentdb/collectionView/collectionViewRouter.ts @@ -9,7 +9,6 @@ import * as fs from 'fs'; import { type Document } from 'mongodb'; import * as path from 'path'; import * as vscode from 'vscode'; -import { type JSONSchema } from 'vscode-json-languageservice'; import { z } from 'zod'; import { ClusterSession } from '../../../documentdb/ClusterSession'; import { getConfirmationAsInSettings } from '../../../utils/dialogs/getConfirmation'; @@ -39,9 +38,7 @@ import { Views } from '../../../documentdb/Views'; import { ext } from '../../../extensionVariables'; import { QueryInsightsAIService } from '../../../services/ai/QueryInsightsAIService'; import { type CollectionItem } from '../../../tree/documentdb/CollectionItem'; -// eslint-disable-next-line import/no-internal-modules -import basicFindQuerySchema from '../../../utils/json/data-api/autocomplete/basicMongoFindFilterSchema.json'; -import { generateMongoFindJsonSchema } from '../../../utils/json/data-api/autocomplete/generateMongoFindJsonSchema'; +import { toFieldCompletionItems } from '../../../utils/json/data-api/autocomplete/toFieldCompletionItems'; import { promptAfterActionEventually } from '../../../utils/survey'; import { UsageImpact } from '../../../utils/surveyTypes'; import { type BaseRouterContext } from '../../api/configuration/appRouter'; @@ -234,24 +231,16 @@ export const collectionsViewRouter = router({ return { documentCount: size }; }), - getAutocompletionSchema: publicProcedureWithTelemetry + getFieldCompletionData: publicProcedureWithTelemetry // procedure type .query(({ ctx }) => { const myCtx = ctx as WithTelemetry; const session: ClusterSession = ClusterSession.getSession(myCtx.sessionId); - const autoCompletionData: FieldEntry[] = session.getKnownFields(); + const fieldEntries: FieldEntry[] = session.getKnownFields(); - let querySchema: JSONSchema; - - if (autoCompletionData.length > 0) { - querySchema = generateMongoFindJsonSchema(autoCompletionData); - } else { - querySchema = basicFindQuerySchema; - } - - return querySchema; + return toFieldCompletionItems(fieldEntries); }), getCurrentPageAsTable: publicProcedureWithTelemetry // parameters diff --git a/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx b/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx index d35ccc952..709c883e2 100644 --- a/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx +++ b/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx @@ -11,7 +11,15 @@ import { InputWithProgress } from '../../../../components/InputWithProgress'; // eslint-disable-next-line import/no-internal-modules import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; import { useConfiguration } from '../../../../api/webview-client/useConfiguration'; -import { LANGUAGE_ID, registerDocumentDBQueryLanguage } from '../../../../documentdbQuery'; +import { + buildEditorUri, + clearCompletionContext, + EditorType, + LANGUAGE_ID, + registerDocumentDBQueryLanguage, + validateExpression, + type Diagnostic, +} from '../../../../documentdbQuery'; import { type CollectionViewWebviewConfigurationType } from '../../collectionViewController'; import { ArrowResetRegular, SendRegular, SettingsFilled, SettingsRegular } from '@fluentui/react-icons'; @@ -23,6 +31,31 @@ import { CollectionViewContext } from '../../collectionViewContext'; import { useHideScrollbarsDuringResize } from '../../hooks/useHideScrollbarsDuringResize'; import './queryEditor.scss'; +/** + * Convert a Diagnostic from the documentdb-query validator to a Monaco marker. + */ +function toMonacoMarker( + diagnostic: Diagnostic, + model: monacoEditor.editor.ITextModel, + monaco: typeof monacoEditor, +): monacoEditor.editor.IMarkerData { + const startPos = model.getPositionAt(diagnostic.startOffset); + const endPos = model.getPositionAt(diagnostic.endOffset); + return { + severity: + diagnostic.severity === 'error' + ? monaco.MarkerSeverity.Error + : diagnostic.severity === 'warning' + ? monaco.MarkerSeverity.Warning + : monaco.MarkerSeverity.Info, + message: diagnostic.message, + startLineNumber: startPos.lineNumber, + startColumn: startPos.column, + endLineNumber: endPos.lineNumber, + endColumn: endPos.column, + }; +} + interface QueryEditorProps { onExecuteRequest: () => void; } @@ -55,15 +88,67 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element const hideScrollbarsTemporarily = useHideScrollbarsDuringResize(); - const handleEditorDidMount = (editor: monacoEditor.editor.IStandaloneCodeEditor, monaco: typeof monacoEditor) => { - editor.setValue('{ }'); + /** + * Creates a Monaco model with a URI scheme for the given editor type. + * This enables the completion provider to identify which editor the request is for. + */ + const createEditorModel = ( + editor: monacoEditor.editor.IStandaloneCodeEditor, + monaco: typeof monacoEditor, + editorType: EditorType, + initialValue: string, + ): monacoEditor.editor.ITextModel => { + const uri = monaco.Uri.parse(buildEditorUri(editorType, configuration.sessionId)); + let model = monaco.editor.getModel(uri); + if (!model) { + model = monaco.editor.createModel(initialValue, LANGUAGE_ID, uri); + } + editor.setModel(model); + return model; + }; + /** + * Sets up debounced validation on editor content changes. + * Returns a cleanup function to clear any pending timeout. + */ + const setupValidation = ( + editor: monacoEditor.editor.IStandaloneCodeEditor, + monaco: typeof monacoEditor, + model: monacoEditor.editor.ITextModel, + ): (() => void) => { + let validationTimeout: ReturnType; + const disposable = editor.onDidChangeModelContent(() => { + clearTimeout(validationTimeout); + validationTimeout = setTimeout(() => { + const diagnostics = validateExpression(editor.getValue()); + const markers = diagnostics.map((d) => toMonacoMarker(d, model, monaco)); + monaco.editor.setModelMarkers(model, 'documentdb-query', markers); + }, 300); + }); + return () => { + clearTimeout(validationTimeout); + disposable.dispose(); + }; + }; + + // Track validation cleanup functions + const filterValidationCleanupRef = useRef<(() => void) | null>(null); + const projectValidationCleanupRef = useRef<(() => void) | null>(null); + const sortValidationCleanupRef = useRef<(() => void) | null>(null); + + const handleEditorDidMount = (editor: monacoEditor.editor.IStandaloneCodeEditor, monaco: typeof monacoEditor) => { // Store the filter editor reference filterEditorRef.current = editor; // Register the documentdb-query language (idempotent — safe to call on every mount) void registerDocumentDBQueryLanguage(monaco); + // Create model with URI scheme for contextual completions + const model = createEditorModel(editor, monaco, EditorType.Filter, '{ }'); + + // Set up debounced validation + filterValidationCleanupRef.current = setupValidation(editor, monaco, model); + const getCurrentQueryFunction = () => ({ filter: filterValue, project: projectValue, @@ -111,8 +196,21 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element aiGenerationAbortControllerRef.current.abort(); aiGenerationAbortControllerRef.current = null; } + + // Clean up validation timeouts + filterValidationCleanupRef.current?.(); + projectValidationCleanupRef.current?.(); + sortValidationCleanupRef.current?.(); + + // Dispose Monaco models + filterEditorRef.current?.getModel()?.dispose(); + projectEditorRef.current?.getModel()?.dispose(); + sortEditorRef.current?.getModel()?.dispose(); + + // Clear completion store for this session + clearCompletionContext(configuration.sessionId); }; - }, []); + }, [configuration.sessionId]); // Update getCurrentQuery function whenever state changes useEffect(() => { @@ -336,7 +434,7 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element }} onMount={(editor, monaco) => { handleEditorDidMount(editor, monaco); - // Sync initial value + // Sync editor content to state editor.onDidChangeModelContent(() => { setFilterValue(editor.getValue()); }); @@ -442,9 +540,18 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element minLines: 1, lineHeight: 19, }} - onMount={(editor) => { + onMount={(editor, monaco) => { + // Register language (idempotent) + void registerDocumentDBQueryLanguage(monaco); + projectEditorRef.current = editor; - editor.setValue(projectValue); + + // Create model with URI scheme for project completions + const model = createEditorModel(editor, monaco, EditorType.Project, projectValue); + + // Set up validation + projectValidationCleanupRef.current = setupValidation(editor, monaco, model); + editor.onDidChangeModelContent(() => { setProjectValue(editor.getValue()); }); @@ -473,9 +580,18 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element minLines: 1, lineHeight: 19, }} - onMount={(editor) => { + onMount={(editor, monaco) => { + // Register language (idempotent) + void registerDocumentDBQueryLanguage(monaco); + sortEditorRef.current = editor; - editor.setValue(sortValue); + + // Create model with URI scheme for sort completions + const model = createEditorModel(editor, monaco, EditorType.Sort, sortValue); + + // Set up validation + sortValidationCleanupRef.current = setupValidation(editor, monaco, model); + editor.onDidChangeModelContent(() => { setSortValue(editor.getValue()); }); diff --git a/src/webviews/documentdbQuery/completionStore.test.ts b/src/webviews/documentdbQuery/completionStore.test.ts new file mode 100644 index 000000000..b674116ac --- /dev/null +++ b/src/webviews/documentdbQuery/completionStore.test.ts @@ -0,0 +1,126 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { + clearAllCompletionContexts, + clearCompletionContext, + getCompletionContext, + setCompletionContext, +} from './completionStore'; + +describe('completionStore', () => { + beforeEach(() => { + clearAllCompletionContexts(); + }); + + test('setCompletionContext then getCompletionContext round-trips correctly', () => { + const context = { + fields: [ + { + fieldName: 'name', + displayType: 'String', + bsonType: 'string', + isSparse: false, + insertText: 'name', + referenceText: '$name', + }, + ], + }; + + setCompletionContext('session-1', context); + expect(getCompletionContext('session-1')).toEqual(context); + }); + + test('getCompletionContext returns undefined for unknown session', () => { + expect(getCompletionContext('unknown')).toBeUndefined(); + }); + + test('clearCompletionContext removes the entry', () => { + setCompletionContext('session-1', { fields: [] }); + expect(getCompletionContext('session-1')).toBeDefined(); + + clearCompletionContext('session-1'); + expect(getCompletionContext('session-1')).toBeUndefined(); + }); + + test('clearCompletionContext is a no-op for unknown session', () => { + expect(() => clearCompletionContext('unknown')).not.toThrow(); + }); + + test('clearAllCompletionContexts removes all entries', () => { + setCompletionContext('session-1', { fields: [] }); + setCompletionContext('session-2', { fields: [] }); + + clearAllCompletionContexts(); + + expect(getCompletionContext('session-1')).toBeUndefined(); + expect(getCompletionContext('session-2')).toBeUndefined(); + }); + + test('setCompletionContext overwrites existing data', () => { + const original = { + fields: [ + { + fieldName: 'old', + displayType: 'String', + bsonType: 'string', + isSparse: false, + insertText: 'old', + referenceText: '$old', + }, + ], + }; + const updated = { + fields: [ + { + fieldName: 'new', + displayType: 'Number', + bsonType: 'double', + isSparse: true, + insertText: 'new', + referenceText: '$new', + }, + ], + }; + + setCompletionContext('session-1', original); + setCompletionContext('session-1', updated); + + expect(getCompletionContext('session-1')).toEqual(updated); + }); + + test('multiple sessions are independent', () => { + const ctx1 = { + fields: [ + { + fieldName: 'a', + displayType: 'String', + bsonType: 'string', + isSparse: false, + insertText: 'a', + referenceText: '$a', + }, + ], + }; + const ctx2 = { + fields: [ + { + fieldName: 'b', + displayType: 'Number', + bsonType: 'int', + isSparse: true, + insertText: 'b', + referenceText: '$b', + }, + ], + }; + + setCompletionContext('session-1', ctx1); + setCompletionContext('session-2', ctx2); + + expect(getCompletionContext('session-1')).toEqual(ctx1); + expect(getCompletionContext('session-2')).toEqual(ctx2); + }); +}); diff --git a/src/webviews/documentdbQuery/completionStore.ts b/src/webviews/documentdbQuery/completionStore.ts new file mode 100644 index 000000000..b97ed859d --- /dev/null +++ b/src/webviews/documentdbQuery/completionStore.ts @@ -0,0 +1,36 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { type FieldCompletionData } from '../../utils/json/data-api/autocomplete/toFieldCompletionItems'; + +/** + * Completion context for a single editor session. + * Holds dynamic field data fetched from the extension host after query execution. + */ +export interface CompletionContext { + fields: FieldCompletionData[]; +} + +const store = new Map(); + +/** Update field data for a session (called after query execution). */ +export function setCompletionContext(sessionId: string, context: CompletionContext): void { + store.set(sessionId, context); +} + +/** Get field data for a session. */ +export function getCompletionContext(sessionId: string): CompletionContext | undefined { + return store.get(sessionId); +} + +/** Remove a session's data (called on tab close / dispose). */ +export function clearCompletionContext(sessionId: string): void { + store.delete(sessionId); +} + +/** Clear all sessions (for testing). */ +export function clearAllCompletionContexts(): void { + store.clear(); +} diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index 23859ddb8..ca10fdc25 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -11,10 +11,12 @@ import { } from '@vscode-documentdb/documentdb-constants'; // eslint-disable-next-line import/no-internal-modules import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; +import { clearAllCompletionContexts, setCompletionContext } from './completionStore'; import { createCompletionItems, getCompletionKindForMeta, getMetaTagsForEditorType, + mapFieldToCompletionItem, mapOperatorToCompletionItem, } from './documentdbQueryCompletionProvider'; import { EditorType } from './languageConfig'; @@ -229,9 +231,14 @@ describe('documentdbQueryCompletionProvider', () => { describe('createCompletionItems', () => { const mockMonaco = createMockMonaco(); + afterEach(() => { + clearAllCompletionContexts(); + }); + test('returns items for filter context using documentdb-constants', () => { const items = createCompletionItems({ editorType: EditorType.Filter, + sessionId: undefined, range: testRange, isDollarPrefix: false, monaco: mockMonaco, @@ -253,6 +260,7 @@ describe('documentdbQueryCompletionProvider', () => { test('filter completions include query operators like $eq, $gt, $match', () => { const items = createCompletionItems({ editorType: EditorType.Filter, + sessionId: undefined, range: testRange, isDollarPrefix: false, monaco: mockMonaco, @@ -267,6 +275,7 @@ describe('documentdbQueryCompletionProvider', () => { test('filter completions include BSON constructors like ObjectId', () => { const items = createCompletionItems({ editorType: EditorType.Filter, + sessionId: undefined, range: testRange, isDollarPrefix: false, monaco: mockMonaco, @@ -281,6 +290,7 @@ describe('documentdbQueryCompletionProvider', () => { test('filter completions do NOT include JS globals like console, Math, function', () => { const items = createCompletionItems({ editorType: EditorType.Filter, + sessionId: undefined, range: testRange, isDollarPrefix: false, monaco: mockMonaco, @@ -300,6 +310,7 @@ describe('documentdbQueryCompletionProvider', () => { test('filter completions do NOT include aggregation stages', () => { const items = createCompletionItems({ editorType: EditorType.Filter, + sessionId: undefined, range: testRange, isDollarPrefix: false, monaco: mockMonaco, @@ -315,6 +326,7 @@ describe('documentdbQueryCompletionProvider', () => { test('filter completions match getFilteredCompletions count for FILTER_COMPLETION_META', () => { const items = createCompletionItems({ editorType: EditorType.Filter, + sessionId: undefined, range: testRange, isDollarPrefix: false, monaco: mockMonaco, @@ -327,6 +339,7 @@ describe('documentdbQueryCompletionProvider', () => { test('default (undefined editor type) matches filter completions', () => { const filterItems = createCompletionItems({ editorType: EditorType.Filter, + sessionId: undefined, range: testRange, isDollarPrefix: false, monaco: mockMonaco, @@ -334,6 +347,7 @@ describe('documentdbQueryCompletionProvider', () => { const defaultItems = createCompletionItems({ editorType: undefined, + sessionId: undefined, range: testRange, isDollarPrefix: false, monaco: mockMonaco, @@ -342,4 +356,158 @@ describe('documentdbQueryCompletionProvider', () => { expect(defaultItems).toHaveLength(filterItems.length); }); }); + + describe('mapFieldToCompletionItem', () => { + const mockMonaco = createMockMonaco(); + + test('maps a simple field to a CompletionItem', () => { + const field = { + fieldName: 'age', + displayType: 'Number', + bsonType: 'int', + isSparse: false, + insertText: 'age', + referenceText: '$age', + }; + + const item = mapFieldToCompletionItem(field, testRange, mockMonaco); + + expect(item.label).toBe('age'); + expect(item.kind).toBe(mockCompletionItemKind.Field); + expect(item.insertText).toBe('age'); + expect(item.detail).toBe('Number'); + expect(item.sortText).toBe('0_age'); + expect(item.range).toBe(testRange); + }); + + test('includes (sparse) indicator for sparse fields', () => { + const field = { + fieldName: 'optionalField', + displayType: 'String', + bsonType: 'string', + isSparse: true, + insertText: 'optionalField', + referenceText: '$optionalField', + }; + + const item = mapFieldToCompletionItem(field, testRange, mockMonaco); + + expect(item.detail).toBe('String (sparse)'); + }); + + test('uses pre-escaped insertText for special field names', () => { + const field = { + fieldName: 'address.city', + displayType: 'String', + bsonType: 'string', + isSparse: false, + insertText: '"address.city"', + referenceText: '$address.city', + }; + + const item = mapFieldToCompletionItem(field, testRange, mockMonaco); + + expect(item.label).toBe('address.city'); + expect(item.insertText).toBe('"address.city"'); + }); + }); + + describe('field completions via store', () => { + const mockMonaco = createMockMonaco(); + + afterEach(() => { + clearAllCompletionContexts(); + }); + + test('field completions appear when store has data', () => { + setCompletionContext('test-session', { + fields: [ + { + fieldName: 'name', + displayType: 'String', + bsonType: 'string', + isSparse: false, + insertText: 'name', + referenceText: '$name', + }, + { + fieldName: 'age', + displayType: 'Number', + bsonType: 'int', + isSparse: false, + insertText: 'age', + referenceText: '$age', + }, + ], + }); + + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: 'test-session', + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + }); + + const labels = items.map((i) => i.label); + expect(labels).toContain('name'); + expect(labels).toContain('age'); + }); + + test('field completions have sortText prefix so they sort first', () => { + setCompletionContext('test-session', { + fields: [ + { + fieldName: 'name', + displayType: 'String', + bsonType: 'string', + isSparse: false, + insertText: 'name', + referenceText: '$name', + }, + ], + }); + + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: 'test-session', + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + }); + + const fieldItem = items.find((i) => i.label === 'name'); + expect(fieldItem?.sortText).toBe('0_name'); + + // Operators should not have a sort prefix starting with 0_ + const operatorItem = items.find((i) => i.label === '$eq'); + expect(operatorItem?.sortText).toBeUndefined(); + }); + + test('empty store returns only operator completions', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: 'nonexistent-session', + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + }); + + const expected = getFilteredCompletions({ meta: [...FILTER_COMPLETION_META] }); + expect(items).toHaveLength(expected.length); + }); + + test('undefined sessionId returns only operator completions', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + }); + + const expected = getFilteredCompletions({ meta: [...FILTER_COMPLETION_META] }); + expect(items).toHaveLength(expected.length); + }); + }); }); diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts index 8c68a5fea..fcc894152 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts @@ -25,6 +25,8 @@ import { } from '@vscode-documentdb/documentdb-constants'; // eslint-disable-next-line import/no-internal-modules import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; +import { type FieldCompletionData } from '../../utils/json/data-api/autocomplete/toFieldCompletionItems'; +import { getCompletionContext } from './completionStore'; import { EditorType } from './languageConfig'; /** @@ -76,12 +78,36 @@ export function mapOperatorToCompletionItem( }; } +/** + * Maps a FieldCompletionData entry to a Monaco CompletionItem. + * + * Fields are given a sort prefix of `"0_"` so they appear before operators + * in the completion list. + */ +export function mapFieldToCompletionItem( + field: FieldCompletionData, + range: monacoEditor.IRange, + monaco: typeof monacoEditor, +): monacoEditor.languages.CompletionItem { + const sparseIndicator = field.isSparse ? ' (sparse)' : ''; + return { + label: field.fieldName, + kind: monaco.languages.CompletionItemKind.Field, + insertText: field.insertText, + detail: `${field.displayType}${sparseIndicator}`, + sortText: `0_${field.fieldName}`, + range, + }; +} + /** * Parameters for creating completion items. */ export interface CreateCompletionItemsParams { /** The editor type parsed from the model URI (undefined if URI doesn't match). */ editorType: EditorType | undefined; + /** The session ID for looking up dynamic field completions. */ + sessionId: string | undefined; /** The range to insert completions at. */ range: monacoEditor.IRange; /** Whether the cursor is immediately after a '$' character. */ @@ -116,10 +142,23 @@ export function getMetaTagsForEditorType(editorType: EditorType | undefined): re * each entry to a Monaco CompletionItem. */ export function createCompletionItems(params: CreateCompletionItemsParams): monacoEditor.languages.CompletionItem[] { - const { editorType, range, monaco } = params; + const { editorType, sessionId, range, monaco } = params; + // Static operator completions from documentdb-constants const metaTags = getMetaTagsForEditorType(editorType); const entries = getFilteredCompletions({ meta: [...metaTags] }); + const operatorItems = entries.map((entry) => mapOperatorToCompletionItem(entry, range, monaco)); + + // Dynamic field completions from the completion store + const fieldItems: monacoEditor.languages.CompletionItem[] = []; + if (sessionId) { + const context = getCompletionContext(sessionId); + if (context) { + for (const field of context.fields) { + fieldItems.push(mapFieldToCompletionItem(field, range, monaco)); + } + } + } - return entries.map((entry) => mapOperatorToCompletionItem(entry, range, monaco)); + return [...fieldItems, ...operatorItems]; } diff --git a/src/webviews/documentdbQuery/documentdbQueryHoverProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryHoverProvider.test.ts new file mode 100644 index 000000000..ca52d52e7 --- /dev/null +++ b/src/webviews/documentdbQuery/documentdbQueryHoverProvider.test.ts @@ -0,0 +1,73 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { getHoverContent } from './documentdbQueryHoverProvider'; + +describe('documentdbQueryHoverProvider', () => { + describe('getHoverContent', () => { + test('returns hover for known operator $gt', () => { + const hover = getHoverContent('$gt'); + expect(hover).not.toBeNull(); + expect(hover!.contents).toHaveLength(1); + + const content = (hover!.contents[0] as { value: string }).value; + expect(content).toContain('**$gt**'); + }); + + test('returns hover with description for $eq', () => { + const hover = getHoverContent('$eq'); + expect(hover).not.toBeNull(); + + const content = (hover!.contents[0] as { value: string }).value; + expect(content).toContain('**$eq**'); + // It should have a description line + expect(content.split('\n').length).toBeGreaterThan(1); + }); + + test('returns hover for BSON constructor ObjectId', () => { + const hover = getHoverContent('ObjectId'); + expect(hover).not.toBeNull(); + + const content = (hover!.contents[0] as { value: string }).value; + expect(content).toContain('**ObjectId**'); + }); + + test('returns null for unknown word', () => { + const hover = getHoverContent('foo'); + expect(hover).toBeNull(); + }); + + test('returns null for arbitrary text that is not an operator', () => { + const hover = getHoverContent('somethingRandom123'); + expect(hover).toBeNull(); + }); + + test('word without $ prefix matches operator when prefixed', () => { + // When cursor is on "gt" (after $ was already output), try $gt + const hover = getHoverContent('gt'); + expect(hover).not.toBeNull(); + + const content = (hover!.contents[0] as { value: string }).value; + expect(content).toContain('**$gt**'); + }); + + test('includes doc link when available', () => { + const hover = getHoverContent('$gt'); + expect(hover).not.toBeNull(); + + const content = (hover!.contents[0] as { value: string }).value; + // $gt is a well-known operator that should have a doc link + expect(content).toContain('[DocumentDB Docs]'); + }); + + test('returns hover for UUID constructor', () => { + const hover = getHoverContent('UUID'); + expect(hover).not.toBeNull(); + + const content = (hover!.contents[0] as { value: string }).value; + expect(content).toContain('**UUID**'); + }); + }); +}); diff --git a/src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts b/src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts new file mode 100644 index 000000000..d07c32951 --- /dev/null +++ b/src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts @@ -0,0 +1,50 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Hover provider logic for the `documentdb-query` language. + * + * Provides inline documentation when hovering over operators and + * BSON constructors. Uses `documentdb-constants` for the operator registry. + */ + +import { getAllCompletions } from '@vscode-documentdb/documentdb-constants'; +// eslint-disable-next-line import/no-internal-modules +import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; + +/** + * Returns hover content for a word under the cursor. + * + * Tries multiple candidates to handle cases where: + * - The cursor is on `gt` after `$` (need to try `$gt`) + * - The cursor is on `ObjectId` (try as-is) + * + * @param word - The word at the cursor position + * @returns A Monaco Hover or null if no match + */ +export function getHoverContent(word: string): monacoEditor.languages.Hover | null { + // Try with '$' prefix first (for operators where cursor lands after $) + // Then try the word as-is (for BSON constructors like ObjectId) + const candidates = word.startsWith('$') ? [word] : [`$${word}`, word]; + + const allEntries = getAllCompletions(); + + for (const candidate of candidates) { + const match = allEntries.find((e) => e.value === candidate); + if (match) { + const lines: string[] = [`**${match.value}**`]; + if (match.description) { + lines.push('', match.description); + } + if (match.link) { + lines.push('', `[DocumentDB Docs](${match.link})`); + } + return { + contents: [{ value: lines.join('\n') }], + }; + } + } + return null; +} diff --git a/src/webviews/documentdbQuery/documentdbQueryValidator.test.ts b/src/webviews/documentdbQuery/documentdbQueryValidator.test.ts new file mode 100644 index 000000000..ad741973a --- /dev/null +++ b/src/webviews/documentdbQuery/documentdbQueryValidator.test.ts @@ -0,0 +1,157 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { levenshteinDistance, validateExpression } from './documentdbQueryValidator'; + +describe('documentdbQueryValidator', () => { + describe('validateExpression', () => { + test('valid expression { age: { $gt: 25 } } produces no diagnostics', () => { + const diagnostics = validateExpression('{ age: { $gt: 25 } }'); + expect(diagnostics).toHaveLength(0); + }); + + test('valid expression with multiple fields produces no diagnostics', () => { + const diagnostics = validateExpression('{ name: "Alice", age: 30 }'); + expect(diagnostics).toHaveLength(0); + }); + + test('valid expression with BSON constructor produces no diagnostics', () => { + const diagnostics = validateExpression('{ _id: ObjectId("507f1f77bcf86cd799439011") }'); + expect(diagnostics).toHaveLength(0); + }); + + test('valid expression with UUID constructor produces no diagnostics', () => { + const diagnostics = validateExpression('{ id: UUID("123e4567-e89b-12d3-a456-426614174000") }'); + expect(diagnostics).toHaveLength(0); + }); + + test('valid expression with nested objects produces no diagnostics', () => { + const diagnostics = validateExpression('{ a: { b: { c: 1 } } }'); + expect(diagnostics).toHaveLength(0); + }); + + test('syntax error { age: { $gt: } produces error diagnostic', () => { + const diagnostics = validateExpression('{ age: { $gt: } }'); + expect(diagnostics.length).toBeGreaterThan(0); + + const errorDiag = diagnostics.find((d) => d.severity === 'error'); + expect(errorDiag).toBeDefined(); + }); + + test('syntax error with unclosed brace produces error diagnostic', () => { + const diagnostics = validateExpression('{ age: 25'); + expect(diagnostics.length).toBeGreaterThan(0); + expect(diagnostics[0].severity).toBe('error'); + }); + + test('typo UUUD("...") produces warning "Did you mean UUID?"', () => { + const diagnostics = validateExpression('{ id: UUUD("abc") }'); + + const warnings = diagnostics.filter((d) => d.severity === 'warning'); + expect(warnings.length).toBeGreaterThan(0); + expect(warnings[0].message).toContain('UUID'); + expect(warnings[0].message).toContain('Did you mean'); + }); + + test('typo Objected produces warning "Did you mean ObjectId?"', () => { + const diagnostics = validateExpression('{ id: ObjctId("abc") }'); + + const warnings = diagnostics.filter((d) => d.severity === 'warning'); + expect(warnings.length).toBeGreaterThan(0); + expect(warnings[0].message).toContain('ObjectId'); + }); + + test('unknown identifier foo used as function is not flagged if not near BSON constructor', () => { + // "foo" is not close to any BSON constructor name (Levenshtein > 2) + const diagnostics = validateExpression('{ id: foo("abc") }'); + const warnings = diagnostics.filter((d) => d.severity === 'warning'); + expect(warnings).toHaveLength(0); + }); + + test('unknown identifier as field name is not flagged', () => { + // Field names (non-function identifiers) should never produce diagnostics + const diagnostics = validateExpression('{ unknownField: 1 }'); + expect(diagnostics).toHaveLength(0); + }); + + test('empty string produces no diagnostics', () => { + const diagnostics = validateExpression(''); + expect(diagnostics).toHaveLength(0); + }); + + test('whitespace-only string produces no diagnostics', () => { + const diagnostics = validateExpression(' '); + expect(diagnostics).toHaveLength(0); + }); + + test('valid expression with Math.min produces no diagnostics', () => { + const diagnostics = validateExpression('{ rating: Math.min(1.7, 2) }'); + expect(diagnostics).toHaveLength(0); + }); + + test('valid expression with ISODate constructor produces no diagnostics', () => { + const diagnostics = validateExpression('{ ts: ISODate("2024-01-01") }'); + expect(diagnostics).toHaveLength(0); + }); + + test('valid expression with MinKey produces no diagnostics', () => { + const diagnostics = validateExpression('{ start: MinKey() }'); + expect(diagnostics).toHaveLength(0); + }); + + test('valid expression with MaxKey produces no diagnostics', () => { + const diagnostics = validateExpression('{ end: MaxKey() }'); + expect(diagnostics).toHaveLength(0); + }); + + test('valid expression with regex produces no diagnostics', () => { + const diagnostics = validateExpression('{ name: /^alice/i }'); + expect(diagnostics).toHaveLength(0); + }); + + test('valid expression with array produces no diagnostics', () => { + const diagnostics = validateExpression('{ tags: { $in: ["a", "b"] } }'); + expect(diagnostics).toHaveLength(0); + }); + + test('diagnostics have valid offsets within the input range', () => { + const code = '{ age: { $gt: } }'; + const diagnostics = validateExpression(code); + + for (const d of diagnostics) { + expect(d.startOffset).toBeGreaterThanOrEqual(0); + expect(d.endOffset).toBeLessThanOrEqual(code.length); + expect(d.startOffset).toBeLessThanOrEqual(d.endOffset); + } + }); + }); + + describe('levenshteinDistance', () => { + test('identical strings have distance 0', () => { + expect(levenshteinDistance('UUID', 'UUID')).toBe(0); + }); + + test('one character difference has distance 1', () => { + expect(levenshteinDistance('UUID', 'UUUD')).toBe(1); + }); + + test('two character difference has distance 2', () => { + expect(levenshteinDistance('ObjectId', 'ObjctId')).toBeLessThanOrEqual(2); + }); + + test('completely different strings have high distance', () => { + expect(levenshteinDistance('UUID', 'something')).toBeGreaterThan(2); + }); + + test('empty string vs non-empty has distance equal to length', () => { + expect(levenshteinDistance('', 'abc')).toBe(3); + expect(levenshteinDistance('abc', '')).toBe(3); + }); + + test('both empty strings have distance 0', () => { + expect(levenshteinDistance('', '')).toBe(0); + }); + }); +}); diff --git a/src/webviews/documentdbQuery/documentdbQueryValidator.ts b/src/webviews/documentdbQuery/documentdbQueryValidator.ts new file mode 100644 index 000000000..0a5c71a9b --- /dev/null +++ b/src/webviews/documentdbQuery/documentdbQueryValidator.ts @@ -0,0 +1,227 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Validator for `documentdb-query` editor content. + * + * Uses `acorn` to parse the expression and `acorn-walk` to traverse the AST. + * Produces diagnostics for: + * - Syntax errors (severity: error) + * - Near-miss BSON constructor typos (severity: warning) + * + * This module is pure and testable — it does not depend on Monaco. + * The mapping from Diagnostic[] to Monaco markers happens in the editor mount handler. + */ + +import { getAllCompletions } from '@vscode-documentdb/documentdb-constants'; +import * as acorn from 'acorn'; +import * as walk from 'acorn-walk'; + +/** + * A diagnostic produced by the validator. + * Offsets are 0-based character positions in the original (unwrapped) input. + */ +export interface Diagnostic { + /** 0-based start character offset in the original input */ + startOffset: number; + /** 0-based end character offset in the original input */ + endOffset: number; + severity: 'error' | 'warning' | 'info'; + message: string; +} + +/** + * Known identifiers that should NOT be flagged as typos. + * These are globals available in shell-bson-parser's sandbox. + */ +const KNOWN_GLOBALS = new Set([ + // BSON constructors (populated dynamically below) + // JS globals available in the sandbox + 'Math', + 'Date', + 'ISODate', + 'RegExp', + 'Infinity', + 'NaN', + 'undefined', + 'true', + 'false', + 'null', + 'Map', + 'Symbol', + // Common JS builtins that might appear in expressions + 'Number', + 'String', + 'Boolean', + 'Array', + 'Object', + 'parseInt', + 'parseFloat', + 'isNaN', + 'isFinite', +]); + +// Add all BSON constructors from documentdb-constants +let bsonConstructorsLoaded = false; + +function ensureBsonConstructors(): void { + if (bsonConstructorsLoaded) return; + bsonConstructorsLoaded = true; + + const allEntries = getAllCompletions(); + for (const entry of allEntries) { + if (entry.meta === 'bson') { + KNOWN_GLOBALS.add(entry.value); + } + } +} + +/** + * Computes the Levenshtein edit distance between two strings. + * Used for near-miss detection of BSON constructor typos. + */ +export function levenshteinDistance(a: string, b: string): number { + const m = a.length; + const n = b.length; + + if (m === 0) return n; + if (n === 0) return m; + + const dp: number[][] = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0) as number[]); + + for (let i = 0; i <= m; i++) dp[i][0] = i; + for (let j = 0; j <= n; j++) dp[0][j] = j; + + for (let i = 1; i <= m; i++) { + for (let j = 1; j <= n; j++) { + if (a[i - 1] === b[j - 1]) { + dp[i][j] = dp[i - 1][j - 1]; + } else { + dp[i][j] = 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]); + } + } + } + + return dp[m][n]; +} + +/** + * Finds the closest BSON constructor name to a given identifier. + * Returns the match and distance if within threshold, otherwise undefined. + */ +function findNearMissBsonConstructor(name: string): { match: string; distance: number } | undefined { + ensureBsonConstructors(); + + const allEntries = getAllCompletions(); + let bestMatch: string | undefined; + let bestDistance = Infinity; + + for (const entry of allEntries) { + if (entry.meta === 'bson') { + const dist = levenshteinDistance(name.toLowerCase(), entry.value.toLowerCase()); + if (dist <= 2 && dist < bestDistance) { + bestDistance = dist; + bestMatch = entry.value; + } + } + } + + if (bestMatch !== undefined && bestDistance <= 2) { + return { match: bestMatch, distance: bestDistance }; + } + + return undefined; +} + +/** + * Validates a documentdb-query expression and returns diagnostics. + * + * @param code - The expression text from the editor (e.g., `{ age: { $gt: 25 } }`) + * @returns Array of diagnostics (empty if the expression is valid) + */ +export function validateExpression(code: string): Diagnostic[] { + ensureBsonConstructors(); + + const trimmed = code.trim(); + if (trimmed.length === 0) { + return []; + } + + const diagnostics: Diagnostic[] = []; + + // Wrap in parentheses for acorn to parse as expression + // The offset adjustment accounts for the added '(' character + const wrapped = `(${code})`; + + let ast: acorn.Node; + try { + ast = acorn.parseExpressionAt(wrapped, 0, { + ecmaVersion: 'latest', + sourceType: 'module', + }); + } catch (error) { + if (error instanceof SyntaxError) { + const syntaxError = error as SyntaxError & { pos?: number; loc?: { line: number; column: number } }; + // Adjust offset for the wrapping parenthesis + const pos = syntaxError.pos !== undefined ? syntaxError.pos - 1 : 0; + const startOffset = Math.max(0, Math.min(pos, code.length)); + const endOffset = Math.min(startOffset + 1, code.length); + + diagnostics.push({ + startOffset, + endOffset, + severity: 'error', + message: syntaxError.message.replace(/\(\d+:\d+\)/, '').trim(), + }); + } + return diagnostics; + } + + // Walk the AST to check identifiers + try { + walk.simple(ast, { + Identifier(node: acorn.Node & { name: string }) { + const name = node.name; + + // Skip known globals and common identifiers + if (KNOWN_GLOBALS.has(name)) { + return; + } + + // Don't flag field names — only flag function call identifiers + // that look like BSON constructor typos + }, + CallExpression(node: acorn.Node & { callee: acorn.Node & { name?: string; type: string } }) { + if (node.callee.type === 'Identifier' && node.callee.name) { + const name = node.callee.name; + + // If it's a known global, skip + if (KNOWN_GLOBALS.has(name)) { + return; + } + + // Check if it's a near-miss of a BSON constructor + const nearMiss = findNearMissBsonConstructor(name); + if (nearMiss) { + // Adjust offset for wrapping parenthesis + const startOffset = node.callee.start - 1; + const endOffset = node.callee.end - 1; + + diagnostics.push({ + startOffset, + endOffset, + severity: 'warning', + message: `Did you mean '${nearMiss.match}'?`, + }); + } + } + }, + }); + } catch { + // If walking fails, just return syntax diagnostics we already have + } + + return diagnostics; +} diff --git a/src/webviews/documentdbQuery/index.ts b/src/webviews/documentdbQuery/index.ts index d36b6b619..535d659cc 100644 --- a/src/webviews/documentdbQuery/index.ts +++ b/src/webviews/documentdbQuery/index.ts @@ -22,5 +22,7 @@ * ``` */ +export { clearCompletionContext, getCompletionContext, setCompletionContext } from './completionStore'; +export { validateExpression, type Diagnostic } from './documentdbQueryValidator'; export { EditorType, LANGUAGE_ID, URI_SCHEME, buildEditorUri, parseEditorUri } from './languageConfig'; export { registerDocumentDBQueryLanguage } from './registerLanguage'; diff --git a/src/webviews/documentdbQuery/registerLanguage.ts b/src/webviews/documentdbQuery/registerLanguage.ts index 832ef1473..0abe4b50f 100644 --- a/src/webviews/documentdbQuery/registerLanguage.ts +++ b/src/webviews/documentdbQuery/registerLanguage.ts @@ -10,6 +10,7 @@ * 1. Registers the language ID with Monaco * 2. Imports the JavaScript Monarch tokenizer for syntax highlighting * 3. Registers a custom CompletionItemProvider scoped to `documentdb-query` + * 4. Registers a HoverProvider for operator/constructor documentation * * The JS tokenizer provides correct highlighting for: * - Unquoted identifiers: `{ name: 1 }` @@ -26,6 +27,7 @@ // eslint-disable-next-line import/no-internal-modules import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; import { createCompletionItems } from './documentdbQueryCompletionProvider'; +import { getHoverContent } from './documentdbQueryHoverProvider'; import { LANGUAGE_ID, parseEditorUri } from './languageConfig'; /** Tracks whether the language has already been registered (idempotent guard). */ @@ -71,7 +73,7 @@ export async function registerDocumentDBQueryLanguage(monaco: typeof monacoEdito // Get the word at the current position for range calculation const wordInfo = model.getWordUntilPosition(position); - const range: monacoEditor.IRange = { + let range: monacoEditor.IRange = { startLineNumber: position.lineNumber, endLineNumber: position.lineNumber, startColumn: wordInfo.startColumn, @@ -79,12 +81,20 @@ export async function registerDocumentDBQueryLanguage(monaco: typeof monacoEdito }; // Check if cursor is preceded by '$' (for operator completions) + // Monaco's getWordUntilPosition() does not treat '$' as part of a word boundary. + // When the user types '$g', wordInfo.startColumn points to 'g', not '$'. + // Without this fix, selecting '$gt' would insert '$$gt' (double dollar). const lineContent = model.getLineContent(position.lineNumber); const charBefore = lineContent[wordInfo.startColumn - 2]; // -2 because columns are 1-based + if (charBefore === '$') { + range = { ...range, startColumn: range.startColumn - 1 }; + } + // Build completion items based on context const items = createCompletionItems({ editorType: parsed?.editorType, + sessionId: parsed?.sessionId, range, isDollarPrefix: charBefore === '$', monaco, @@ -94,6 +104,35 @@ export async function registerDocumentDBQueryLanguage(monaco: typeof monacoEdito }, }); + // Step 5: Register the hover provider + monaco.languages.registerHoverProvider(LANGUAGE_ID, { + provideHover: ( + model: monacoEditor.editor.ITextModel, + position: monacoEditor.Position, + ): monacoEditor.languages.Hover | null => { + const wordAtPosition = model.getWordAtPosition(position); + if (!wordAtPosition) { + return null; + } + + const hover = getHoverContent(wordAtPosition.word); + if (!hover) { + return null; + } + + // Set the range for the hover highlight + return { + ...hover, + range: { + startLineNumber: position.lineNumber, + endLineNumber: position.lineNumber, + startColumn: wordAtPosition.startColumn, + endColumn: wordAtPosition.endColumn, + }, + }; + }, + }); + isRegistered = true; } From e8989d5069dd5f11d5b8dc9ec7532f092d83c1d9 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Mar 2026 14:20:48 +0000 Subject: [PATCH 058/128] feat: Enhance documentdb-query validation with additional tests and identifier checks --- .../documentdbQueryValidator.test.ts | 45 +++++++ .../documentdbQueryValidator.ts | 115 ++++++++++++++++-- 2 files changed, 150 insertions(+), 10 deletions(-) diff --git a/src/webviews/documentdbQuery/documentdbQueryValidator.test.ts b/src/webviews/documentdbQuery/documentdbQueryValidator.test.ts index ad741973a..756e077a8 100644 --- a/src/webviews/documentdbQuery/documentdbQueryValidator.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryValidator.test.ts @@ -76,6 +76,13 @@ describe('documentdbQueryValidator', () => { expect(diagnostics).toHaveLength(0); }); + test('unknown field name ___id is not flagged (field validation is out of scope)', () => { + // The validator does not validate field names against the schema. + // That requires integration with the completion store (known fields). + const diagnostics = validateExpression('{ ___id: 1 }'); + expect(diagnostics).toHaveLength(0); + }); + test('empty string produces no diagnostics', () => { const diagnostics = validateExpression(''); expect(diagnostics).toHaveLength(0); @@ -91,6 +98,44 @@ describe('documentdbQueryValidator', () => { expect(diagnostics).toHaveLength(0); }); + test('valid expression with Date.now produces no diagnostics', () => { + const diagnostics = validateExpression('{ ts: Date.now() }'); + expect(diagnostics).toHaveLength(0); + }); + + test('typo Daate.now() produces warning "Did you mean Date?"', () => { + const diagnostics = validateExpression('{ _id: Daate.now() }'); + + const warnings = diagnostics.filter((d) => d.severity === 'warning'); + expect(warnings.length).toBeGreaterThan(0); + expect(warnings[0].message).toContain('Date'); + expect(warnings[0].message).toContain('Did you mean'); + }); + + test('typo Maht.min() produces warning "Did you mean Math?"', () => { + const diagnostics = validateExpression('{ val: Maht.min(1, 2) }'); + + const warnings = diagnostics.filter((d) => d.severity === 'warning'); + expect(warnings.length).toBeGreaterThan(0); + expect(warnings[0].message).toContain('Math'); + }); + + test('typo Nubmer.parseInt() produces warning "Did you mean Number?"', () => { + const diagnostics = validateExpression('{ x: Nubmer.parseInt("42") }'); + + const warnings = diagnostics.filter((d) => d.severity === 'warning'); + expect(warnings.length).toBeGreaterThan(0); + expect(warnings[0].message).toContain('Number'); + }); + + test('Date.nodw() does NOT produce a warning (method validation is out of scope)', () => { + // We validate the object (Date) but not individual method names. + // Date is a known global, so no warning. The .nodw() method name + // is not validated — that would require method-level knowledge. + const diagnostics = validateExpression('{ _id: Date.nodw() }'); + expect(diagnostics).toHaveLength(0); + }); + test('valid expression with ISODate constructor produces no diagnostics', () => { const diagnostics = validateExpression('{ ts: ISODate("2024-01-01") }'); expect(diagnostics).toHaveLength(0); diff --git a/src/webviews/documentdbQuery/documentdbQueryValidator.ts b/src/webviews/documentdbQuery/documentdbQueryValidator.ts index 0a5c71a9b..ed31bf114 100644 --- a/src/webviews/documentdbQuery/documentdbQueryValidator.ts +++ b/src/webviews/documentdbQuery/documentdbQueryValidator.ts @@ -108,16 +108,20 @@ export function levenshteinDistance(a: string, b: string): number { } /** - * Finds the closest BSON constructor name to a given identifier. + * Finds the closest known identifier (BSON constructor or known global) to a given name. * Returns the match and distance if within threshold, otherwise undefined. + * + * Searches both BSON constructor entries (from documentdb-constants) and + * KNOWN_GLOBALS (Date, Math, RegExp, etc.) for near-misses. */ -function findNearMissBsonConstructor(name: string): { match: string; distance: number } | undefined { +function findNearMissKnownIdentifier(name: string): { match: string; distance: number } | undefined { ensureBsonConstructors(); - const allEntries = getAllCompletions(); let bestMatch: string | undefined; let bestDistance = Infinity; + // Check against BSON constructors + const allEntries = getAllCompletions(); for (const entry of allEntries) { if (entry.meta === 'bson') { const dist = levenshteinDistance(name.toLowerCase(), entry.value.toLowerCase()); @@ -128,6 +132,15 @@ function findNearMissBsonConstructor(name: string): { match: string; distance: n } } + // Check against KNOWN_GLOBALS (Date, Math, RegExp, Number, etc.) + for (const known of KNOWN_GLOBALS) { + const dist = levenshteinDistance(name.toLowerCase(), known.toLowerCase()); + if (dist <= 2 && dist < bestDistance) { + bestDistance = dist; + bestMatch = known; + } + } + if (bestMatch !== undefined && bestDistance <= 2) { return { match: bestMatch, distance: bestDistance }; } @@ -146,9 +159,12 @@ export function validateExpression(code: string): Diagnostic[] { const trimmed = code.trim(); if (trimmed.length === 0) { + console.debug('[documentdb-query validator] Empty input, skipping validation'); return []; } + console.debug('[documentdb-query validator] Validating expression:', JSON.stringify(code)); + const diagnostics: Diagnostic[] = []; // Wrap in parentheses for acorn to parse as expression @@ -161,6 +177,10 @@ export function validateExpression(code: string): Diagnostic[] { ecmaVersion: 'latest', sourceType: 'module', }); + console.debug( + '[documentdb-query validator] Parsed successfully, AST type:', + (ast as acorn.Node & { type: string }).type, + ); } catch (error) { if (error instanceof SyntaxError) { const syntaxError = error as SyntaxError & { pos?: number; loc?: { line: number; column: number } }; @@ -169,13 +189,22 @@ export function validateExpression(code: string): Diagnostic[] { const startOffset = Math.max(0, Math.min(pos, code.length)); const endOffset = Math.min(startOffset + 1, code.length); + const message = syntaxError.message.replace(/\(\d+:\d+\)/, '').trim(); + console.debug( + '[documentdb-query validator] Syntax error at offset %d–%d: %s', + startOffset, + endOffset, + message, + ); + diagnostics.push({ startOffset, endOffset, severity: 'error', - message: syntaxError.message.replace(/\(\d+:\d+\)/, '').trim(), + message, }); } + console.debug('[documentdb-query validator] Returning %d diagnostic(s) after parse error', diagnostics.length); return diagnostics; } @@ -191,37 +220,103 @@ export function validateExpression(code: string): Diagnostic[] { } // Don't flag field names — only flag function call identifiers - // that look like BSON constructor typos + // that look like BSON constructor typos. + // CallExpression and MemberExpression handlers below handle + // identifiers in call/member positions. }, - CallExpression(node: acorn.Node & { callee: acorn.Node & { name?: string; type: string } }) { + CallExpression( + node: acorn.Node & { + callee: acorn.Node & { + name?: string; + type: string; + object?: acorn.Node & { name?: string; type: string }; + }; + }, + ) { + // Case 1: Direct call — e.g., ObjctId("abc") if (node.callee.type === 'Identifier' && node.callee.name) { const name = node.callee.name; - // If it's a known global, skip if (KNOWN_GLOBALS.has(name)) { return; } - // Check if it's a near-miss of a BSON constructor - const nearMiss = findNearMissBsonConstructor(name); + const nearMiss = findNearMissKnownIdentifier(name); if (nearMiss) { - // Adjust offset for wrapping parenthesis const startOffset = node.callee.start - 1; const endOffset = node.callee.end - 1; + console.debug( + '[documentdb-query validator] Near-miss: "%s" at offset %d–%d → did you mean "%s"? (distance: %d)', + name, + startOffset, + endOffset, + nearMiss.match, + nearMiss.distance, + ); + + diagnostics.push({ + startOffset, + endOffset, + severity: 'warning', + message: `Did you mean '${nearMiss.match}'?`, + }); + } else { + console.debug( + '[documentdb-query validator] Unknown call: "%s" (no near-miss match)', + name, + ); + } + } + + // Case 2: Member call — e.g., Daate.now(), Maht.min() + // Check if the object is an unknown identifier that's a near-miss + if ( + node.callee.type === 'MemberExpression' && + node.callee.object && + node.callee.object.type === 'Identifier' && + node.callee.object.name + ) { + const objName = node.callee.object.name; + + if (KNOWN_GLOBALS.has(objName)) { + return; + } + + const nearMiss = findNearMissKnownIdentifier(objName); + if (nearMiss) { + const startOffset = node.callee.object.start - 1; + const endOffset = node.callee.object.end - 1; + + console.debug( + '[documentdb-query validator] Near-miss (member object): "%s" at offset %d–%d → did you mean "%s"? (distance: %d)', + objName, + startOffset, + endOffset, + nearMiss.match, + nearMiss.distance, + ); + diagnostics.push({ startOffset, endOffset, severity: 'warning', message: `Did you mean '${nearMiss.match}'?`, }); + } else { + console.debug( + '[documentdb-query validator] Unknown member call object: "%s" (no near-miss match)', + objName, + ); } } }, }); } catch { // If walking fails, just return syntax diagnostics we already have + console.debug('[documentdb-query validator] AST walk failed, returning syntax diagnostics only'); } + console.debug('[documentdb-query validator] Returning %d diagnostic(s):', diagnostics.length, diagnostics); return diagnostics; } From ce2c04a98fed874019ddb46f0a86e875ac187edf Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Mar 2026 14:20:55 +0000 Subject: [PATCH 059/128] feat: Implement type-aware operator sorting for documentdb-query completion items --- .../documentdbQueryCompletionProvider.test.ts | 235 ++++++++++++++++++ .../documentdbQueryCompletionProvider.ts | 45 +++- 2 files changed, 278 insertions(+), 2 deletions(-) diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index ca10fdc25..f62a93edd 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -16,6 +16,7 @@ import { createCompletionItems, getCompletionKindForMeta, getMetaTagsForEditorType, + getOperatorSortPrefix, mapFieldToCompletionItem, mapOperatorToCompletionItem, } from './documentdbQueryCompletionProvider'; @@ -510,4 +511,238 @@ describe('documentdbQueryCompletionProvider', () => { expect(items).toHaveLength(expected.length); }); }); + + describe('getOperatorSortPrefix', () => { + test('returns undefined when no fieldBsonTypes provided', () => { + const entry: OperatorEntry = { + value: '$eq', + meta: 'query:comparison', + description: 'Equals', + }; + expect(getOperatorSortPrefix(entry, undefined)).toBeUndefined(); + expect(getOperatorSortPrefix(entry, [])).toBeUndefined(); + }); + + test('returns "1_" for universal operator (no applicableBsonTypes)', () => { + const entry: OperatorEntry = { + value: '$eq', + meta: 'query:comparison', + description: 'Equals', + }; + expect(getOperatorSortPrefix(entry, ['string'])).toBe('1_'); + }); + + test('returns "0_" for type-relevant operator (applicableBsonTypes matches)', () => { + const entry: OperatorEntry = { + value: '$regex', + meta: 'query:evaluation', + description: 'Regex match', + applicableBsonTypes: ['string'], + }; + expect(getOperatorSortPrefix(entry, ['string'])).toBe('0_'); + }); + + test('returns "2_" for non-matching operator (applicableBsonTypes does not match)', () => { + const entry: OperatorEntry = { + value: '$regex', + meta: 'query:evaluation', + description: 'Regex match', + applicableBsonTypes: ['string'], + }; + expect(getOperatorSortPrefix(entry, ['int'])).toBe('2_'); + }); + + test('handles polymorphic fields (multiple bsonTypes)', () => { + const regexEntry: OperatorEntry = { + value: '$regex', + meta: 'query:evaluation', + description: 'Regex match', + applicableBsonTypes: ['string'], + }; + // Field is sometimes string, sometimes int — $regex should match + expect(getOperatorSortPrefix(regexEntry, ['int', 'string'])).toBe('0_'); + }); + + test('returns "2_" when operator types and field types have no intersection', () => { + const sizeEntry: OperatorEntry = { + value: '$size', + meta: 'query:array', + description: 'Array size', + applicableBsonTypes: ['array'], + }; + expect(getOperatorSortPrefix(sizeEntry, ['string', 'int'])).toBe('2_'); + }); + }); + + describe('type-aware operator sorting in mapOperatorToCompletionItem', () => { + const mockMonaco = createMockMonaco(); + + test('sortText is undefined when no fieldBsonTypes provided', () => { + const entry: OperatorEntry = { + value: '$eq', + meta: 'query:comparison', + description: 'Equals', + }; + const item = mapOperatorToCompletionItem(entry, testRange, mockMonaco); + expect(item.sortText).toBeUndefined(); + }); + + test('sortText is undefined when empty fieldBsonTypes provided', () => { + const entry: OperatorEntry = { + value: '$eq', + meta: 'query:comparison', + description: 'Equals', + }; + const item = mapOperatorToCompletionItem(entry, testRange, mockMonaco, []); + expect(item.sortText).toBeUndefined(); + }); + + test('universal operator gets "1_" prefix when fieldBsonTypes provided', () => { + const entry: OperatorEntry = { + value: '$eq', + meta: 'query:comparison', + description: 'Equals', + }; + const item = mapOperatorToCompletionItem(entry, testRange, mockMonaco, ['int']); + expect(item.sortText).toBe('1_$eq'); + }); + + test('type-relevant operator gets "0_" prefix', () => { + const entry: OperatorEntry = { + value: '$regex', + meta: 'query:evaluation', + description: 'Regex match', + applicableBsonTypes: ['string'], + }; + const item = mapOperatorToCompletionItem(entry, testRange, mockMonaco, ['string']); + expect(item.sortText).toBe('0_$regex'); + }); + + test('non-matching operator gets "2_" prefix (demoted, not hidden)', () => { + const entry: OperatorEntry = { + value: '$regex', + meta: 'query:evaluation', + description: 'Regex match', + applicableBsonTypes: ['string'], + }; + const item = mapOperatorToCompletionItem(entry, testRange, mockMonaco, ['int']); + expect(item.sortText).toBe('2_$regex'); + }); + }); + + describe('type-aware sorting via createCompletionItems', () => { + const mockMonaco = createMockMonaco(); + + afterEach(() => { + clearAllCompletionContexts(); + }); + + test('without fieldBsonTypes, operators have no sortText (backward compatible)', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + }); + + const regexItem = items.find((i) => i.label === '$regex'); + expect(regexItem?.sortText).toBeUndefined(); + + const eqItem = items.find((i) => i.label === '$eq'); + expect(eqItem?.sortText).toBeUndefined(); + }); + + test('with fieldBsonTypes=["string"], $regex gets "0_" and $size gets "2_"', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + fieldBsonTypes: ['string'], + }); + + const regexItem = items.find((i) => i.label === '$regex'); + expect(regexItem?.sortText).toBe('0_$regex'); + + const sizeItem = items.find((i) => i.label === '$size'); + expect(sizeItem?.sortText).toBe('2_$size'); + + // Universal operators like $eq get "1_" + const eqItem = items.find((i) => i.label === '$eq'); + expect(eqItem?.sortText).toBe('1_$eq'); + }); + + test('with fieldBsonTypes=["int"], $regex gets "2_" (demoted, still present)', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + fieldBsonTypes: ['int'], + }); + + const labels = items.map((i) => i.label); + // $regex is still in the list, just demoted + expect(labels).toContain('$regex'); + + const regexItem = items.find((i) => i.label === '$regex'); + expect(regexItem?.sortText).toBe('2_$regex'); + + // Bitwise operators should match int + const bitsAllSetItem = items.find((i) => i.label === '$bitsAllSet'); + expect(bitsAllSetItem?.sortText).toBe('0_$bitsAllSet'); + }); + + test('all operators still present regardless of fieldBsonTypes', () => { + const itemsWithoutType = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + }); + + const itemsWithType = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + fieldBsonTypes: ['int'], + }); + + // Same number of items — nothing filtered out + expect(itemsWithType).toHaveLength(itemsWithoutType.length); + }); + + test('field items still get "0_" prefix even when fieldBsonTypes is set', () => { + setCompletionContext('test-session', { + fields: [ + { + fieldName: 'age', + displayType: 'Number', + bsonType: 'int', + isSparse: false, + insertText: 'age', + referenceText: '$age', + }, + ], + }); + + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: 'test-session', + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + fieldBsonTypes: ['int'], + }); + + const fieldItem = items.find((i) => i.label === 'age'); + expect(fieldItem?.sortText).toBe('0_age'); + }); + }); }); diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts index fcc894152..c3bc4e4ba 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts @@ -50,18 +50,52 @@ export function getCompletionKindForMeta( return kinds.Text; } +/** + * Computes a sortText prefix for an operator based on its type relevance + * to the given field BSON types. + * + * - `"0_"` — Type-relevant: operator's `applicableBsonTypes` intersects with `fieldBsonTypes` + * - `"1_"` — Universal: operator has no `applicableBsonTypes` (works on any type) + * - `"2_"` — Non-matching: operator's `applicableBsonTypes` is set but doesn't match + * + * Returns `undefined` when no field type info is available (no sorting override). + */ +export function getOperatorSortPrefix( + entry: OperatorEntry, + fieldBsonTypes: readonly string[] | undefined, +): string | undefined { + if (!fieldBsonTypes || fieldBsonTypes.length === 0) { + return undefined; + } + + if (!entry.applicableBsonTypes || entry.applicableBsonTypes.length === 0) { + // Universal operator — no type restriction + return '1_'; + } + + const hasMatch = entry.applicableBsonTypes.some((t) => fieldBsonTypes.includes(t)); + return hasMatch ? '0_' : '2_'; +} + /** * Maps an OperatorEntry from documentdb-constants to a Monaco CompletionItem. * * This is a pure function with no side effects — safe for unit testing * without a Monaco runtime. + * + * @param entry - the operator entry to map + * @param range - the insertion range + * @param monaco - the Monaco API + * @param fieldBsonTypes - optional BSON types of the field for type-aware sorting */ export function mapOperatorToCompletionItem( entry: OperatorEntry, range: monacoEditor.IRange, monaco: typeof monacoEditor, + fieldBsonTypes?: readonly string[], ): monacoEditor.languages.CompletionItem { const hasSnippet = !!entry.snippet; + const sortPrefix = getOperatorSortPrefix(entry, fieldBsonTypes); return { label: entry.value, @@ -74,6 +108,7 @@ export function mapOperatorToCompletionItem( value: `[DocumentDB Docs](${entry.link})`, } : undefined, + sortText: sortPrefix ? `${sortPrefix}${entry.value}` : undefined, range, }; } @@ -114,6 +149,12 @@ export interface CreateCompletionItemsParams { isDollarPrefix: boolean; /** The Monaco editor API. */ monaco: typeof monacoEditor; + /** + * Optional BSON types of the field the cursor is operating on. + * When provided, operators are sorted by type relevance: + * type-matching first, universal second, non-matching last. + */ + fieldBsonTypes?: readonly string[]; } /** @@ -142,12 +183,12 @@ export function getMetaTagsForEditorType(editorType: EditorType | undefined): re * each entry to a Monaco CompletionItem. */ export function createCompletionItems(params: CreateCompletionItemsParams): monacoEditor.languages.CompletionItem[] { - const { editorType, sessionId, range, monaco } = params; + const { editorType, sessionId, range, monaco, fieldBsonTypes } = params; // Static operator completions from documentdb-constants const metaTags = getMetaTagsForEditorType(editorType); const entries = getFilteredCompletions({ meta: [...metaTags] }); - const operatorItems = entries.map((entry) => mapOperatorToCompletionItem(entry, range, monaco)); + const operatorItems = entries.map((entry) => mapOperatorToCompletionItem(entry, range, monaco, fieldBsonTypes)); // Dynamic field completions from the completion store const fieldItems: monacoEditor.languages.CompletionItem[] = []; From 3b90d6ee1177f4238d32b69af6509bd45c28c482 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Mar 2026 14:24:05 +0000 Subject: [PATCH 060/128] refactor: Remove debug logging from documentdb-query validation function --- .../documentdbQueryValidator.ts | 47 ------------------- 1 file changed, 47 deletions(-) diff --git a/src/webviews/documentdbQuery/documentdbQueryValidator.ts b/src/webviews/documentdbQuery/documentdbQueryValidator.ts index ed31bf114..2b3c4c124 100644 --- a/src/webviews/documentdbQuery/documentdbQueryValidator.ts +++ b/src/webviews/documentdbQuery/documentdbQueryValidator.ts @@ -159,12 +159,9 @@ export function validateExpression(code: string): Diagnostic[] { const trimmed = code.trim(); if (trimmed.length === 0) { - console.debug('[documentdb-query validator] Empty input, skipping validation'); return []; } - console.debug('[documentdb-query validator] Validating expression:', JSON.stringify(code)); - const diagnostics: Diagnostic[] = []; // Wrap in parentheses for acorn to parse as expression @@ -177,10 +174,6 @@ export function validateExpression(code: string): Diagnostic[] { ecmaVersion: 'latest', sourceType: 'module', }); - console.debug( - '[documentdb-query validator] Parsed successfully, AST type:', - (ast as acorn.Node & { type: string }).type, - ); } catch (error) { if (error instanceof SyntaxError) { const syntaxError = error as SyntaxError & { pos?: number; loc?: { line: number; column: number } }; @@ -190,13 +183,6 @@ export function validateExpression(code: string): Diagnostic[] { const endOffset = Math.min(startOffset + 1, code.length); const message = syntaxError.message.replace(/\(\d+:\d+\)/, '').trim(); - console.debug( - '[documentdb-query validator] Syntax error at offset %d–%d: %s', - startOffset, - endOffset, - message, - ); - diagnostics.push({ startOffset, endOffset, @@ -204,7 +190,6 @@ export function validateExpression(code: string): Diagnostic[] { message, }); } - console.debug('[documentdb-query validator] Returning %d diagnostic(s) after parse error', diagnostics.length); return diagnostics; } @@ -245,27 +230,12 @@ export function validateExpression(code: string): Diagnostic[] { if (nearMiss) { const startOffset = node.callee.start - 1; const endOffset = node.callee.end - 1; - - console.debug( - '[documentdb-query validator] Near-miss: "%s" at offset %d–%d → did you mean "%s"? (distance: %d)', - name, - startOffset, - endOffset, - nearMiss.match, - nearMiss.distance, - ); - diagnostics.push({ startOffset, endOffset, severity: 'warning', message: `Did you mean '${nearMiss.match}'?`, }); - } else { - console.debug( - '[documentdb-query validator] Unknown call: "%s" (no near-miss match)', - name, - ); } } @@ -287,36 +257,19 @@ export function validateExpression(code: string): Diagnostic[] { if (nearMiss) { const startOffset = node.callee.object.start - 1; const endOffset = node.callee.object.end - 1; - - console.debug( - '[documentdb-query validator] Near-miss (member object): "%s" at offset %d–%d → did you mean "%s"? (distance: %d)', - objName, - startOffset, - endOffset, - nearMiss.match, - nearMiss.distance, - ); - diagnostics.push({ startOffset, endOffset, severity: 'warning', message: `Did you mean '${nearMiss.match}'?`, }); - } else { - console.debug( - '[documentdb-query validator] Unknown member call object: "%s" (no near-miss match)', - objName, - ); } } }, }); } catch { // If walking fails, just return syntax diagnostics we already have - console.debug('[documentdb-query validator] AST walk failed, returning syntax diagnostics only'); } - console.debug('[documentdb-query validator] Returning %d diagnostic(s):', diagnostics.length, diagnostics); return diagnostics; } From 9fb2d69f2164fde5f27a2615ce0ad12c0cd4f221 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Mar 2026 15:59:18 +0000 Subject: [PATCH 061/128] fix: coalesce concurrent language registration calls Use a shared registrationPromise to prevent duplicate provider registrations when multiple editors call registerDocumentDBQueryLanguage() before the first async import resolves. --- .../documentdbQuery/registerLanguage.ts | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/webviews/documentdbQuery/registerLanguage.ts b/src/webviews/documentdbQuery/registerLanguage.ts index 0abe4b50f..4f1d73407 100644 --- a/src/webviews/documentdbQuery/registerLanguage.ts +++ b/src/webviews/documentdbQuery/registerLanguage.ts @@ -30,20 +30,24 @@ import { createCompletionItems } from './documentdbQueryCompletionProvider'; import { getHoverContent } from './documentdbQueryHoverProvider'; import { LANGUAGE_ID, parseEditorUri } from './languageConfig'; -/** Tracks whether the language has already been registered (idempotent guard). */ -let isRegistered = false; +/** Coalesces concurrent registrations into a single promise. */ +let registrationPromise: Promise | undefined; /** * Registers the `documentdb-query` language with Monaco. * - * Safe to call multiple times — subsequent calls are no-ops. + * Safe to call multiple times — concurrent calls coalesce into one registration. * * @param monaco - the Monaco editor API instance */ -export async function registerDocumentDBQueryLanguage(monaco: typeof monacoEditor): Promise { - if (isRegistered) { - return; +export function registerDocumentDBQueryLanguage(monaco: typeof monacoEditor): Promise { + if (!registrationPromise) { + registrationPromise = doRegisterLanguage(monaco); } + return registrationPromise; +} + +async function doRegisterLanguage(monaco: typeof monacoEditor): Promise { // Step 1: Register the language ID monaco.languages.register({ id: LANGUAGE_ID }); @@ -132,8 +136,6 @@ export async function registerDocumentDBQueryLanguage(monaco: typeof monacoEdito }; }, }); - - isRegistered = true; } /** @@ -141,5 +143,5 @@ export async function registerDocumentDBQueryLanguage(monaco: typeof monacoEdito * @internal */ export function _resetRegistration(): void { - isRegistered = false; + registrationPromise = undefined; } From 419380bae0f0bd9d984bbc168636b4093369934a Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Mar 2026 16:00:03 +0000 Subject: [PATCH 062/128] docs: clarify charBefore out-of-bounds behavior with example --- src/webviews/documentdbQuery/registerLanguage.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/webviews/documentdbQuery/registerLanguage.ts b/src/webviews/documentdbQuery/registerLanguage.ts index 4f1d73407..705a00d7d 100644 --- a/src/webviews/documentdbQuery/registerLanguage.ts +++ b/src/webviews/documentdbQuery/registerLanguage.ts @@ -89,7 +89,9 @@ async function doRegisterLanguage(monaco: typeof monacoEditor): Promise { // When the user types '$g', wordInfo.startColumn points to 'g', not '$'. // Without this fix, selecting '$gt' would insert '$$gt' (double dollar). const lineContent = model.getLineContent(position.lineNumber); - const charBefore = lineContent[wordInfo.startColumn - 2]; // -2 because columns are 1-based + // -2 because columns are 1-based: e.g. startColumn=1 → index -1 → undefined (safe). + // JS returns undefined for out-of-bounds array access, so (undefined === '$') → false. + const charBefore = lineContent[wordInfo.startColumn - 2]; if (charBefore === '$') { range = { ...range, startColumn: range.startColumn - 1 }; From e98417a9de623ce02ffad94b51cc680f8043e912 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Mar 2026 16:00:39 +0000 Subject: [PATCH 063/128] docs: add TODO for unused isDollarPrefix parameter (WIP) --- .../documentdbQuery/documentdbQueryCompletionProvider.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts index c3bc4e4ba..67eb88952 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts @@ -146,6 +146,8 @@ export interface CreateCompletionItemsParams { /** The range to insert completions at. */ range: monacoEditor.IRange; /** Whether the cursor is immediately after a '$' character. */ + // TODO: WIP — isDollarPrefix is passed but not yet consumed by createCompletionItems(). + // Will be used to filter/prioritize $-prefixed operators vs constructors. isDollarPrefix: boolean; /** The Monaco editor API. */ monaco: typeof monacoEditor; From d941a6031baf4b915d2b5ffc83cf9bbf50c93912 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Mar 2026 16:01:36 +0000 Subject: [PATCH 064/128] docs: document Identifier visitor as planned no-op --- .../documentdbQueryValidator.ts | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/webviews/documentdbQuery/documentdbQueryValidator.ts b/src/webviews/documentdbQuery/documentdbQueryValidator.ts index 2b3c4c124..9baca90a0 100644 --- a/src/webviews/documentdbQuery/documentdbQueryValidator.ts +++ b/src/webviews/documentdbQuery/documentdbQueryValidator.ts @@ -196,18 +196,13 @@ export function validateExpression(code: string): Diagnostic[] { // Walk the AST to check identifiers try { walk.simple(ast, { - Identifier(node: acorn.Node & { name: string }) { - const name = node.name; - - // Skip known globals and common identifiers - if (KNOWN_GLOBALS.has(name)) { - return; - } - - // Don't flag field names — only flag function call identifiers - // that look like BSON constructor typos. - // CallExpression and MemberExpression handlers below handle - // identifiers in call/member positions. + // Planned no-op: bare identifiers are intentionally not flagged. + // In DocumentDB queries, most identifiers are field names (e.g. `{ age: 1 }`) + // which are valid and shouldn't produce diagnostics. Only identifiers in + // call positions (BSON constructor typos) are checked — see CallExpression + // and MemberExpression handlers below. + Identifier(_node: acorn.Node & { name: string }) { + // no-op by design }, CallExpression( node: acorn.Node & { From 7bc3533f512f899dfd985b464ddc628dbb121c7d Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Mar 2026 16:02:23 +0000 Subject: [PATCH 065/128] feat: add telemetry for field completion data fetch failures Report fieldCompletionDataFetchFailed event when getFieldCompletionData fails, so silent field-completion degradation is visible in telemetry. --- .../documentdb/collectionView/CollectionView.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/webviews/documentdb/collectionView/CollectionView.tsx b/src/webviews/documentdb/collectionView/CollectionView.tsx index ef05ace0c..863a07bed 100644 --- a/src/webviews/documentdb/collectionView/CollectionView.tsx +++ b/src/webviews/documentdb/collectionView/CollectionView.tsx @@ -360,6 +360,16 @@ export const CollectionView = (): JSX.Element => { .catch((error) => { console.debug('Failed to update field completion data:', error); // Non-blocking — completion will work without fields + trpcClient.common.reportEvent + .mutate({ + eventName: 'fieldCompletionDataFetchFailed', + properties: { + error: error instanceof Error ? error.message : String(error), + }, + }) + .catch(() => { + // best-effort telemetry, swallow errors + }); }); } From 5514c639de3df6996df783d56c8caccb1a8a59d3 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Mar 2026 16:03:31 +0000 Subject: [PATCH 066/128] fix: remove unnecessary blank line in registerDocumentDBQueryLanguage function --- src/webviews/documentdbQuery/registerLanguage.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/webviews/documentdbQuery/registerLanguage.ts b/src/webviews/documentdbQuery/registerLanguage.ts index 705a00d7d..68fec4e0a 100644 --- a/src/webviews/documentdbQuery/registerLanguage.ts +++ b/src/webviews/documentdbQuery/registerLanguage.ts @@ -48,7 +48,6 @@ export function registerDocumentDBQueryLanguage(monaco: typeof monacoEditor): Pr } async function doRegisterLanguage(monaco: typeof monacoEditor): Promise { - // Step 1: Register the language ID monaco.languages.register({ id: LANGUAGE_ID }); From 5bf7bf3a7a96abe68ac7e72c77c324976230ded6 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Mar 2026 16:35:55 +0000 Subject: [PATCH 067/128] Step 4.5(1): cursor context detector with heuristic scanning Implements detectCursorContext() - a pure function that determines the semantic position of the cursor within a DocumentDB query expression. Supports: key, value, operator, array-element, and unknown positions. Uses backward character scanning (no AST parsing) for robustness with incomplete/mid-typing input. Includes 41 tests covering: - Core context detection (complete expressions) - Incomplete/broken input (Step 1.5 from plan) - Multi-line expressions - fieldLookup integration for BSON type enrichment --- .../documentdbQuery/cursorContext.test.ts | 271 ++++++++++++ src/webviews/documentdbQuery/cursorContext.ts | 410 ++++++++++++++++++ 2 files changed, 681 insertions(+) create mode 100644 src/webviews/documentdbQuery/cursorContext.test.ts create mode 100644 src/webviews/documentdbQuery/cursorContext.ts diff --git a/src/webviews/documentdbQuery/cursorContext.test.ts b/src/webviews/documentdbQuery/cursorContext.test.ts new file mode 100644 index 000000000..03f0d0ca7 --- /dev/null +++ b/src/webviews/documentdbQuery/cursorContext.test.ts @@ -0,0 +1,271 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { detectCursorContext, type CursorContext, type FieldTypeLookup } from './cursorContext'; + +/** + * Helper: place cursor at the `|` marker in the input string. + * Returns { text, offset } with the `|` removed. + */ +function parseCursor(input: string): { text: string; offset: number } { + const idx = input.indexOf('|'); + if (idx === -1) { + throw new Error(`Test input must contain a '|' cursor marker: "${input}"`); + } + return { + text: input.slice(0, idx) + input.slice(idx + 1), + offset: idx, + }; +} + +/** Shorthand to detect context from a `|`-marked string. */ +function detect(input: string, fieldLookup?: FieldTypeLookup): CursorContext { + const { text, offset } = parseCursor(input); + return detectCursorContext(text, offset, fieldLookup); +} + +describe('detectCursorContext', () => { + // --------------------------------------------------------------- + // Step 1: Core context detection (complete expressions) + // --------------------------------------------------------------- + describe('Step 1: Core context detection', () => { + describe('key position (root)', () => { + it('detects key position in empty object', () => { + const result = detect('{ | }'); + expect(result).toEqual({ position: 'key', depth: 1 }); + }); + + it('detects key position after opening brace', () => { + const result = detect('{|}'); + expect(result).toEqual({ position: 'key', depth: 1 }); + }); + + it('detects key position after comma in root object', () => { + const result = detect('{ name: "Alice", | }'); + expect(result).toEqual({ position: 'key', depth: 1 }); + }); + }); + + describe('value position', () => { + it('detects value position after colon', () => { + const result = detect('{ _id: | }'); + expect(result).toEqual({ position: 'value', fieldName: '_id' }); + }); + + it('detects value position for quoted key', () => { + const result = detect('{ "my.field": | }'); + expect(result).toEqual({ position: 'value', fieldName: 'my.field' }); + }); + + it('detects value position for single-quoted key', () => { + const result = detect("{ 'address.city': | }"); + expect(result).toEqual({ position: 'value', fieldName: 'address.city' }); + }); + + it('includes bsonType when fieldLookup provides it', () => { + const lookup: FieldTypeLookup = (name) => (name === 'age' ? 'int' : undefined); + const result = detect('{ age: | }', lookup); + expect(result).toEqual({ position: 'value', fieldName: 'age', fieldBsonType: 'int' }); + }); + + it('omits bsonType when fieldLookup returns undefined', () => { + const lookup: FieldTypeLookup = () => undefined; + const result = detect('{ age: | }', lookup); + expect(result).toEqual({ position: 'value', fieldName: 'age' }); + }); + }); + + describe('operator position (nested object)', () => { + it('detects operator position inside nested object', () => { + const result = detect('{ age: { | } }'); + expect(result).toEqual({ position: 'operator', fieldName: 'age' }); + }); + + it('detects operator position with bsonType', () => { + const lookup: FieldTypeLookup = (name) => (name === 'age' ? 'int' : undefined); + const result = detect('{ age: { | } }', lookup); + expect(result).toEqual({ position: 'operator', fieldName: 'age', fieldBsonType: 'int' }); + }); + + it('detects operator position after comma in nested object', () => { + const result = detect('{ age: { $gt: 5, | } }'); + expect(result).toEqual({ position: 'operator', fieldName: 'age' }); + }); + }); + + describe('array-element position', () => { + it('detects array-element inside $and', () => { + const result = detect('{ $and: [ | ] }'); + expect(result).toEqual({ position: 'array-element', parentOperator: '$and' }); + }); + + it('detects array-element inside $or', () => { + const result = detect('{ $or: [ | ] }'); + expect(result).toEqual({ position: 'array-element', parentOperator: '$or' }); + }); + + it('detects array-element inside $nor', () => { + const result = detect('{ $nor: [ | ] }'); + expect(result).toEqual({ position: 'array-element', parentOperator: '$nor' }); + }); + }); + + describe('key inside logical operator array element', () => { + it('detects key inside $and array element object', () => { + const result = detect('{ $and: [ { | } ] }'); + expect(result.position).toBe('key'); + }); + + it('detects key inside $or array element object after comma', () => { + const result = detect('{ $or: [ { x: 1 }, { | } ] }'); + expect(result.position).toBe('key'); + }); + }); + + describe('edge cases', () => { + it('returns unknown for empty string', () => { + expect(detectCursorContext('', 0)).toEqual({ position: 'unknown' }); + }); + + it('returns unknown for cursor at offset 0', () => { + expect(detectCursorContext('{ age: 1 }', 0)).toEqual({ position: 'unknown' }); + }); + + it('returns unknown for null-ish text', () => { + expect(detectCursorContext('', 5)).toEqual({ position: 'unknown' }); + }); + + it('clamps cursor offset to text length', () => { + // Cursor past end of text — should still work + const result = detectCursorContext('{ age: ', 100); + expect(result).toEqual({ position: 'value', fieldName: 'age' }); + }); + }); + }); + + // --------------------------------------------------------------- + // Step 1.5: Incomplete / broken input (mid-typing states) + // --------------------------------------------------------------- + describe('Step 1.5: Incomplete / broken input', () => { + it('{ age: | — colon just typed, no closing brace', () => { + const result = detect('{ age: |'); + expect(result).toEqual({ position: 'value', fieldName: 'age' }); + }); + + it('{ age: $| — started typing BSON constructor', () => { + const result = detect('{ age: $|'); + expect(result).toEqual({ position: 'value', fieldName: 'age' }); + }); + + it('{ age: $ |} — dollar with closing brace', () => { + const result = detect('{ age: $ |}'); + expect(result).toEqual({ position: 'value', fieldName: 'age' }); + }); + + it('{ age: {| — opened nested object, no close', () => { + const result = detect('{ age: {|'); + expect(result).toEqual({ position: 'operator', fieldName: 'age' }); + }); + + it('{ age: { $| — partially typed operator', () => { + const result = detect('{ age: { $|'); + expect(result).toEqual({ position: 'operator', fieldName: 'age' }); + }); + + it('{ age: { $ |} — incomplete operator inside nested object', () => { + const result = detect('{ age: { $ |}'); + expect(result).toEqual({ position: 'operator', fieldName: 'age' }); + }); + + it('{ age: { $g| — partially typed $gt', () => { + const result = detect('{ age: { $g|'); + expect(result).toEqual({ position: 'operator', fieldName: 'age' }); + }); + + it('{ | — opened root object, no field name yet', () => { + const result = detect('{ |'); + expect(result).toEqual({ position: 'key', depth: 1 }); + }); + + it('{ a| — partially typed field name', () => { + const result = detect('{ a|'); + expect(result).toEqual({ position: 'key', depth: 1 }); + }); + + it('{ name: "Alice", | — comma after first pair, new key expected', () => { + const result = detect('{ name: "Alice", |'); + expect(result).toEqual({ position: 'key', depth: 1 }); + }); + + it('{ name: "Alice", a| — partially typed second field name', () => { + const result = detect('{ name: "Alice", a|'); + expect(result).toEqual({ position: 'key', depth: 1 }); + }); + + it('{ $and: [| — opened array for logical operator', () => { + const result = detect('{ $and: [|'); + expect(result).toEqual({ position: 'array-element', parentOperator: '$and' }); + }); + + it('{ $and: [ {| — inside $and array element object', () => { + const result = detect('{ $and: [ {|'); + expect(result.position).toBe('key'); + }); + + it('{ age: { $gt: 5, | — after comma inside nested operator object', () => { + const result = detect('{ age: { $gt: 5, |'); + expect(result).toEqual({ position: 'operator', fieldName: 'age' }); + }); + + it('{| — just the opening brace', () => { + const result = detect('{|'); + expect(result).toEqual({ position: 'key', depth: 1 }); + }); + + it('empty string → unknown', () => { + expect(detectCursorContext('', 0)).toEqual({ position: 'unknown' }); + }); + + it('handles fieldLookup with incomplete input', () => { + const lookup: FieldTypeLookup = (name) => (name === 'age' ? 'int' : undefined); + const result = detect('{ age: { $|', lookup); + expect(result).toEqual({ position: 'operator', fieldName: 'age', fieldBsonType: 'int' }); + }); + + it('{ $or: [ { name: "x" }, {| — second element in $or array', () => { + const result = detect('{ $or: [ { name: "x" }, {|'); + expect(result.position).toBe('key'); + }); + }); + + // --------------------------------------------------------------- + // Multi-line expressions + // --------------------------------------------------------------- + describe('multi-line expressions', () => { + it('key position in multi-line object', () => { + const result = detect(`{ + name: "Alice", + | +}`); + expect(result).toEqual({ position: 'key', depth: 1 }); + }); + + it('value position in multi-line object', () => { + const result = detect(`{ + age: | +}`); + expect(result).toEqual({ position: 'value', fieldName: 'age' }); + }); + + it('operator position in multi-line nested object', () => { + const result = detect(`{ + age: { + | + } +}`); + expect(result).toEqual({ position: 'operator', fieldName: 'age' }); + }); + }); +}); diff --git a/src/webviews/documentdbQuery/cursorContext.ts b/src/webviews/documentdbQuery/cursorContext.ts new file mode 100644 index 000000000..64598fed8 --- /dev/null +++ b/src/webviews/documentdbQuery/cursorContext.ts @@ -0,0 +1,410 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Cursor context detection for the `documentdb-query` language. + * + * Determines the semantic position of the cursor within a DocumentDB query + * expression (e.g., key position, value position, operator position) using + * a heuristic character-scanning approach. + * + * This module is a pure function with no Monaco or VS Code dependencies, + * making it fully unit-testable. + */ + +/** + * The semantic position of the cursor within a query expression. + * + * Used by the completion provider to determine which completions to show. + */ +export type CursorContext = + | { position: 'key'; depth: number } + | { position: 'value'; fieldName: string; fieldBsonType?: string } + | { position: 'operator'; fieldName: string; fieldBsonType?: string } + | { position: 'array-element'; parentOperator: string } + | { position: 'unknown' }; + +/** + * A callback that resolves a field name to its BSON type string. + * Used to enrich cursor context with type information from the completion store. + */ +export type FieldTypeLookup = (fieldName: string) => string | undefined; + +/** + * Detects the semantic cursor context within a DocumentDB query expression. + * + * Uses a heuristic backward-scanning approach from the cursor position to + * determine whether the cursor is at a key, value, operator, or array-element + * position. Falls back to `{ position: 'unknown' }` when context cannot be + * determined. + * + * @param text - the full text of the editor + * @param cursorOffset - the 0-based character offset of the cursor + * @param fieldLookup - optional callback to resolve field names to BSON types + * @returns the detected cursor context + */ +export function detectCursorContext( + text: string, + cursorOffset: number, + fieldLookup?: FieldTypeLookup, +): CursorContext { + if (!text || cursorOffset <= 0) { + return { position: 'unknown' }; + } + + // Clamp cursor to text length + const offset = Math.min(cursorOffset, text.length); + + // Find the nearest structural character before the cursor + const scanResult = scanBackward(text, offset); + + if (!scanResult) { + return { position: 'unknown' }; + } + + switch (scanResult.char) { + case ':': + return resolveValueContext(text, scanResult.index, fieldLookup); + + case '{': + return resolveOpenBraceContext(text, scanResult.index, fieldLookup); + + case ',': + return resolveCommaContext(text, scanResult.index, fieldLookup); + + case '[': + return resolveOpenBracketContext(text, scanResult.index); + + default: + return { position: 'unknown' }; + } +} + +// ---------- Internal helpers ---------- + +/** Structural characters that define context boundaries. */ +const STRUCTURAL_CHARS = new Set([':', '{', ',', '[']); + +interface ScanResult { + char: string; + index: number; +} + +/** + * Scans backward from the cursor, skipping whitespace and identifier characters + * (letters, digits, `_`, `$`, `.`, quotes), to find the nearest structural character. + * + * Identifier characters are skipped because the cursor may be mid-word + * (e.g., `{ ag|` — cursor is after 'g', but context is 'key' from the `{`). + */ +function scanBackward(text: string, offset: number): ScanResult | undefined { + let i = offset - 1; + while (i >= 0) { + const ch = text[i]; + if (STRUCTURAL_CHARS.has(ch)) { + return { char: ch, index: i }; + } + // Skip whitespace and identifier-like characters + if (isSkippable(ch)) { + i--; + continue; + } + // Hit something unexpected (e.g., '}', ']', ')') — stop scanning + // '}' and ']' indicate we've exited the current expression + return undefined; + } + return undefined; +} + +/** + * Characters to skip during backward scanning. + * These are characters that can appear between a structural char and the cursor: + * - whitespace + * - identifier chars (a-z, A-Z, 0-9, _, $, .) + * - quote marks (the user may be inside a quoted key) + * - minus sign (for negative numbers) + */ +function isSkippable(ch: string): boolean { + return /[\s\w.$"'`\-/]/.test(ch); +} + +/** + * Resolves context when ':' is found — cursor is in a value position. + * + * Examples: + * - `{ _id: | }` → value with fieldName '_id' + * - `{ age: | }` → value with fieldName 'age' + */ +function resolveValueContext( + text: string, + colonIndex: number, + fieldLookup?: FieldTypeLookup, +): CursorContext { + const fieldName = extractKeyBeforeColon(text, colonIndex); + if (!fieldName) { + return { position: 'unknown' }; + } + const fieldBsonType = fieldLookup?.(fieldName); + return { + position: 'value', + fieldName, + ...(fieldBsonType !== undefined && { fieldBsonType }), + }; +} + +/** + * Resolves context when '{' is found. + * + * Two sub-cases: + * 1. Root or top-level: `{ | }` → key position + * 2. After a colon: `{ age: { | } }` → operator position for field 'age' + */ +function resolveOpenBraceContext( + text: string, + braceIndex: number, + fieldLookup?: FieldTypeLookup, +): CursorContext { + // Look backward from the '{' to find what precedes it + const beforeBrace = scanBackwardFrom(text, braceIndex); + + if (beforeBrace && beforeBrace.char === ':') { + // Pattern: `fieldName: { | }` → operator position + const fieldName = extractKeyBeforeColon(text, beforeBrace.index); + if (fieldName) { + // If the field name starts with '$', this is a nested query object + // inside a logical operator like $and: [ { | } ], but the immediate + // '{' is after a ':' which makes it an operator context + const fieldBsonType = fieldLookup?.(fieldName); + return { + position: 'operator', + fieldName, + ...(fieldBsonType !== undefined && { fieldBsonType }), + }; + } + } + + if (beforeBrace && beforeBrace.char === '[') { + // Pattern: `$and: [ { | } ]` → key at depth 1 + return resolveKeyInsideArray(text, beforeBrace.index); + } + + if (beforeBrace && beforeBrace.char === ',') { + // Pattern: `$and: [ {...}, { | } ]` — inside an array after another element + return resolveCommaInsideArrayForBrace(text, beforeBrace.index); + } + + // Root object or can't determine parent + // +1 because the brace at braceIndex is the one we're inside + const depth = computeDepth(text, braceIndex) + 1; + return { position: 'key', depth }; +} + +/** + * Resolves context when ',' is found. + * + * Sub-cases: + * 1. Inside an object: `{ name: "x", | }` → key position + * 2. Inside an operator object: `{ age: { $gt: 5, | } }` → operator position + * 3. Inside an array: `{ $and: [ {...}, | ] }` → array-element position + */ +function resolveCommaContext( + text: string, + commaIndex: number, + fieldLookup?: FieldTypeLookup, +): CursorContext { + // Determine if comma is inside an array or an object by finding the + // nearest unmatched '[' or '{' + const enclosing = findEnclosingBracket(text, commaIndex); + + if (!enclosing) { + return { position: 'unknown' }; + } + + if (enclosing.char === '[') { + // Inside an array — determine parent operator + return resolveOpenBracketContext(text, enclosing.index); + } + + if (enclosing.char === '{') { + // Inside an object — is this a root-level object or a nested operator object? + return resolveOpenBraceContext(text, enclosing.index, fieldLookup); + } + + return { position: 'unknown' }; +} + +/** + * Resolves context when '[' is found. + * + * Example: `{ $and: [ | ] }` → array-element with parentOperator '$and' + */ +function resolveOpenBracketContext( + text: string, + bracketIndex: number, +): CursorContext { + // Look backward from '[' to find the parent key via ':' + const beforeBracket = scanBackwardFrom(text, bracketIndex); + + if (beforeBracket && beforeBracket.char === ':') { + const parentKey = extractKeyBeforeColon(text, beforeBracket.index); + if (parentKey && parentKey.startsWith('$')) { + return { position: 'array-element', parentOperator: parentKey }; + } + } + + return { position: 'unknown' }; +} + +/** + * Resolves key context when '{' is found immediately after '['. + * Pattern: `$and: [ { | } ]` → key at depth 1 + */ +function resolveKeyInsideArray( + text: string, + bracketIndex: number, +): CursorContext { + // Check if this array belongs to a logical operator + const beforeBracket = scanBackwardFrom(text, bracketIndex); + if (beforeBracket && beforeBracket.char === ':') { + const parentKey = extractKeyBeforeColon(text, beforeBracket.index); + if (parentKey && parentKey.startsWith('$')) { + // Inside a logical operator array element — treat as key context + const depth = computeDepth(text, bracketIndex); + return { position: 'key', depth: depth + 1 }; + } + } + const depth = computeDepth(text, bracketIndex); + return { position: 'key', depth: depth + 1 }; +} + +/** + * Resolves context when '{' is preceded by ',' inside an array. + * Pattern: `$and: [ {...}, { | } ]` + */ +function resolveCommaInsideArrayForBrace( + text: string, + commaIndex: number, +): CursorContext { + const enclosing = findEnclosingBracket(text, commaIndex); + if (enclosing && enclosing.char === '[') { + return resolveKeyInsideArray(text, enclosing.index); + } + return { position: 'key', depth: 0 }; +} + +// ---------- Character scanning utilities ---------- + +/** + * Scans backward from a given index (exclusive), skipping whitespace + * and identifier characters, to find the nearest structural character. + */ +function scanBackwardFrom(text: string, index: number): ScanResult | undefined { + let i = index - 1; + while (i >= 0) { + const ch = text[i]; + if (STRUCTURAL_CHARS.has(ch) || ch === ']' || ch === '}') { + if (ch === ']' || ch === '}') { + return undefined; // Hit a closing bracket — stop + } + return { char: ch, index: i }; + } + if (isSkippable(ch)) { + i--; + continue; + } + return undefined; + } + return undefined; +} + +/** + * Finds the nearest unmatched opening bracket (`{` or `[`) before the given index. + * Properly handles nested brackets by maintaining a balance counter. + */ +function findEnclosingBracket(text: string, index: number): ScanResult | undefined { + let braceDepth = 0; + let bracketDepth = 0; + + for (let i = index - 1; i >= 0; i--) { + const ch = text[i]; + switch (ch) { + case '}': + braceDepth++; + break; + case '{': + if (braceDepth > 0) { + braceDepth--; + } else { + return { char: '{', index: i }; + } + break; + case ']': + bracketDepth++; + break; + case '[': + if (bracketDepth > 0) { + bracketDepth--; + } else { + return { char: '[', index: i }; + } + break; + } + } + return undefined; +} + +/** + * Extracts the key name immediately before a colon. + * + * Handles: + * - Unquoted keys: `age:` → 'age' + * - Single-quoted keys: `'my.field':` → 'my.field' + * - Double-quoted keys: `"my.field":` → 'my.field' + * - Dollar-prefixed: `$and:` → '$and' + */ +function extractKeyBeforeColon(text: string, colonIndex: number): string | undefined { + let i = colonIndex - 1; + + // Skip whitespace before the colon + while (i >= 0 && /\s/.test(text[i])) { + i--; + } + + if (i < 0) return undefined; + + // Check if the key is quoted + const quoteChar = text[i]; + if (quoteChar === '"' || quoteChar === "'") { + // Find the matching opening quote + const closeQuoteIndex = i; + i--; + while (i >= 0 && text[i] !== quoteChar) { + i--; + } + if (i < 0) return undefined; // Unmatched quote + return text.substring(i + 1, closeQuoteIndex); + } + + // Unquoted key — collect identifier characters (including $ and .) + const end = i + 1; + while (i >= 0 && /[\w$.]/.test(text[i])) { + i--; + } + const key = text.substring(i + 1, end); + return key.length > 0 ? key : undefined; +} + +/** + * Computes the brace nesting depth at a given position. + * Counts unmatched `{` before the index. + */ +function computeDepth(text: string, index: number): number { + let depth = 0; + for (let i = 0; i < index; i++) { + if (text[i] === '{') depth++; + if (text[i] === '}') depth--; + } + return Math.max(0, depth); +} From 0e0a081d6f2c3747054931fc0822fc8e3aeb7e6f Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Mar 2026 16:44:20 +0000 Subject: [PATCH 068/128] Step 4.5(2): context-sensitive completion filtering Wire CursorContext into createCompletionItems() to filter completions based on the semantic cursor position: - key position: field names + key-position operators (, , etc.) - value position: BSON constructors only (ObjectId, UUID, ISODate) - operator position: comparison/element/array operators with type-aware sort - array-element: same as key position - unknown/undefined: full list (backward compatible) All 48 existing tests pass unchanged. 16 new context-sensitive tests added. --- .../documentdbQueryCompletionProvider.test.ts | 381 ++++++++++++++++++ .../documentdbQueryCompletionProvider.ts | 154 ++++++- src/webviews/documentdbQuery/index.ts | 1 + 3 files changed, 531 insertions(+), 5 deletions(-) diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index f62a93edd..dd47e443e 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -12,6 +12,7 @@ import { // eslint-disable-next-line import/no-internal-modules import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; import { clearAllCompletionContexts, setCompletionContext } from './completionStore'; +import { type CursorContext } from './cursorContext'; import { createCompletionItems, getCompletionKindForMeta, @@ -745,4 +746,384 @@ describe('documentdbQueryCompletionProvider', () => { expect(fieldItem?.sortText).toBe('0_age'); }); }); + + // --------------------------------------------------------------- + // Context-sensitive completions (Step 4.5) + // --------------------------------------------------------------- + describe('context-sensitive completions', () => { + const mockMonaco = createMockMonaco(); + + afterEach(() => { + clearAllCompletionContexts(); + }); + + describe('key position', () => { + const keyContext: CursorContext = { position: 'key', depth: 1 }; + + test('shows field names when store has data', () => { + setCompletionContext('test-session', { + fields: [ + { + fieldName: 'name', + displayType: 'String', + bsonType: 'string', + isSparse: false, + insertText: 'name', + referenceText: '$name', + }, + ], + }); + + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: 'test-session', + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: keyContext, + }); + + const labels = items.map((i) => i.label); + expect(labels).toContain('name'); + }); + + test('shows key-position operators ($and, $or, $nor)', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: keyContext, + }); + + const labels = items.map((i) => i.label); + expect(labels).toContain('$and'); + expect(labels).toContain('$or'); + expect(labels).toContain('$nor'); + expect(labels).toContain('$not'); + expect(labels).toContain('$comment'); + expect(labels).toContain('$expr'); + }); + + test('does NOT show value-level operators ($gt, $lt, $regex, $eq)', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: keyContext, + }); + + const labels = items.map((i) => i.label); + expect(labels).not.toContain('$gt'); + expect(labels).not.toContain('$lt'); + expect(labels).not.toContain('$regex'); + expect(labels).not.toContain('$eq'); + expect(labels).not.toContain('$in'); + expect(labels).not.toContain('$exists'); + }); + + test('does NOT show BSON constructors', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: keyContext, + }); + + const labels = items.map((i) => i.label); + expect(labels).not.toContain('ObjectId'); + expect(labels).not.toContain('UUID'); + expect(labels).not.toContain('ISODate'); + }); + + test('fields sort before operators', () => { + setCompletionContext('test-session', { + fields: [ + { + fieldName: 'age', + displayType: 'Number', + bsonType: 'int', + isSparse: false, + insertText: 'age', + referenceText: '$age', + }, + ], + }); + + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: 'test-session', + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: keyContext, + }); + + const fieldItem = items.find((i) => i.label === 'age'); + const andItem = items.find((i) => i.label === '$and'); + expect(fieldItem?.sortText).toBe('0_age'); + expect(andItem?.sortText).toBe('1_$and'); + }); + }); + + describe('value position', () => { + const valueContext: CursorContext = { position: 'value', fieldName: 'age' }; + + test('shows BSON constructors', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: valueContext, + }); + + const labels = items.map((i) => i.label); + expect(labels).toContain('ObjectId'); + expect(labels).toContain('UUID'); + expect(labels).toContain('ISODate'); + }); + + test('does NOT show query operators', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: valueContext, + }); + + const labels = items.map((i) => i.label); + expect(labels).not.toContain('$gt'); + expect(labels).not.toContain('$eq'); + expect(labels).not.toContain('$and'); + }); + + test('does NOT show field names', () => { + setCompletionContext('test-session', { + fields: [ + { + fieldName: 'name', + displayType: 'String', + bsonType: 'string', + isSparse: false, + insertText: 'name', + referenceText: '$name', + }, + ], + }); + + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: 'test-session', + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: valueContext, + }); + + const labels = items.map((i) => i.label); + expect(labels).not.toContain('name'); + }); + }); + + describe('operator position', () => { + const operatorContext: CursorContext = { position: 'operator', fieldName: 'age' }; + + test('shows comparison operators ($gt, $lt, $eq, $in)', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: operatorContext, + }); + + const labels = items.map((i) => i.label); + expect(labels).toContain('$gt'); + expect(labels).toContain('$lt'); + expect(labels).toContain('$eq'); + expect(labels).toContain('$in'); + expect(labels).toContain('$exists'); + expect(labels).toContain('$regex'); + }); + + test('does NOT show key-position operators ($and, $or)', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: operatorContext, + }); + + const labels = items.map((i) => i.label); + expect(labels).not.toContain('$and'); + expect(labels).not.toContain('$or'); + expect(labels).not.toContain('$nor'); + }); + + test('does NOT show BSON constructors', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: operatorContext, + }); + + const labels = items.map((i) => i.label); + expect(labels).not.toContain('ObjectId'); + expect(labels).not.toContain('UUID'); + }); + + test('does NOT show field names', () => { + setCompletionContext('test-session', { + fields: [ + { + fieldName: 'name', + displayType: 'String', + bsonType: 'string', + isSparse: false, + insertText: 'name', + referenceText: '$name', + }, + ], + }); + + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: 'test-session', + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: operatorContext, + }); + + const labels = items.map((i) => i.label); + expect(labels).not.toContain('name'); + }); + + test('applies type-aware sorting when fieldBsonType is available', () => { + const typedContext: CursorContext = { + position: 'operator', + fieldName: 'age', + fieldBsonType: 'int', + }; + + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: typedContext, + }); + + // $regex has applicableBsonTypes=['string'], doesn't match 'int' → demoted + const regexItem = items.find((i) => i.label === '$regex'); + expect(regexItem?.sortText).toBe('2_$regex'); + + // $bitsAllSet has applicableBsonTypes containing 'int' → promoted + const bitsItem = items.find((i) => i.label === '$bitsAllSet'); + expect(bitsItem?.sortText).toBe('0_$bitsAllSet'); + + // $eq is universal → middle + const eqItem = items.find((i) => i.label === '$eq'); + expect(eqItem?.sortText).toBe('1_$eq'); + }); + }); + + describe('array-element position', () => { + const arrayContext: CursorContext = { position: 'array-element', parentOperator: '$and' }; + + test('behaves like key position (shows fields + key operators)', () => { + setCompletionContext('test-session', { + fields: [ + { + fieldName: 'age', + displayType: 'Number', + bsonType: 'int', + isSparse: false, + insertText: 'age', + referenceText: '$age', + }, + ], + }); + + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: 'test-session', + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: arrayContext, + }); + + const labels = items.map((i) => i.label); + // Should include fields + expect(labels).toContain('age'); + // Should include key-position operators + expect(labels).toContain('$and'); + expect(labels).toContain('$or'); + // Should NOT include value-level operators + expect(labels).not.toContain('$gt'); + expect(labels).not.toContain('$regex'); + // Should NOT include BSON constructors + expect(labels).not.toContain('ObjectId'); + }); + }); + + describe('unknown position', () => { + const unknownContext: CursorContext = { position: 'unknown' }; + + test('falls back to showing all completions', () => { + const itemsWithContext = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: unknownContext, + }); + + const itemsWithoutContext = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + }); + + // Same number of items + expect(itemsWithContext).toHaveLength(itemsWithoutContext.length); + }); + }); + + describe('no cursorContext (undefined)', () => { + test('falls back to showing all completions (backward compatible)', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: undefined, + }); + + const expected = getFilteredCompletions({ meta: [...FILTER_COMPLETION_META] }); + expect(items).toHaveLength(expected.length); + }); + }); + }); }); diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts index 67eb88952..15fc8900e 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts @@ -27,6 +27,7 @@ import { import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; import { type FieldCompletionData } from '../../utils/json/data-api/autocomplete/toFieldCompletionItems'; import { getCompletionContext } from './completionStore'; +import { type CursorContext } from './cursorContext'; import { EditorType } from './languageConfig'; /** @@ -157,6 +158,13 @@ export interface CreateCompletionItemsParams { * type-matching first, universal second, non-matching last. */ fieldBsonTypes?: readonly string[]; + /** + * Optional cursor context from the heuristic cursor position detector. + * When provided, completions are filtered based on the semantic position + * of the cursor (key, value, operator, array-element). + * When undefined, falls back to showing all completions (backward compatible). + */ + cursorContext?: CursorContext; } /** @@ -177,22 +185,159 @@ export function getMetaTagsForEditorType(editorType: EditorType | undefined): re } } +/** + * Operator values that are valid at key position (root level of a query object). + * These are logical operators and top-level query operators that take a document-level position, + * as opposed to value-level operators like $gt, $regex, etc. + * + * Exported for testing. + */ +export const KEY_POSITION_OPERATORS = new Set([ + '$and', + '$or', + '$nor', + '$not', + '$comment', + '$expr', + '$jsonSchema', + '$text', + '$where', +]); + /** * Creates Monaco completion items based on the editor context. * * This function is the main entry point called by the CompletionItemProvider. * It delegates to `documentdb-constants` for the operator data and maps * each entry to a Monaco CompletionItem. + * + * When a `cursorContext` is provided, completions are filtered based on the + * semantic position of the cursor: + * - **key**: field names + key-position operators ($and, $or, etc.) + * - **value**: BSON constructors only + * - **operator**: query operators (comparison, element, array, etc.) with type-aware sorting + * - **array-element**: same as key position + * - **unknown**: all completions (backward compatible fallback) */ export function createCompletionItems(params: CreateCompletionItemsParams): monacoEditor.languages.CompletionItem[] { - const { editorType, sessionId, range, monaco, fieldBsonTypes } = params; + const { editorType, sessionId, range, monaco, fieldBsonTypes, cursorContext } = params; + + // If no cursor context → fall back to showing everything (backward compatible) + if (!cursorContext || cursorContext.position === 'unknown') { + return createAllCompletions(editorType, sessionId, range, monaco, fieldBsonTypes); + } + + switch (cursorContext.position) { + case 'key': + case 'array-element': + return createKeyPositionCompletions(editorType, sessionId, range, monaco); + + case 'value': + return createValuePositionCompletions(editorType, range, monaco); + + case 'operator': { + const bsonTypes = cursorContext.fieldBsonType ? [cursorContext.fieldBsonType] : fieldBsonTypes; + return createOperatorPositionCompletions(editorType, range, monaco, bsonTypes); + } + + default: + return createAllCompletions(editorType, sessionId, range, monaco, fieldBsonTypes); + } +} - // Static operator completions from documentdb-constants +/** + * Returns all completions (operators + fields) — the pre-4.5 behavior. + * Used as fallback when cursor context is unknown or not provided. + */ +function createAllCompletions( + editorType: EditorType | undefined, + sessionId: string | undefined, + range: monacoEditor.IRange, + monaco: typeof monacoEditor, + fieldBsonTypes: readonly string[] | undefined, +): monacoEditor.languages.CompletionItem[] { const metaTags = getMetaTagsForEditorType(editorType); const entries = getFilteredCompletions({ meta: [...metaTags] }); const operatorItems = entries.map((entry) => mapOperatorToCompletionItem(entry, range, monaco, fieldBsonTypes)); - // Dynamic field completions from the completion store + const fieldItems = getFieldCompletionItems(sessionId, range, monaco); + return [...fieldItems, ...operatorItems]; +} + +/** + * Returns completions appropriate for key position: + * field names + key-position operators ($and, $or, $nor, $not, $comment, $expr, $jsonSchema, $text, $where). + * + * Fields get sort prefix `0_`, operators get `1_`. + */ +function createKeyPositionCompletions( + editorType: EditorType | undefined, + sessionId: string | undefined, + range: monacoEditor.IRange, + monaco: typeof monacoEditor, +): monacoEditor.languages.CompletionItem[] { + const metaTags = getMetaTagsForEditorType(editorType); + const allEntries = getFilteredCompletions({ meta: [...metaTags] }); + + // Filter to only key-position operators + const keyEntries = allEntries.filter((e) => KEY_POSITION_OPERATORS.has(e.value)); + const operatorItems = keyEntries.map((entry) => { + const item = mapOperatorToCompletionItem(entry, range, monaco); + // Give operators a `1_` prefix so fields sort first + item.sortText = `1_${entry.value}`; + return item; + }); + + const fieldItems = getFieldCompletionItems(sessionId, range, monaco); + return [...fieldItems, ...operatorItems]; +} + +/** + * Returns completions appropriate for value position: + * BSON constructors only (ObjectId, UUID, ISODate, etc.). + */ +function createValuePositionCompletions( + editorType: EditorType | undefined, + range: monacoEditor.IRange, + monaco: typeof monacoEditor, +): monacoEditor.languages.CompletionItem[] { + // For value position, we only want BSON constructors + // In the filter context, these have meta='bson' + const metaTags = getMetaTagsForEditorType(editorType); + const allEntries = getFilteredCompletions({ meta: [...metaTags] }); + const bsonEntries = allEntries.filter((e) => e.meta === 'bson'); + return bsonEntries.map((entry) => mapOperatorToCompletionItem(entry, range, monaco)); +} + +/** + * Returns completions appropriate for operator position (inside `{ field: { | } }`): + * Query operators (comparison, element, array, evaluation, bitwise) excluding key-position-only operators. + * Type-aware sorting is applied when field BSON types are available. + */ +function createOperatorPositionCompletions( + editorType: EditorType | undefined, + range: monacoEditor.IRange, + monaco: typeof monacoEditor, + fieldBsonTypes: readonly string[] | undefined, +): monacoEditor.languages.CompletionItem[] { + const metaTags = getMetaTagsForEditorType(editorType); + const allEntries = getFilteredCompletions({ meta: [...metaTags] }); + + // Exclude key-position-only operators and BSON constructors + const operatorEntries = allEntries.filter( + (e) => e.meta !== 'bson' && e.meta !== 'variable' && !KEY_POSITION_OPERATORS.has(e.value), + ); + return operatorEntries.map((entry) => mapOperatorToCompletionItem(entry, range, monaco, fieldBsonTypes)); +} + +/** + * Retrieves field completion items from the completion store for the given session. + */ +function getFieldCompletionItems( + sessionId: string | undefined, + range: monacoEditor.IRange, + monaco: typeof monacoEditor, +): monacoEditor.languages.CompletionItem[] { const fieldItems: monacoEditor.languages.CompletionItem[] = []; if (sessionId) { const context = getCompletionContext(sessionId); @@ -202,6 +347,5 @@ export function createCompletionItems(params: CreateCompletionItemsParams): mona } } } - - return [...fieldItems, ...operatorItems]; + return fieldItems; } diff --git a/src/webviews/documentdbQuery/index.ts b/src/webviews/documentdbQuery/index.ts index 535d659cc..cb349f84a 100644 --- a/src/webviews/documentdbQuery/index.ts +++ b/src/webviews/documentdbQuery/index.ts @@ -23,6 +23,7 @@ */ export { clearCompletionContext, getCompletionContext, setCompletionContext } from './completionStore'; +export { detectCursorContext, type CursorContext, type FieldTypeLookup } from './cursorContext'; export { validateExpression, type Diagnostic } from './documentdbQueryValidator'; export { EditorType, LANGUAGE_ID, URI_SCHEME, buildEditorUri, parseEditorUri } from './languageConfig'; export { registerDocumentDBQueryLanguage } from './registerLanguage'; From 3ee3e6742d0c59d43657747c09ec900e7140c4a6 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Mar 2026 16:45:32 +0000 Subject: [PATCH 069/128] Step 4.5(3): wire cursor context into completion provider Call detectCursorContext() in provideCompletionItems to detect the semantic cursor position from editor text + offset. Pass the detected CursorContext through to createCompletionItems() for context-sensitive filtering. Includes field type lookup via completionStore to enrich context with BSON types for type-aware operator sorting. --- src/webviews/documentdbQuery/cursorContext.ts | 39 ++++--------------- .../documentdbQuery/registerLanguage.ts | 19 ++++++++- 2 files changed, 25 insertions(+), 33 deletions(-) diff --git a/src/webviews/documentdbQuery/cursorContext.ts b/src/webviews/documentdbQuery/cursorContext.ts index 64598fed8..d6c06f2c5 100644 --- a/src/webviews/documentdbQuery/cursorContext.ts +++ b/src/webviews/documentdbQuery/cursorContext.ts @@ -45,11 +45,7 @@ export type FieldTypeLookup = (fieldName: string) => string | undefined; * @param fieldLookup - optional callback to resolve field names to BSON types * @returns the detected cursor context */ -export function detectCursorContext( - text: string, - cursorOffset: number, - fieldLookup?: FieldTypeLookup, -): CursorContext { +export function detectCursorContext(text: string, cursorOffset: number, fieldLookup?: FieldTypeLookup): CursorContext { if (!text || cursorOffset <= 0) { return { position: 'unknown' }; } @@ -137,11 +133,7 @@ function isSkippable(ch: string): boolean { * - `{ _id: | }` → value with fieldName '_id' * - `{ age: | }` → value with fieldName 'age' */ -function resolveValueContext( - text: string, - colonIndex: number, - fieldLookup?: FieldTypeLookup, -): CursorContext { +function resolveValueContext(text: string, colonIndex: number, fieldLookup?: FieldTypeLookup): CursorContext { const fieldName = extractKeyBeforeColon(text, colonIndex); if (!fieldName) { return { position: 'unknown' }; @@ -161,11 +153,7 @@ function resolveValueContext( * 1. Root or top-level: `{ | }` → key position * 2. After a colon: `{ age: { | } }` → operator position for field 'age' */ -function resolveOpenBraceContext( - text: string, - braceIndex: number, - fieldLookup?: FieldTypeLookup, -): CursorContext { +function resolveOpenBraceContext(text: string, braceIndex: number, fieldLookup?: FieldTypeLookup): CursorContext { // Look backward from the '{' to find what precedes it const beforeBrace = scanBackwardFrom(text, braceIndex); @@ -209,11 +197,7 @@ function resolveOpenBraceContext( * 2. Inside an operator object: `{ age: { $gt: 5, | } }` → operator position * 3. Inside an array: `{ $and: [ {...}, | ] }` → array-element position */ -function resolveCommaContext( - text: string, - commaIndex: number, - fieldLookup?: FieldTypeLookup, -): CursorContext { +function resolveCommaContext(text: string, commaIndex: number, fieldLookup?: FieldTypeLookup): CursorContext { // Determine if comma is inside an array or an object by finding the // nearest unmatched '[' or '{' const enclosing = findEnclosingBracket(text, commaIndex); @@ -240,10 +224,7 @@ function resolveCommaContext( * * Example: `{ $and: [ | ] }` → array-element with parentOperator '$and' */ -function resolveOpenBracketContext( - text: string, - bracketIndex: number, -): CursorContext { +function resolveOpenBracketContext(text: string, bracketIndex: number): CursorContext { // Look backward from '[' to find the parent key via ':' const beforeBracket = scanBackwardFrom(text, bracketIndex); @@ -261,10 +242,7 @@ function resolveOpenBracketContext( * Resolves key context when '{' is found immediately after '['. * Pattern: `$and: [ { | } ]` → key at depth 1 */ -function resolveKeyInsideArray( - text: string, - bracketIndex: number, -): CursorContext { +function resolveKeyInsideArray(text: string, bracketIndex: number): CursorContext { // Check if this array belongs to a logical operator const beforeBracket = scanBackwardFrom(text, bracketIndex); if (beforeBracket && beforeBracket.char === ':') { @@ -283,10 +261,7 @@ function resolveKeyInsideArray( * Resolves context when '{' is preceded by ',' inside an array. * Pattern: `$and: [ {...}, { | } ]` */ -function resolveCommaInsideArrayForBrace( - text: string, - commaIndex: number, -): CursorContext { +function resolveCommaInsideArrayForBrace(text: string, commaIndex: number): CursorContext { const enclosing = findEnclosingBracket(text, commaIndex); if (enclosing && enclosing.char === '[') { return resolveKeyInsideArray(text, enclosing.index); diff --git a/src/webviews/documentdbQuery/registerLanguage.ts b/src/webviews/documentdbQuery/registerLanguage.ts index 68fec4e0a..7624ff4b7 100644 --- a/src/webviews/documentdbQuery/registerLanguage.ts +++ b/src/webviews/documentdbQuery/registerLanguage.ts @@ -26,6 +26,8 @@ // eslint-disable-next-line import/no-internal-modules import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; +import { getCompletionContext } from './completionStore'; +import { detectCursorContext } from './cursorContext'; import { createCompletionItems } from './documentdbQueryCompletionProvider'; import { getHoverContent } from './documentdbQueryHoverProvider'; import { LANGUAGE_ID, parseEditorUri } from './languageConfig'; @@ -96,13 +98,28 @@ async function doRegisterLanguage(monaco: typeof monacoEditor): Promise { range = { ...range, startColumn: range.startColumn - 1 }; } + // Detect cursor context for context-sensitive completions + const text = model.getValue(); + const cursorOffset = model.getOffsetAt(position); + const sessionId = parsed?.sessionId; + + // Build field lookup from completion store to enrich context with BSON types + const fieldLookup = (fieldName: string): string | undefined => { + if (!sessionId) return undefined; + const ctx = getCompletionContext(sessionId); + return ctx?.fields.find((f) => f.fieldName === fieldName)?.bsonType; + }; + + const cursorContext = detectCursorContext(text, cursorOffset, fieldLookup); + // Build completion items based on context const items = createCompletionItems({ editorType: parsed?.editorType, - sessionId: parsed?.sessionId, + sessionId, range, isDollarPrefix: charBefore === '$', monaco, + cursorContext, }); return { suggestions: items }; From 4c97c356463fe8f3a07ee7db77b0f57d4f83656d Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Mar 2026 18:04:09 +0000 Subject: [PATCH 070/128] Step 4.5(5): fix Issues A, B, C from manual testing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue A - Strip outer braces from operator snippets at operator position: { $gt: ${1:value} } → $gt: ${1:value} (when inside { field: { | } }) Prevents double-brace insertion bug. Issue B - Add category labels to completion items: Uses CompletionItemLabel.detail for operator category (comparison, logical, etc.) Uses CompletionItemLabel.description for operator description text. Issue C - Value position now shows operators + BSON constructors: Operators sorted first (0_), BSON constructors second (1_). Operators keep their full brace-wrapping snippets at value position. Also: trace-level console.debug logging in provideCompletionItems for debugging. 178 tests pass across 6 test suites. Build + lint clean. --- .../documentdbQueryCompletionProvider.test.ts | 182 ++++++++++++++---- .../documentdbQueryCompletionProvider.ts | 87 ++++++++- .../documentdbQuery/registerLanguage.ts | 18 ++ 3 files changed, 238 insertions(+), 49 deletions(-) diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index dd47e443e..0b2d78a12 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -15,11 +15,13 @@ import { clearAllCompletionContexts, setCompletionContext } from './completionSt import { type CursorContext } from './cursorContext'; import { createCompletionItems, + getCategoryLabel, getCompletionKindForMeta, getMetaTagsForEditorType, getOperatorSortPrefix, mapFieldToCompletionItem, mapOperatorToCompletionItem, + stripOuterBraces, } from './documentdbQueryCompletionProvider'; import { EditorType } from './languageConfig'; @@ -77,6 +79,14 @@ function createMockMonaco(): typeof monacoEditor { } as unknown as typeof monacoEditor; } +/** + * Extracts the label string from a CompletionItem's label, + * which may be a plain string or a CompletionItemLabel object. + */ +function getLabelText(label: string | monacoEditor.languages.CompletionItemLabel): string { + return typeof label === 'string' ? label : label.label; +} + /** Standard test range for all completion items. */ const testRange: monacoEditor.IRange = { startLineNumber: 1, @@ -145,7 +155,7 @@ describe('documentdbQueryCompletionProvider', () => { const item = mapOperatorToCompletionItem(entry, testRange, mockMonaco); - expect(item.label).toBe('$eq'); + expect(getLabelText(item.label)).toBe('$eq'); expect(item.kind).toBe(mockCompletionItemKind.Operator); expect(item.insertText).toBe('$eq'); expect(item.insertTextRules).toBeUndefined(); @@ -164,7 +174,7 @@ describe('documentdbQueryCompletionProvider', () => { const item = mapOperatorToCompletionItem(entry, testRange, mockMonaco); - expect(item.label).toBe('$gt'); + expect(getLabelText(item.label)).toBe('$gt'); expect(item.insertText).toBe('{ $gt: ${1:value} }'); expect(item.insertTextRules).toBe(mockInsertTextRule.InsertAsSnippet); }); @@ -180,7 +190,7 @@ describe('documentdbQueryCompletionProvider', () => { const item = mapOperatorToCompletionItem(entry, testRange, mockMonaco); - expect(item.label).toBe('ObjectId'); + expect(getLabelText(item.label)).toBe('ObjectId'); expect(item.kind).toBe(mockCompletionItemKind.Constructor); expect(item.insertText).toBe('ObjectId("${1:hex}")'); expect(item.insertTextRules).toBe(mockInsertTextRule.InsertAsSnippet); @@ -252,7 +262,7 @@ describe('documentdbQueryCompletionProvider', () => { // All items should have required CompletionItem properties for (const item of items) { expect(item.label).toBeDefined(); - expect(typeof item.label).toBe('string'); + expect(getLabelText(item.label)).toBeDefined(); expect(item.kind).toBeDefined(); expect(item.insertText).toBeDefined(); expect(item.range).toBe(testRange); @@ -268,7 +278,7 @@ describe('documentdbQueryCompletionProvider', () => { monaco: mockMonaco, }); - const labels = items.map((item) => item.label); + const labels = items.map((item) => getLabelText(item.label)); expect(labels).toContain('$eq'); expect(labels).toContain('$gt'); expect(labels).toContain('$in'); @@ -283,7 +293,7 @@ describe('documentdbQueryCompletionProvider', () => { monaco: mockMonaco, }); - const labels = items.map((item) => item.label); + const labels = items.map((item) => getLabelText(item.label)); expect(labels).toContain('ObjectId'); expect(labels).toContain('UUID'); expect(labels).toContain('ISODate'); @@ -298,7 +308,7 @@ describe('documentdbQueryCompletionProvider', () => { monaco: mockMonaco, }); - const labels = items.map((item) => item.label); + const labels = items.map((item) => getLabelText(item.label)); expect(labels).not.toContain('console'); expect(labels).not.toContain('Math'); expect(labels).not.toContain('function'); @@ -318,7 +328,7 @@ describe('documentdbQueryCompletionProvider', () => { monaco: mockMonaco, }); - const labels = items.map((item) => item.label); + const labels = items.map((item) => getLabelText(item.label)); // $match is a query operator AND a stage, but $group/$unwind are stage-only expect(labels).not.toContain('$group'); expect(labels).not.toContain('$unwind'); @@ -451,7 +461,7 @@ describe('documentdbQueryCompletionProvider', () => { monaco: mockMonaco, }); - const labels = items.map((i) => i.label); + const labels = items.map((i) => getLabelText(i.label)); expect(labels).toContain('name'); expect(labels).toContain('age'); }); @@ -478,11 +488,11 @@ describe('documentdbQueryCompletionProvider', () => { monaco: mockMonaco, }); - const fieldItem = items.find((i) => i.label === 'name'); + const fieldItem = items.find((i) => getLabelText(i.label) === 'name'); expect(fieldItem?.sortText).toBe('0_name'); // Operators should not have a sort prefix starting with 0_ - const operatorItem = items.find((i) => i.label === '$eq'); + const operatorItem = items.find((i) => getLabelText(i.label) === '$eq'); expect(operatorItem?.sortText).toBeUndefined(); }); @@ -647,10 +657,10 @@ describe('documentdbQueryCompletionProvider', () => { monaco: mockMonaco, }); - const regexItem = items.find((i) => i.label === '$regex'); + const regexItem = items.find((i) => getLabelText(i.label) === '$regex'); expect(regexItem?.sortText).toBeUndefined(); - const eqItem = items.find((i) => i.label === '$eq'); + const eqItem = items.find((i) => getLabelText(i.label) === '$eq'); expect(eqItem?.sortText).toBeUndefined(); }); @@ -664,14 +674,14 @@ describe('documentdbQueryCompletionProvider', () => { fieldBsonTypes: ['string'], }); - const regexItem = items.find((i) => i.label === '$regex'); + const regexItem = items.find((i) => getLabelText(i.label) === '$regex'); expect(regexItem?.sortText).toBe('0_$regex'); - const sizeItem = items.find((i) => i.label === '$size'); + const sizeItem = items.find((i) => getLabelText(i.label) === '$size'); expect(sizeItem?.sortText).toBe('2_$size'); // Universal operators like $eq get "1_" - const eqItem = items.find((i) => i.label === '$eq'); + const eqItem = items.find((i) => getLabelText(i.label) === '$eq'); expect(eqItem?.sortText).toBe('1_$eq'); }); @@ -685,15 +695,15 @@ describe('documentdbQueryCompletionProvider', () => { fieldBsonTypes: ['int'], }); - const labels = items.map((i) => i.label); + const labels = items.map((i) => getLabelText(i.label)); // $regex is still in the list, just demoted expect(labels).toContain('$regex'); - const regexItem = items.find((i) => i.label === '$regex'); + const regexItem = items.find((i) => getLabelText(i.label) === '$regex'); expect(regexItem?.sortText).toBe('2_$regex'); // Bitwise operators should match int - const bitsAllSetItem = items.find((i) => i.label === '$bitsAllSet'); + const bitsAllSetItem = items.find((i) => getLabelText(i.label) === '$bitsAllSet'); expect(bitsAllSetItem?.sortText).toBe('0_$bitsAllSet'); }); @@ -742,11 +752,47 @@ describe('documentdbQueryCompletionProvider', () => { fieldBsonTypes: ['int'], }); - const fieldItem = items.find((i) => i.label === 'age'); + const fieldItem = items.find((i) => getLabelText(i.label) === 'age'); expect(fieldItem?.sortText).toBe('0_age'); }); }); + describe('stripOuterBraces', () => { + test('strips outer { } from operator snippets', () => { + expect(stripOuterBraces('{ $gt: ${1:value} }')).toBe('$gt: ${1:value}'); + }); + + test('preserves inner brackets', () => { + expect(stripOuterBraces('{ $in: [${1:value}] }')).toBe('$in: [${1:value}]'); + }); + + test('preserves inner braces', () => { + expect(stripOuterBraces('{ $elemMatch: { ${1:query} } }')).toBe('$elemMatch: { ${1:query} }'); + }); + + test('returns unchanged if not wrapped', () => { + expect(stripOuterBraces('ObjectId("${1:hex}")')).toBe('ObjectId("${1:hex}")'); + }); + + test('returns unchanged for non-matching patterns', () => { + expect(stripOuterBraces('$gt')).toBe('$gt'); + }); + }); + + describe('getCategoryLabel', () => { + test('extracts sub-category from qualified meta tag', () => { + expect(getCategoryLabel('query:comparison')).toBe('comparison'); + expect(getCategoryLabel('query:logical')).toBe('logical'); + expect(getCategoryLabel('query:element')).toBe('element'); + expect(getCategoryLabel('query:array')).toBe('array'); + }); + + test('returns whole tag when no colon', () => { + expect(getCategoryLabel('bson')).toBe('bson'); + expect(getCategoryLabel('variable')).toBe('variable'); + }); + }); + // --------------------------------------------------------------- // Context-sensitive completions (Step 4.5) // --------------------------------------------------------------- @@ -783,7 +829,7 @@ describe('documentdbQueryCompletionProvider', () => { cursorContext: keyContext, }); - const labels = items.map((i) => i.label); + const labels = items.map((i) => getLabelText(i.label)); expect(labels).toContain('name'); }); @@ -797,7 +843,7 @@ describe('documentdbQueryCompletionProvider', () => { cursorContext: keyContext, }); - const labels = items.map((i) => i.label); + const labels = items.map((i) => getLabelText(i.label)); expect(labels).toContain('$and'); expect(labels).toContain('$or'); expect(labels).toContain('$nor'); @@ -816,7 +862,7 @@ describe('documentdbQueryCompletionProvider', () => { cursorContext: keyContext, }); - const labels = items.map((i) => i.label); + const labels = items.map((i) => getLabelText(i.label)); expect(labels).not.toContain('$gt'); expect(labels).not.toContain('$lt'); expect(labels).not.toContain('$regex'); @@ -835,7 +881,7 @@ describe('documentdbQueryCompletionProvider', () => { cursorContext: keyContext, }); - const labels = items.map((i) => i.label); + const labels = items.map((i) => getLabelText(i.label)); expect(labels).not.toContain('ObjectId'); expect(labels).not.toContain('UUID'); expect(labels).not.toContain('ISODate'); @@ -864,8 +910,8 @@ describe('documentdbQueryCompletionProvider', () => { cursorContext: keyContext, }); - const fieldItem = items.find((i) => i.label === 'age'); - const andItem = items.find((i) => i.label === '$and'); + const fieldItem = items.find((i) => getLabelText(i.label) === 'age'); + const andItem = items.find((i) => getLabelText(i.label) === '$and'); expect(fieldItem?.sortText).toBe('0_age'); expect(andItem?.sortText).toBe('1_$and'); }); @@ -884,13 +930,13 @@ describe('documentdbQueryCompletionProvider', () => { cursorContext: valueContext, }); - const labels = items.map((i) => i.label); + const labels = items.map((i) => getLabelText(i.label)); expect(labels).toContain('ObjectId'); expect(labels).toContain('UUID'); expect(labels).toContain('ISODate'); }); - test('does NOT show query operators', () => { + test('shows query operators (with brace-wrapping snippets)', () => { const items = createCompletionItems({ editorType: EditorType.Filter, sessionId: undefined, @@ -900,10 +946,45 @@ describe('documentdbQueryCompletionProvider', () => { cursorContext: valueContext, }); - const labels = items.map((i) => i.label); - expect(labels).not.toContain('$gt'); - expect(labels).not.toContain('$eq'); + const labels = items.map((i) => getLabelText(i.label)); + expect(labels).toContain('$gt'); + expect(labels).toContain('$eq'); + expect(labels).toContain('$in'); + + // Operators should have their full brace-wrapping snippets at value position + const gtItem = items.find((i) => getLabelText(i.label) === '$gt'); + expect(gtItem?.insertText).toBe('{ $gt: ${1:value} }'); + }); + + test('operators sort before BSON constructors', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: valueContext, + }); + + const gtItem = items.find((i) => getLabelText(i.label) === '$gt'); + const objectIdItem = items.find((i) => getLabelText(i.label) === 'ObjectId'); + expect(gtItem?.sortText).toBe('0_$gt'); + expect(objectIdItem?.sortText).toBe('1_ObjectId'); + }); + + test('does NOT show key-position operators ($and, $or)', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: valueContext, + }); + + const labels = items.map((i) => getLabelText(i.label)); expect(labels).not.toContain('$and'); + expect(labels).not.toContain('$or'); }); test('does NOT show field names', () => { @@ -929,7 +1010,7 @@ describe('documentdbQueryCompletionProvider', () => { cursorContext: valueContext, }); - const labels = items.map((i) => i.label); + const labels = items.map((i) => getLabelText(i.label)); expect(labels).not.toContain('name'); }); }); @@ -947,7 +1028,7 @@ describe('documentdbQueryCompletionProvider', () => { cursorContext: operatorContext, }); - const labels = items.map((i) => i.label); + const labels = items.map((i) => getLabelText(i.label)); expect(labels).toContain('$gt'); expect(labels).toContain('$lt'); expect(labels).toContain('$eq'); @@ -966,7 +1047,7 @@ describe('documentdbQueryCompletionProvider', () => { cursorContext: operatorContext, }); - const labels = items.map((i) => i.label); + const labels = items.map((i) => getLabelText(i.label)); expect(labels).not.toContain('$and'); expect(labels).not.toContain('$or'); expect(labels).not.toContain('$nor'); @@ -982,7 +1063,7 @@ describe('documentdbQueryCompletionProvider', () => { cursorContext: operatorContext, }); - const labels = items.map((i) => i.label); + const labels = items.map((i) => getLabelText(i.label)); expect(labels).not.toContain('ObjectId'); expect(labels).not.toContain('UUID'); }); @@ -1010,7 +1091,7 @@ describe('documentdbQueryCompletionProvider', () => { cursorContext: operatorContext, }); - const labels = items.map((i) => i.label); + const labels = items.map((i) => getLabelText(i.label)); expect(labels).not.toContain('name'); }); @@ -1031,17 +1112,38 @@ describe('documentdbQueryCompletionProvider', () => { }); // $regex has applicableBsonTypes=['string'], doesn't match 'int' → demoted - const regexItem = items.find((i) => i.label === '$regex'); + const regexItem = items.find((i) => getLabelText(i.label) === '$regex'); expect(regexItem?.sortText).toBe('2_$regex'); // $bitsAllSet has applicableBsonTypes containing 'int' → promoted - const bitsItem = items.find((i) => i.label === '$bitsAllSet'); + const bitsItem = items.find((i) => getLabelText(i.label) === '$bitsAllSet'); expect(bitsItem?.sortText).toBe('0_$bitsAllSet'); // $eq is universal → middle - const eqItem = items.find((i) => i.label === '$eq'); + const eqItem = items.find((i) => getLabelText(i.label) === '$eq'); expect(eqItem?.sortText).toBe('1_$eq'); }); + + test('strips outer braces from operator snippets (Issue A fix)', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: operatorContext, + }); + + // At operator position, snippets should NOT have outer { } + const gtItem = items.find((i) => getLabelText(i.label) === '$gt'); + expect(gtItem?.insertText).toBe('$gt: ${1:value}'); + + const inItem = items.find((i) => getLabelText(i.label) === '$in'); + expect(inItem?.insertText).toBe('$in: [${1:value}]'); + + const regexItem = items.find((i) => getLabelText(i.label) === '$regex'); + expect(regexItem?.insertText).toBe('$regex: /${1:pattern}/'); + }); }); describe('array-element position', () => { @@ -1070,7 +1172,7 @@ describe('documentdbQueryCompletionProvider', () => { cursorContext: arrayContext, }); - const labels = items.map((i) => i.label); + const labels = items.map((i) => getLabelText(i.label)); // Should include fields expect(labels).toContain('age'); // Should include key-position operators diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts index 15fc8900e..150932e71 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts @@ -78,6 +78,42 @@ export function getOperatorSortPrefix( return hasMatch ? '0_' : '2_'; } +/** + * Extracts a human-readable category label from a meta tag. + * + * Examples: + * - `'query:comparison'` → `'comparison'` + * - `'query:logical'` → `'logical'` + * - `'bson'` → `'bson'` + * - `'variable'` → `'variable'` + */ +export function getCategoryLabel(meta: string): string { + const colonIndex = meta.indexOf(':'); + return colonIndex >= 0 ? meta.substring(colonIndex + 1) : meta; +} + +/** + * Strips the outermost `{ ` and ` }` from an operator snippet. + * + * Operator snippets in documentdb-constants are designed for value position + * (e.g., `{ $gt: ${1:value} }`). At operator position, the user is already + * inside braces, so the outer wrapping must be removed to avoid double-nesting. + * + * Only strips if the snippet starts with `'{ '` and ends with `' }'`. + * Inner brackets/braces are preserved: + * - `{ $in: [${1:value}] }` → `$in: [${1:value}]` + * - `{ $gt: ${1:value} }` → `$gt: ${1:value}` + * + * @param snippet - the original snippet string + * @returns the snippet with outer braces stripped, or the original if not wrapped + */ +export function stripOuterBraces(snippet: string): string { + if (snippet.startsWith('{ ') && snippet.endsWith(' }')) { + return snippet.slice(2, -2); + } + return snippet; +} + /** * Maps an OperatorEntry from documentdb-constants to a Monaco CompletionItem. * @@ -88,20 +124,32 @@ export function getOperatorSortPrefix( * @param range - the insertion range * @param monaco - the Monaco API * @param fieldBsonTypes - optional BSON types of the field for type-aware sorting + * @param stripBraces - when true, strip outer `{ }` from snippets (for operator position) */ export function mapOperatorToCompletionItem( entry: OperatorEntry, range: monacoEditor.IRange, monaco: typeof monacoEditor, fieldBsonTypes?: readonly string[], + stripBraces?: boolean, ): monacoEditor.languages.CompletionItem { const hasSnippet = !!entry.snippet; const sortPrefix = getOperatorSortPrefix(entry, fieldBsonTypes); + let insertText = hasSnippet ? entry.snippet! : entry.value; + if (stripBraces && hasSnippet) { + insertText = stripOuterBraces(insertText); + } + + const categoryLabel = getCategoryLabel(entry.meta); return { - label: entry.value, + label: { + label: entry.value, + detail: ` ${categoryLabel}`, + description: entry.description, + }, kind: getCompletionKindForMeta(entry.meta, monaco.languages.CompletionItemKind), - insertText: hasSnippet ? entry.snippet! : entry.value, + insertText, insertTextRules: hasSnippet ? monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet : undefined, detail: entry.description, documentation: entry.link @@ -214,8 +262,8 @@ export const KEY_POSITION_OPERATORS = new Set([ * When a `cursorContext` is provided, completions are filtered based on the * semantic position of the cursor: * - **key**: field names + key-position operators ($and, $or, etc.) - * - **value**: BSON constructors only - * - **operator**: query operators (comparison, element, array, etc.) with type-aware sorting + * - **value**: query operators (with braces in snippet) + BSON constructors + * - **operator**: query operators (without braces in snippet) with type-aware sorting * - **array-element**: same as key position * - **unknown**: all completions (backward compatible fallback) */ @@ -294,19 +342,39 @@ function createKeyPositionCompletions( /** * Returns completions appropriate for value position: - * BSON constructors only (ObjectId, UUID, ISODate, etc.). + * Query operators first (with full brace-wrapping snippets), then BSON constructors. + * + * Operators use their original snippets which include `{ }` — this is correct + * at value position because the user needs the nested object + * (e.g., `{ _id: }` → selecting `$gt` inserts `{ $gt: value }`). */ function createValuePositionCompletions( editorType: EditorType | undefined, range: monacoEditor.IRange, monaco: typeof monacoEditor, ): monacoEditor.languages.CompletionItem[] { - // For value position, we only want BSON constructors - // In the filter context, these have meta='bson' const metaTags = getMetaTagsForEditorType(editorType); const allEntries = getFilteredCompletions({ meta: [...metaTags] }); + + // Operators first (sort prefix 0_), excluding key-position-only operators + const operatorEntries = allEntries.filter( + (e) => e.meta !== 'bson' && e.meta !== 'variable' && !KEY_POSITION_OPERATORS.has(e.value), + ); + const operatorItems = operatorEntries.map((entry) => { + const item = mapOperatorToCompletionItem(entry, range, monaco); + item.sortText = `0_${entry.value}`; + return item; + }); + + // BSON constructors second (sort prefix 1_) const bsonEntries = allEntries.filter((e) => e.meta === 'bson'); - return bsonEntries.map((entry) => mapOperatorToCompletionItem(entry, range, monaco)); + const bsonItems = bsonEntries.map((entry) => { + const item = mapOperatorToCompletionItem(entry, range, monaco); + item.sortText = `1_${entry.value}`; + return item; + }); + + return [...operatorItems, ...bsonItems]; } /** @@ -327,7 +395,8 @@ function createOperatorPositionCompletions( const operatorEntries = allEntries.filter( (e) => e.meta !== 'bson' && e.meta !== 'variable' && !KEY_POSITION_OPERATORS.has(e.value), ); - return operatorEntries.map((entry) => mapOperatorToCompletionItem(entry, range, monaco, fieldBsonTypes)); + // Strip outer braces from snippets — at operator position the user is already inside { } + return operatorEntries.map((entry) => mapOperatorToCompletionItem(entry, range, monaco, fieldBsonTypes, true)); } /** diff --git a/src/webviews/documentdbQuery/registerLanguage.ts b/src/webviews/documentdbQuery/registerLanguage.ts index 7624ff4b7..79fdf80f7 100644 --- a/src/webviews/documentdbQuery/registerLanguage.ts +++ b/src/webviews/documentdbQuery/registerLanguage.ts @@ -112,6 +112,18 @@ async function doRegisterLanguage(monaco: typeof monacoEditor): Promise { const cursorContext = detectCursorContext(text, cursorOffset, fieldLookup); + // Trace-level logging for debugging context-sensitive completions + console.debug('[documentdb-query] provideCompletionItems', { + text, + cursorOffset, + position: { line: position.lineNumber, col: position.column }, + charBefore, + isDollarPrefix: charBefore === '$', + cursorContext, + editorType: parsed?.editorType, + sessionId, + }); + // Build completion items based on context const items = createCompletionItems({ editorType: parsed?.editorType, @@ -122,6 +134,12 @@ async function doRegisterLanguage(monaco: typeof monacoEditor): Promise { cursorContext, }); + console.debug('[documentdb-query] completionItems', { + count: items.length, + labels: items.map((i) => i.label), + contextPosition: cursorContext.position, + }); + return { suggestions: items }; }, }); From e4837ce54526886501237a67f90c5d23abe18bc1 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Mar 2026 18:26:04 +0000 Subject: [PATCH 071/128] Step 4.5(6): clean up completion item styling - Remove 'detail' field from operator completions (was noisy) - Move category label to label.description (matches field items pattern) - Move entry.description to documentation (was in both detail and desc) - Combine description text + docs link in documentation field - Add range/insertText to trace logging for snippet debugging --- .../documentdbQueryCompletionProvider.test.ts | 7 ++++--- .../documentdbQueryCompletionProvider.ts | 18 ++++++++++-------- .../documentdbQuery/registerLanguage.ts | 9 +++++++++ 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index 0b2d78a12..3e1f31948 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -159,8 +159,9 @@ describe('documentdbQueryCompletionProvider', () => { expect(item.kind).toBe(mockCompletionItemKind.Operator); expect(item.insertText).toBe('$eq'); expect(item.insertTextRules).toBeUndefined(); - expect(item.detail).toBe('Matches values equal to a specified value.'); - expect(item.documentation).toBeUndefined(); // no link + expect(item.documentation).toEqual({ + value: 'Matches values equal to a specified value.', + }); expect(item.range).toBe(testRange); }); @@ -195,7 +196,7 @@ describe('documentdbQueryCompletionProvider', () => { expect(item.insertText).toBe('ObjectId("${1:hex}")'); expect(item.insertTextRules).toBe(mockInsertTextRule.InsertAsSnippet); expect(item.documentation).toEqual({ - value: '[DocumentDB Docs](https://docs.example.com/objectid)', + value: 'Creates a new ObjectId value.\n\n[DocumentDB Docs](https://docs.example.com/objectid)', }); }); diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts index 150932e71..dae3484a6 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts @@ -142,21 +142,23 @@ export function mapOperatorToCompletionItem( const categoryLabel = getCategoryLabel(entry.meta); + // Build documentation: description text + optional docs link + let documentationValue = entry.description; + if (entry.link) { + documentationValue += `\n\n[DocumentDB Docs](${entry.link})`; + } + return { label: { label: entry.value, - detail: ` ${categoryLabel}`, - description: entry.description, + description: categoryLabel, }, kind: getCompletionKindForMeta(entry.meta, monaco.languages.CompletionItemKind), insertText, insertTextRules: hasSnippet ? monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet : undefined, - detail: entry.description, - documentation: entry.link - ? { - value: `[DocumentDB Docs](${entry.link})`, - } - : undefined, + documentation: { + value: documentationValue, + }, sortText: sortPrefix ? `${sortPrefix}${entry.value}` : undefined, range, }; diff --git a/src/webviews/documentdbQuery/registerLanguage.ts b/src/webviews/documentdbQuery/registerLanguage.ts index 79fdf80f7..faeba3f66 100644 --- a/src/webviews/documentdbQuery/registerLanguage.ts +++ b/src/webviews/documentdbQuery/registerLanguage.ts @@ -119,6 +119,8 @@ async function doRegisterLanguage(monaco: typeof monacoEditor): Promise { position: { line: position.lineNumber, col: position.column }, charBefore, isDollarPrefix: charBefore === '$', + wordInfo: { word: wordInfo.word, startColumn: wordInfo.startColumn, endColumn: wordInfo.endColumn }, + range, cursorContext, editorType: parsed?.editorType, sessionId, @@ -138,6 +140,13 @@ async function doRegisterLanguage(monaco: typeof monacoEditor): Promise { count: items.length, labels: items.map((i) => i.label), contextPosition: cursorContext.position, + // Log first 3 items with their insertText for snippet debugging + sampleItems: items.slice(0, 3).map((i) => ({ + label: i.label, + insertText: i.insertText, + insertTextRules: i.insertTextRules, + range: i.range, + })), }); return { suggestions: items }; From 63d0056937ddb7794eb545f5b092034e589eb52d Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Mar 2026 18:37:30 +0000 Subject: [PATCH 072/128] Step 4.5(7): fix $gt snippet variable escape bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause: Monaco snippet syntax interprets $gt as a variable reference (variable 'gt'), which resolves to empty string for unknown variables. Result: { $gt: ${1:value} } produces '{ : value }'. Fix: escapeSnippetDollars() escapes $ before letters ($gt → \$gt) while preserving tab stop syntax (${1:value} unchanged). BSON constructors like ObjectId("${1:hex}") are unaffected. This was the root cause of POC Observation 2 (T5 ⚠️ PARTIAL). --- .../documentdbQueryCompletionProvider.test.ts | 35 ++++++++++++++++--- .../documentdbQueryCompletionProvider.ts | 23 ++++++++++++ 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index 3e1f31948..b336fe0a2 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -15,6 +15,7 @@ import { clearAllCompletionContexts, setCompletionContext } from './completionSt import { type CursorContext } from './cursorContext'; import { createCompletionItems, + escapeSnippetDollars, getCategoryLabel, getCompletionKindForMeta, getMetaTagsForEditorType, @@ -176,7 +177,7 @@ describe('documentdbQueryCompletionProvider', () => { const item = mapOperatorToCompletionItem(entry, testRange, mockMonaco); expect(getLabelText(item.label)).toBe('$gt'); - expect(item.insertText).toBe('{ $gt: ${1:value} }'); + expect(item.insertText).toBe('{ \\$gt: ${1:value} }'); expect(item.insertTextRules).toBe(mockInsertTextRule.InsertAsSnippet); }); @@ -794,6 +795,30 @@ describe('documentdbQueryCompletionProvider', () => { }); }); + describe('escapeSnippetDollars', () => { + test('escapes $ before operator names in snippets', () => { + expect(escapeSnippetDollars('{ $gt: ${1:value} }')).toBe('{ \\$gt: ${1:value} }'); + }); + + test('preserves tab stop syntax', () => { + expect(escapeSnippetDollars('${1:value}')).toBe('${1:value}'); + expect(escapeSnippetDollars('$1')).toBe('$1'); + }); + + test('escapes multiple operator names', () => { + expect(escapeSnippetDollars('{ $and: [{ $gt: ${1:value} }] }')).toBe('{ \\$and: [{ \\$gt: ${1:value} }] }'); + }); + + test('does not escape BSON constructor snippets', () => { + expect(escapeSnippetDollars('ObjectId("${1:hex}")')).toBe('ObjectId("${1:hex}")'); + }); + + test('escapes stripped operator snippets', () => { + expect(escapeSnippetDollars('$gt: ${1:value}')).toBe('\\$gt: ${1:value}'); + expect(escapeSnippetDollars('$in: [${1:value}]')).toBe('\\$in: [${1:value}]'); + }); + }); + // --------------------------------------------------------------- // Context-sensitive completions (Step 4.5) // --------------------------------------------------------------- @@ -954,7 +979,7 @@ describe('documentdbQueryCompletionProvider', () => { // Operators should have their full brace-wrapping snippets at value position const gtItem = items.find((i) => getLabelText(i.label) === '$gt'); - expect(gtItem?.insertText).toBe('{ $gt: ${1:value} }'); + expect(gtItem?.insertText).toBe('{ \\$gt: ${1:value} }'); }); test('operators sort before BSON constructors', () => { @@ -1137,13 +1162,13 @@ describe('documentdbQueryCompletionProvider', () => { // At operator position, snippets should NOT have outer { } const gtItem = items.find((i) => getLabelText(i.label) === '$gt'); - expect(gtItem?.insertText).toBe('$gt: ${1:value}'); + expect(gtItem?.insertText).toBe('\\$gt: ${1:value}'); const inItem = items.find((i) => getLabelText(i.label) === '$in'); - expect(inItem?.insertText).toBe('$in: [${1:value}]'); + expect(inItem?.insertText).toBe('\\$in: [${1:value}]'); const regexItem = items.find((i) => getLabelText(i.label) === '$regex'); - expect(regexItem?.insertText).toBe('$regex: /${1:pattern}/'); + expect(regexItem?.insertText).toBe('\\$regex: /${1:pattern}/'); }); }); diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts index dae3484a6..e95083c33 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts @@ -114,6 +114,26 @@ export function stripOuterBraces(snippet: string): string { return snippet; } +/** + * Escapes literal `$` signs in snippet text that would be misinterpreted + * as Monaco snippet variables. + * + * In Monaco snippet syntax, `$name` is a variable reference (resolves to empty + * for unknown variables). Operator names like `$gt` in snippets get consumed + * as variable references, producing empty output instead of the literal `$gt`. + * + * This function escapes `$` when followed by a letter (`$gt` → `\$gt`) + * while preserving tab stop syntax (`${1:value}` and `$1` are unchanged). + * + * @param snippet - the snippet text to escape + * @returns the snippet with literal `$` signs escaped + */ +export function escapeSnippetDollars(snippet: string): string { + // Match $ followed by a letter (variable reference like $gt, $in, $regex) + // Don't match $ followed by { (tab stop like ${1:value}) or digit ($1) + return snippet.replace(/\$(?=[a-zA-Z])/g, '\\$'); +} + /** * Maps an OperatorEntry from documentdb-constants to a Monaco CompletionItem. * @@ -139,6 +159,9 @@ export function mapOperatorToCompletionItem( if (stripBraces && hasSnippet) { insertText = stripOuterBraces(insertText); } + if (hasSnippet) { + insertText = escapeSnippetDollars(insertText); + } const categoryLabel = getCategoryLabel(entry.meta); From c80ebcd7052eedbac8458bd0c4bfabde9fce89ec Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Mar 2026 18:52:59 +0000 Subject: [PATCH 073/128] Step 4.5(8): refactor completions into folder + type-aware value suggestions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactor: - Extract completion logic into completions/ folder: - snippetUtils.ts: stripOuterBraces, escapeSnippetDollars - mapCompletionItems.ts: operator/field → CompletionItem mapping - typeSuggestions.ts: type-aware value suggestions (NEW) - createCompletionItems.ts: main entry point with context branching - index.ts: barrel exports - documentdbQueryCompletionProvider.ts now re-exports from completions/ New feature — type-aware value suggestions at value position: - bool fields → true, false (as first completions) - int/double/long/decimal → range query { $gt: ▪, $lt: ▪ } - string → regex snippet, empty string literal - date → ISODate constructor, date range snippet - objectid → ObjectId constructor - null → null literal - array → $elemMatch, $size snippets Suggestions get sort prefix 00_ (before operators at 0_). First suggestion is preselected. 197 tests pass across 6 suites. Build + lint clean. --- .../completions/createCompletionItems.ts | 232 +++++++++ .../documentdbQuery/completions/index.ts | 30 ++ .../completions/mapCompletionItems.ts | 140 ++++++ .../completions/snippetUtils.ts | 42 ++ .../completions/typeSuggestions.ts | 180 +++++++ .../documentdbQueryCompletionProvider.test.ts | 164 ++++++ .../documentdbQueryCompletionProvider.ts | 465 +----------------- 7 files changed, 814 insertions(+), 439 deletions(-) create mode 100644 src/webviews/documentdbQuery/completions/createCompletionItems.ts create mode 100644 src/webviews/documentdbQuery/completions/index.ts create mode 100644 src/webviews/documentdbQuery/completions/mapCompletionItems.ts create mode 100644 src/webviews/documentdbQuery/completions/snippetUtils.ts create mode 100644 src/webviews/documentdbQuery/completions/typeSuggestions.ts diff --git a/src/webviews/documentdbQuery/completions/createCompletionItems.ts b/src/webviews/documentdbQuery/completions/createCompletionItems.ts new file mode 100644 index 000000000..8d141b1a1 --- /dev/null +++ b/src/webviews/documentdbQuery/completions/createCompletionItems.ts @@ -0,0 +1,232 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Context-sensitive completion item creation for the `documentdb-query` language. + * + * This module is the main entry point for the completion provider. It uses + * cursor context detection to determine which completions to show and delegates + * to specialized functions for each context (key, value, operator, etc.). + */ + +import { + FILTER_COMPLETION_META, + getFilteredCompletions, + PROJECTION_COMPLETION_META, +} from '@vscode-documentdb/documentdb-constants'; +// eslint-disable-next-line import/no-internal-modules +import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; +import { getCompletionContext } from '../completionStore'; +import { type CursorContext } from '../cursorContext'; +import { EditorType } from '../languageConfig'; +import { mapFieldToCompletionItem, mapOperatorToCompletionItem } from './mapCompletionItems'; +import { createTypeSuggestions } from './typeSuggestions'; + +/** + * Parameters for creating completion items. + */ +export interface CreateCompletionItemsParams { + /** The editor type parsed from the model URI (undefined if URI doesn't match). */ + editorType: EditorType | undefined; + /** The session ID for looking up dynamic field completions. */ + sessionId: string | undefined; + /** The range to insert completions at. */ + range: monacoEditor.IRange; + /** Whether the cursor is immediately after a '$' character. */ + isDollarPrefix: boolean; + /** The Monaco editor API. */ + monaco: typeof monacoEditor; + /** + * Optional BSON types of the field the cursor is operating on. + * When provided, operators are sorted by type relevance. + */ + fieldBsonTypes?: readonly string[]; + /** + * Optional cursor context from the heuristic cursor position detector. + * When provided, completions are filtered based on the semantic position + * of the cursor. When undefined, falls back to showing all completions. + */ + cursorContext?: CursorContext; +} + +/** + * Operator values that are valid at key position (root level of a query object). + * + * Exported for testing. + */ +export const KEY_POSITION_OPERATORS = new Set([ + '$and', + '$or', + '$nor', + '$not', + '$comment', + '$expr', + '$jsonSchema', + '$text', + '$where', +]); + +/** + * Returns the completion meta tags appropriate for the given editor type. + * + * Exported for testing. + */ +export function getMetaTagsForEditorType(editorType: EditorType | undefined): readonly string[] { + switch (editorType) { + case EditorType.Filter: + return FILTER_COMPLETION_META; + case EditorType.Project: + case EditorType.Sort: + return PROJECTION_COMPLETION_META; + default: + return FILTER_COMPLETION_META; + } +} + +/** + * Creates Monaco completion items based on the editor context. + * + * Main entry point called by the CompletionItemProvider. + * + * Context routing: + * - **key**: field names + key-position operators ($and, $or, etc.) + * - **value**: type suggestions + operators (with braces) + BSON constructors + * - **operator**: operators (without braces) with type-aware sorting + * - **array-element**: same as key position + * - **unknown**: all completions (backward compatible fallback) + */ +export function createCompletionItems(params: CreateCompletionItemsParams): monacoEditor.languages.CompletionItem[] { + const { editorType, sessionId, range, monaco, fieldBsonTypes, cursorContext } = params; + + if (!cursorContext || cursorContext.position === 'unknown') { + return createAllCompletions(editorType, sessionId, range, monaco, fieldBsonTypes); + } + + switch (cursorContext.position) { + case 'key': + case 'array-element': + return createKeyPositionCompletions(editorType, sessionId, range, monaco); + + case 'value': { + const fieldBsonType = cursorContext.fieldBsonType; + return createValuePositionCompletions(editorType, range, monaco, fieldBsonType); + } + + case 'operator': { + const bsonTypes = cursorContext.fieldBsonType ? [cursorContext.fieldBsonType] : fieldBsonTypes; + return createOperatorPositionCompletions(editorType, range, monaco, bsonTypes); + } + + default: + return createAllCompletions(editorType, sessionId, range, monaco, fieldBsonTypes); + } +} + +// ---------- Context-specific completion builders ---------- + +function createAllCompletions( + editorType: EditorType | undefined, + sessionId: string | undefined, + range: monacoEditor.IRange, + monaco: typeof monacoEditor, + fieldBsonTypes: readonly string[] | undefined, +): monacoEditor.languages.CompletionItem[] { + const metaTags = getMetaTagsForEditorType(editorType); + const entries = getFilteredCompletions({ meta: [...metaTags] }); + const operatorItems = entries.map((entry) => mapOperatorToCompletionItem(entry, range, monaco, fieldBsonTypes)); + const fieldItems = getFieldCompletionItems(sessionId, range, monaco); + return [...fieldItems, ...operatorItems]; +} + +function createKeyPositionCompletions( + editorType: EditorType | undefined, + sessionId: string | undefined, + range: monacoEditor.IRange, + monaco: typeof monacoEditor, +): monacoEditor.languages.CompletionItem[] { + const metaTags = getMetaTagsForEditorType(editorType); + const allEntries = getFilteredCompletions({ meta: [...metaTags] }); + + const keyEntries = allEntries.filter((e) => KEY_POSITION_OPERATORS.has(e.value)); + const operatorItems = keyEntries.map((entry) => { + const item = mapOperatorToCompletionItem(entry, range, monaco); + item.sortText = `1_${entry.value}`; + return item; + }); + + const fieldItems = getFieldCompletionItems(sessionId, range, monaco); + return [...fieldItems, ...operatorItems]; +} + +/** + * Value position completions: + * 1. Type-aware suggestions (sort `00_`) — e.g., `true`/`false` for booleans + * 2. Query operators with brace-wrapping snippets (sort `0_`) + * 3. BSON constructors (sort `1_`) + */ +function createValuePositionCompletions( + editorType: EditorType | undefined, + range: monacoEditor.IRange, + monaco: typeof monacoEditor, + fieldBsonType: string | undefined, +): monacoEditor.languages.CompletionItem[] { + const metaTags = getMetaTagsForEditorType(editorType); + const allEntries = getFilteredCompletions({ meta: [...metaTags] }); + + // 1. Type-aware suggestions (highest priority) + const typeSuggestions = createTypeSuggestions(fieldBsonType, range, monaco); + + // 2. Operators (sort prefix 0_), excluding key-position-only operators + const operatorEntries = allEntries.filter( + (e) => e.meta !== 'bson' && e.meta !== 'variable' && !KEY_POSITION_OPERATORS.has(e.value), + ); + const operatorItems = operatorEntries.map((entry) => { + const item = mapOperatorToCompletionItem(entry, range, monaco); + item.sortText = `0_${entry.value}`; + return item; + }); + + // 3. BSON constructors (sort prefix 1_) + const bsonEntries = allEntries.filter((e) => e.meta === 'bson'); + const bsonItems = bsonEntries.map((entry) => { + const item = mapOperatorToCompletionItem(entry, range, monaco); + item.sortText = `1_${entry.value}`; + return item; + }); + + return [...typeSuggestions, ...operatorItems, ...bsonItems]; +} + +function createOperatorPositionCompletions( + editorType: EditorType | undefined, + range: monacoEditor.IRange, + monaco: typeof monacoEditor, + fieldBsonTypes: readonly string[] | undefined, +): monacoEditor.languages.CompletionItem[] { + const metaTags = getMetaTagsForEditorType(editorType); + const allEntries = getFilteredCompletions({ meta: [...metaTags] }); + + const operatorEntries = allEntries.filter( + (e) => e.meta !== 'bson' && e.meta !== 'variable' && !KEY_POSITION_OPERATORS.has(e.value), + ); + return operatorEntries.map((entry) => mapOperatorToCompletionItem(entry, range, monaco, fieldBsonTypes, true)); +} + +function getFieldCompletionItems( + sessionId: string | undefined, + range: monacoEditor.IRange, + monaco: typeof monacoEditor, +): monacoEditor.languages.CompletionItem[] { + const fieldItems: monacoEditor.languages.CompletionItem[] = []; + if (sessionId) { + const context = getCompletionContext(sessionId); + if (context) { + for (const field of context.fields) { + fieldItems.push(mapFieldToCompletionItem(field, range, monaco)); + } + } + } + return fieldItems; +} diff --git a/src/webviews/documentdbQuery/completions/index.ts b/src/webviews/documentdbQuery/completions/index.ts new file mode 100644 index 000000000..2474f9ab3 --- /dev/null +++ b/src/webviews/documentdbQuery/completions/index.ts @@ -0,0 +1,30 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Completion items for the `documentdb-query` language. + * + * This folder contains context-sensitive completion logic: + * - `createCompletionItems.ts` — main entry point, context branching + * - `mapCompletionItems.ts` — operator/field → CompletionItem mapping + * - `typeSuggestions.ts` — type-aware value suggestions (bool → true/false, etc.) + * - `snippetUtils.ts` — snippet text manipulation (brace stripping, $ escaping) + */ + +export { + KEY_POSITION_OPERATORS, + createCompletionItems, + getMetaTagsForEditorType, + type CreateCompletionItemsParams, +} from './createCompletionItems'; +export { + getCategoryLabel, + getCompletionKindForMeta, + getOperatorSortPrefix, + mapFieldToCompletionItem, + mapOperatorToCompletionItem, +} from './mapCompletionItems'; +export { escapeSnippetDollars, stripOuterBraces } from './snippetUtils'; +export { createTypeSuggestions } from './typeSuggestions'; diff --git a/src/webviews/documentdbQuery/completions/mapCompletionItems.ts b/src/webviews/documentdbQuery/completions/mapCompletionItems.ts new file mode 100644 index 000000000..692aef5df --- /dev/null +++ b/src/webviews/documentdbQuery/completions/mapCompletionItems.ts @@ -0,0 +1,140 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Functions for mapping operator and field data to Monaco CompletionItems. + */ + +import { type OperatorEntry } from '@vscode-documentdb/documentdb-constants'; +// eslint-disable-next-line import/no-internal-modules +import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; +import { type FieldCompletionData } from '../../../utils/json/data-api/autocomplete/toFieldCompletionItems'; +import { escapeSnippetDollars, stripOuterBraces } from './snippetUtils'; + +/** + * Maps a meta tag category to a Monaco CompletionItemKind. + */ +export function getCompletionKindForMeta( + meta: string, + kinds: typeof monacoEditor.languages.CompletionItemKind, +): number { + if (meta.startsWith('query')) return kinds.Operator; + if (meta.startsWith('expr')) return kinds.Function; + if (meta === 'bson') return kinds.Constructor; + if (meta === 'stage') return kinds.Module; + if (meta === 'accumulator') return kinds.Method; + if (meta === 'update') return kinds.Property; + if (meta === 'variable') return kinds.Variable; + if (meta === 'window') return kinds.Event; + if (meta === 'field:identifier') return kinds.Field; + return kinds.Text; +} + +/** + * Computes a sortText prefix for an operator based on its type relevance + * to the given field BSON types. + * + * - `"0_"` — Type-relevant: operator's `applicableBsonTypes` intersects with `fieldBsonTypes` + * - `"1_"` — Universal: operator has no `applicableBsonTypes` (works on any type) + * - `"2_"` — Non-matching: operator's `applicableBsonTypes` is set but doesn't match + * + * Returns `undefined` when no field type info is available (no sorting override). + */ +export function getOperatorSortPrefix( + entry: OperatorEntry, + fieldBsonTypes: readonly string[] | undefined, +): string | undefined { + if (!fieldBsonTypes || fieldBsonTypes.length === 0) { + return undefined; + } + + if (!entry.applicableBsonTypes || entry.applicableBsonTypes.length === 0) { + return '1_'; + } + + const hasMatch = entry.applicableBsonTypes.some((t) => fieldBsonTypes.includes(t)); + return hasMatch ? '0_' : '2_'; +} + +/** + * Extracts a human-readable category label from a meta tag. + * `'query:comparison'` → `'comparison'`, `'bson'` → `'bson'` + */ +export function getCategoryLabel(meta: string): string { + const colonIndex = meta.indexOf(':'); + return colonIndex >= 0 ? meta.substring(colonIndex + 1) : meta; +} + +/** + * Maps an OperatorEntry from documentdb-constants to a Monaco CompletionItem. + * + * Pure function — safe for unit testing without a Monaco runtime. + * + * @param entry - the operator entry to map + * @param range - the insertion range + * @param monaco - the Monaco API + * @param fieldBsonTypes - optional BSON types of the field for type-aware sorting + * @param shouldStripBraces - when true, strip outer `{ }` from snippets (for operator position) + */ +export function mapOperatorToCompletionItem( + entry: OperatorEntry, + range: monacoEditor.IRange, + monaco: typeof monacoEditor, + fieldBsonTypes?: readonly string[], + shouldStripBraces?: boolean, +): monacoEditor.languages.CompletionItem { + const hasSnippet = !!entry.snippet; + const sortPrefix = getOperatorSortPrefix(entry, fieldBsonTypes); + let insertText = hasSnippet ? entry.snippet! : entry.value; + if (shouldStripBraces && hasSnippet) { + insertText = stripOuterBraces(insertText); + } + if (hasSnippet) { + insertText = escapeSnippetDollars(insertText); + } + + const categoryLabel = getCategoryLabel(entry.meta); + + let documentationValue = entry.description; + if (entry.link) { + documentationValue += `\n\n[DocumentDB Docs](${entry.link})`; + } + + return { + label: { + label: entry.value, + description: categoryLabel, + }, + kind: getCompletionKindForMeta(entry.meta, monaco.languages.CompletionItemKind), + insertText, + insertTextRules: hasSnippet ? monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet : undefined, + documentation: { + value: documentationValue, + }, + sortText: sortPrefix ? `${sortPrefix}${entry.value}` : undefined, + range, + }; +} + +/** + * Maps a FieldCompletionData entry to a Monaco CompletionItem. + * + * Fields are given a sort prefix of `"0_"` so they appear before operators. + */ +export function mapFieldToCompletionItem( + field: FieldCompletionData, + range: monacoEditor.IRange, + monaco: typeof monacoEditor, +): monacoEditor.languages.CompletionItem { + const sparseIndicator = field.isSparse ? ' (sparse)' : ''; + return { + label: field.fieldName, + kind: monaco.languages.CompletionItemKind.Field, + insertText: field.insertText, + detail: `${field.displayType}${sparseIndicator}`, + sortText: `0_${field.fieldName}`, + range, + }; +} diff --git a/src/webviews/documentdbQuery/completions/snippetUtils.ts b/src/webviews/documentdbQuery/completions/snippetUtils.ts new file mode 100644 index 000000000..e43b7f70c --- /dev/null +++ b/src/webviews/documentdbQuery/completions/snippetUtils.ts @@ -0,0 +1,42 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Utility functions for manipulating Monaco snippet text. + */ + +/** + * Strips the outermost `{ ` and ` }` from an operator snippet. + * + * Operator snippets in documentdb-constants are designed for value position + * (e.g., `{ $gt: ${1:value} }`). At operator position, the user is already + * inside braces, so the outer wrapping must be removed to avoid double-nesting. + * + * Only strips if the snippet starts with `'{ '` and ends with `' }'`. + * Inner brackets/braces are preserved: + * - `{ $in: [${1:value}] }` → `$in: [${1:value}]` + * - `{ $gt: ${1:value} }` → `$gt: ${1:value}` + */ +export function stripOuterBraces(snippet: string): string { + if (snippet.startsWith('{ ') && snippet.endsWith(' }')) { + return snippet.slice(2, -2); + } + return snippet; +} + +/** + * Escapes literal `$` signs in snippet text that would be misinterpreted + * as Monaco snippet variables. + * + * In Monaco snippet syntax, `$name` is a variable reference (resolves to empty + * for unknown variables). Operator names like `$gt` in snippets get consumed + * as variable references, producing empty output instead of the literal `$gt`. + * + * This function escapes `$` when followed by a letter (`$gt` → `\$gt`) + * while preserving tab stop syntax (`${1:value}` and `$1` are unchanged). + */ +export function escapeSnippetDollars(snippet: string): string { + return snippet.replace(/\$(?=[a-zA-Z])/g, '\\$'); +} diff --git a/src/webviews/documentdbQuery/completions/typeSuggestions.ts b/src/webviews/documentdbQuery/completions/typeSuggestions.ts new file mode 100644 index 000000000..ee99f5662 --- /dev/null +++ b/src/webviews/documentdbQuery/completions/typeSuggestions.ts @@ -0,0 +1,180 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Type-aware value suggestions for the completion provider. + * + * When the cursor is at a value position and the field's BSON type is known, + * this module provides contextual suggestions that match the field type: + * - Boolean fields → `true`, `false` + * - Number fields → range query snippet `{ $gt: ▪, $lt: ▪ }` + * - String fields → regex snippet, empty string literal + * - Date fields → ISODate constructor, date range snippet + * - ObjectId fields → ObjectId constructor + * - Null fields → `null` + * - Array fields → `$elemMatch` snippet + * + * These suggestions appear at the top of the completion list (sort prefix `00_`) + * to surface the most common patterns for each type. + */ + +// eslint-disable-next-line import/no-internal-modules +import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; +import { escapeSnippetDollars } from './snippetUtils'; + +/** A type suggestion definition. */ +interface TypeSuggestionDef { + /** Display label */ + label: string; + /** Text or snippet to insert */ + insertText: string; + /** Whether insertText is a snippet (has tab stops) */ + isSnippet: boolean; + /** Description shown in the label area */ + description: string; + /** Documentation shown in the details panel */ + documentation?: string; +} + +/** + * Maps BSON type strings to curated value suggestions. + * + * Each type maps to an array of suggestions ordered by likelihood. + * The suggestions use Monaco snippet syntax for tab stops. + */ +const TYPE_SUGGESTIONS: Record = { + bool: [ + { label: 'true', insertText: 'true', isSnippet: false, description: 'boolean literal' }, + { label: 'false', insertText: 'false', isSnippet: false, description: 'boolean literal' }, + ], + int: numberSuggestions(), + double: numberSuggestions(), + long: numberSuggestions(), + decimal: numberSuggestions(), + string: [ + { + label: '{ $regex: /▪/ }', + insertText: '{ $regex: /${1:pattern}/ }', + isSnippet: true, + description: 'pattern match', + documentation: 'Match documents where this string field matches a regular expression pattern.', + }, + { + label: '""', + insertText: '"${1:text}"', + isSnippet: true, + description: 'string literal', + }, + ], + date: [ + { + label: 'ISODate("▪")', + insertText: 'ISODate("${1:yyyy-MM-ddTHH:mm:ssZ}")', + isSnippet: true, + description: 'date value', + }, + { + label: '{ $gt: ISODate("▪"), $lt: ISODate("▪") }', + insertText: '{ $gt: ISODate("${1:start}"), $lt: ISODate("${2:end}") }', + isSnippet: true, + description: 'date range', + documentation: 'Match documents where this date field falls within a range.', + }, + ], + objectid: [ + { + label: 'ObjectId("▪")', + insertText: 'ObjectId("${1:hex}")', + isSnippet: true, + description: 'objectid value', + }, + ], + null: [{ label: 'null', insertText: 'null', isSnippet: false, description: 'null literal' }], + array: [ + { + label: '{ $elemMatch: { ▪ } }', + insertText: '{ $elemMatch: { ${1:query} } }', + isSnippet: true, + description: 'match array element', + documentation: 'Match documents where at least one array element matches the query.', + }, + { + label: '{ $size: ▪ }', + insertText: '{ $size: ${1:length} }', + isSnippet: true, + description: 'array length', + documentation: 'Match documents where the array has the specified number of elements.', + }, + ], +}; + +/** Shared number-type suggestions (int, double, long, decimal). */ +function numberSuggestions(): readonly TypeSuggestionDef[] { + return [ + { + label: '{ $gt: ▪, $lt: ▪ }', + insertText: '{ $gt: ${1:min}, $lt: ${2:max} }', + isSnippet: true, + description: 'range query', + documentation: 'Match documents where this numeric field falls within a range.', + }, + { + label: '{ $gte: ▪ }', + insertText: '{ $gte: ${1:value} }', + isSnippet: true, + description: 'minimum value', + }, + ]; +} + +/** + * Creates type-aware value suggestions based on the field's BSON type. + * + * Returns an array of high-priority completion items (sort prefix `00_`) + * that appear at the top of the value-position completion list. + * + * Returns an empty array when the BSON type is unknown or has no specific suggestions. + * + * @param fieldBsonType - BSON type string from the schema (e.g., 'int', 'string', 'bool') + * @param range - the insertion range + * @param monaco - the Monaco API + */ +export function createTypeSuggestions( + fieldBsonType: string | undefined, + range: monacoEditor.IRange, + monaco: typeof monacoEditor, +): monacoEditor.languages.CompletionItem[] { + if (!fieldBsonType) { + return []; + } + + const suggestions = TYPE_SUGGESTIONS[fieldBsonType]; + if (!suggestions) { + return []; + } + + return suggestions.map((def, index) => { + let insertText = def.insertText; + if (def.isSnippet) { + insertText = escapeSnippetDollars(insertText); + } + + return { + label: { + label: def.label, + description: def.description, + }, + kind: def.isSnippet + ? monaco.languages.CompletionItemKind.Snippet + : monaco.languages.CompletionItemKind.Value, + insertText, + insertTextRules: def.isSnippet ? monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet : undefined, + documentation: def.documentation ? { value: def.documentation } : undefined, + sortText: `00_${String(index).padStart(2, '0')}`, + preselect: index === 0, + range, + }; + }); +} diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index b336fe0a2..4aa647bb7 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -15,6 +15,7 @@ import { clearAllCompletionContexts, setCompletionContext } from './completionSt import { type CursorContext } from './cursorContext'; import { createCompletionItems, + createTypeSuggestions, escapeSnippetDollars, getCategoryLabel, getCompletionKindForMeta, @@ -1254,4 +1255,167 @@ describe('documentdbQueryCompletionProvider', () => { }); }); }); + + // --------------------------------------------------------------- + // Type-aware value suggestions + // --------------------------------------------------------------- + describe('createTypeSuggestions', () => { + const mockMonaco = createMockMonaco(); + + test('returns empty array for undefined bsonType', () => { + const items = createTypeSuggestions(undefined, testRange, mockMonaco); + expect(items).toHaveLength(0); + }); + + test('returns empty array for unknown bsonType', () => { + const items = createTypeSuggestions('unknownType', testRange, mockMonaco); + expect(items).toHaveLength(0); + }); + + test('returns true/false for boolean fields', () => { + const items = createTypeSuggestions('bool', testRange, mockMonaco); + expect(items).toHaveLength(2); + + const labels = items.map((i) => getLabelText(i.label)); + expect(labels).toContain('true'); + expect(labels).toContain('false'); + + // Plain text, not snippets + const trueItem = items.find((i) => getLabelText(i.label) === 'true'); + expect(trueItem?.insertText).toBe('true'); + expect(trueItem?.insertTextRules).toBeUndefined(); + expect(trueItem?.kind).toBe(mockCompletionItemKind.Value); + }); + + test('returns range query for int fields', () => { + const items = createTypeSuggestions('int', testRange, mockMonaco); + expect(items.length).toBeGreaterThanOrEqual(1); + + const labels = items.map((i) => getLabelText(i.label)); + expect(labels[0]).toContain('$gt'); + expect(labels[0]).toContain('$lt'); + + // Should be a snippet + expect(items[0].kind).toBe(mockCompletionItemKind.Snippet); + }); + + test('returns regex and empty string for string fields', () => { + const items = createTypeSuggestions('string', testRange, mockMonaco); + expect(items.length).toBeGreaterThanOrEqual(1); + + const labels = items.map((i) => getLabelText(i.label)); + expect(labels).toContain('{ $regex: /▪/ }'); + }); + + test('returns ISODate for date fields', () => { + const items = createTypeSuggestions('date', testRange, mockMonaco); + expect(items.length).toBeGreaterThanOrEqual(1); + + const labels = items.map((i) => getLabelText(i.label)); + expect(labels).toContain('ISODate("▪")'); + }); + + test('returns ObjectId for objectid fields', () => { + const items = createTypeSuggestions('objectid', testRange, mockMonaco); + expect(items).toHaveLength(1); + + expect(getLabelText(items[0].label)).toBe('ObjectId("▪")'); + }); + + test('returns null for null fields', () => { + const items = createTypeSuggestions('null', testRange, mockMonaco); + expect(items).toHaveLength(1); + + expect(getLabelText(items[0].label)).toBe('null'); + expect(items[0].insertText).toBe('null'); + }); + + test('returns elemMatch and size for array fields', () => { + const items = createTypeSuggestions('array', testRange, mockMonaco); + expect(items.length).toBeGreaterThanOrEqual(2); + + const labels = items.map((i) => getLabelText(i.label)); + expect(labels).toContain('{ $elemMatch: { ▪ } }'); + expect(labels).toContain('{ $size: ▪ }'); + }); + + test('suggestions have sort prefix 00_ (highest priority)', () => { + const items = createTypeSuggestions('bool', testRange, mockMonaco); + for (const item of items) { + expect(item.sortText).toMatch(/^00_/); + } + }); + + test('first suggestion is preselected', () => { + const items = createTypeSuggestions('int', testRange, mockMonaco); + expect(items[0].preselect).toBe(true); + }); + }); + + describe('type suggestions in value position integration', () => { + const mockMonaco = createMockMonaco(); + + test('boolean field at value position shows true/false first', () => { + const context: CursorContext = { position: 'value', fieldName: 'isActive', fieldBsonType: 'bool' }; + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: context, + }); + + const labels = items.map((i) => getLabelText(i.label)); + // true/false should be present + expect(labels).toContain('true'); + expect(labels).toContain('false'); + + // Operators should also be present + expect(labels).toContain('$eq'); + expect(labels).toContain('$gt'); + + // true/false should sort before operators (00_ < 0_) + const trueItem = items.find((i) => getLabelText(i.label) === 'true'); + const eqItem = items.find((i) => getLabelText(i.label) === '$eq'); + expect(trueItem!.sortText! < eqItem!.sortText!).toBe(true); + }); + + test('int field at value position shows range query first', () => { + const context: CursorContext = { position: 'value', fieldName: 'age', fieldBsonType: 'int' }; + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: context, + }); + + // Range query suggestion should be first (sort 00_00) + const first = items[0]; + expect(getLabelText(first.label)).toContain('$gt'); + expect(first.sortText).toBe('00_00'); + }); + + test('unknown type at value position has no type suggestions', () => { + const context: CursorContext = { position: 'value', fieldName: 'data' }; + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: context, + }); + + // No type suggestions, but operators and BSON should still be present + const labels = items.map((i) => getLabelText(i.label)); + expect(labels).toContain('$eq'); + expect(labels).toContain('ObjectId'); + + // No items with 00_ sort prefix + expect(items.filter((i) => i.sortText?.startsWith('00_'))).toHaveLength(0); + }); + }); }); diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts index e95083c33..3d3b74643 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts @@ -4,442 +4,29 @@ *--------------------------------------------------------------------------------------------*/ /** - * Completion provider logic for the `documentdb-query` language. - * - * This module is structured for testability: the core mapping function - * (`mapOperatorToCompletionItem`) and the item-building function - * (`createCompletionItems`) are pure functions that receive their Monaco - * dependency through parameters rather than imports. - * - * Context routing uses the model URI to determine which completions to show: - * - `documentdb://filter/*` → query operators + BSON constructors - * - `documentdb://project/*` → field identifiers (future) - * - `documentdb://sort/*` → field identifiers (future) - */ - -import { - FILTER_COMPLETION_META, - getFilteredCompletions, - PROJECTION_COMPLETION_META, - type OperatorEntry, -} from '@vscode-documentdb/documentdb-constants'; -// eslint-disable-next-line import/no-internal-modules -import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; -import { type FieldCompletionData } from '../../utils/json/data-api/autocomplete/toFieldCompletionItems'; -import { getCompletionContext } from './completionStore'; -import { type CursorContext } from './cursorContext'; -import { EditorType } from './languageConfig'; - -/** - * Maps a meta tag category to a Monaco CompletionItemKind. - * - * This mapping is extracted as a pure function for testability. - */ -export function getCompletionKindForMeta( - meta: string, - kinds: typeof monacoEditor.languages.CompletionItemKind, -): number { - if (meta.startsWith('query')) return kinds.Operator; - if (meta.startsWith('expr')) return kinds.Function; - if (meta === 'bson') return kinds.Constructor; - if (meta === 'stage') return kinds.Module; - if (meta === 'accumulator') return kinds.Method; - if (meta === 'update') return kinds.Property; - if (meta === 'variable') return kinds.Variable; - if (meta === 'window') return kinds.Event; - if (meta === 'field:identifier') return kinds.Field; - return kinds.Text; -} - -/** - * Computes a sortText prefix for an operator based on its type relevance - * to the given field BSON types. - * - * - `"0_"` — Type-relevant: operator's `applicableBsonTypes` intersects with `fieldBsonTypes` - * - `"1_"` — Universal: operator has no `applicableBsonTypes` (works on any type) - * - `"2_"` — Non-matching: operator's `applicableBsonTypes` is set but doesn't match - * - * Returns `undefined` when no field type info is available (no sorting override). - */ -export function getOperatorSortPrefix( - entry: OperatorEntry, - fieldBsonTypes: readonly string[] | undefined, -): string | undefined { - if (!fieldBsonTypes || fieldBsonTypes.length === 0) { - return undefined; - } - - if (!entry.applicableBsonTypes || entry.applicableBsonTypes.length === 0) { - // Universal operator — no type restriction - return '1_'; - } - - const hasMatch = entry.applicableBsonTypes.some((t) => fieldBsonTypes.includes(t)); - return hasMatch ? '0_' : '2_'; -} - -/** - * Extracts a human-readable category label from a meta tag. - * - * Examples: - * - `'query:comparison'` → `'comparison'` - * - `'query:logical'` → `'logical'` - * - `'bson'` → `'bson'` - * - `'variable'` → `'variable'` - */ -export function getCategoryLabel(meta: string): string { - const colonIndex = meta.indexOf(':'); - return colonIndex >= 0 ? meta.substring(colonIndex + 1) : meta; -} - -/** - * Strips the outermost `{ ` and ` }` from an operator snippet. - * - * Operator snippets in documentdb-constants are designed for value position - * (e.g., `{ $gt: ${1:value} }`). At operator position, the user is already - * inside braces, so the outer wrapping must be removed to avoid double-nesting. - * - * Only strips if the snippet starts with `'{ '` and ends with `' }'`. - * Inner brackets/braces are preserved: - * - `{ $in: [${1:value}] }` → `$in: [${1:value}]` - * - `{ $gt: ${1:value} }` → `$gt: ${1:value}` - * - * @param snippet - the original snippet string - * @returns the snippet with outer braces stripped, or the original if not wrapped - */ -export function stripOuterBraces(snippet: string): string { - if (snippet.startsWith('{ ') && snippet.endsWith(' }')) { - return snippet.slice(2, -2); - } - return snippet; -} - -/** - * Escapes literal `$` signs in snippet text that would be misinterpreted - * as Monaco snippet variables. - * - * In Monaco snippet syntax, `$name` is a variable reference (resolves to empty - * for unknown variables). Operator names like `$gt` in snippets get consumed - * as variable references, producing empty output instead of the literal `$gt`. - * - * This function escapes `$` when followed by a letter (`$gt` → `\$gt`) - * while preserving tab stop syntax (`${1:value}` and `$1` are unchanged). - * - * @param snippet - the snippet text to escape - * @returns the snippet with literal `$` signs escaped - */ -export function escapeSnippetDollars(snippet: string): string { - // Match $ followed by a letter (variable reference like $gt, $in, $regex) - // Don't match $ followed by { (tab stop like ${1:value}) or digit ($1) - return snippet.replace(/\$(?=[a-zA-Z])/g, '\\$'); -} - -/** - * Maps an OperatorEntry from documentdb-constants to a Monaco CompletionItem. - * - * This is a pure function with no side effects — safe for unit testing - * without a Monaco runtime. - * - * @param entry - the operator entry to map - * @param range - the insertion range - * @param monaco - the Monaco API - * @param fieldBsonTypes - optional BSON types of the field for type-aware sorting - * @param stripBraces - when true, strip outer `{ }` from snippets (for operator position) - */ -export function mapOperatorToCompletionItem( - entry: OperatorEntry, - range: monacoEditor.IRange, - monaco: typeof monacoEditor, - fieldBsonTypes?: readonly string[], - stripBraces?: boolean, -): monacoEditor.languages.CompletionItem { - const hasSnippet = !!entry.snippet; - const sortPrefix = getOperatorSortPrefix(entry, fieldBsonTypes); - let insertText = hasSnippet ? entry.snippet! : entry.value; - if (stripBraces && hasSnippet) { - insertText = stripOuterBraces(insertText); - } - if (hasSnippet) { - insertText = escapeSnippetDollars(insertText); - } - - const categoryLabel = getCategoryLabel(entry.meta); - - // Build documentation: description text + optional docs link - let documentationValue = entry.description; - if (entry.link) { - documentationValue += `\n\n[DocumentDB Docs](${entry.link})`; - } - - return { - label: { - label: entry.value, - description: categoryLabel, - }, - kind: getCompletionKindForMeta(entry.meta, monaco.languages.CompletionItemKind), - insertText, - insertTextRules: hasSnippet ? monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet : undefined, - documentation: { - value: documentationValue, - }, - sortText: sortPrefix ? `${sortPrefix}${entry.value}` : undefined, - range, - }; -} - -/** - * Maps a FieldCompletionData entry to a Monaco CompletionItem. - * - * Fields are given a sort prefix of `"0_"` so they appear before operators - * in the completion list. - */ -export function mapFieldToCompletionItem( - field: FieldCompletionData, - range: monacoEditor.IRange, - monaco: typeof monacoEditor, -): monacoEditor.languages.CompletionItem { - const sparseIndicator = field.isSparse ? ' (sparse)' : ''; - return { - label: field.fieldName, - kind: monaco.languages.CompletionItemKind.Field, - insertText: field.insertText, - detail: `${field.displayType}${sparseIndicator}`, - sortText: `0_${field.fieldName}`, - range, - }; -} - -/** - * Parameters for creating completion items. - */ -export interface CreateCompletionItemsParams { - /** The editor type parsed from the model URI (undefined if URI doesn't match). */ - editorType: EditorType | undefined; - /** The session ID for looking up dynamic field completions. */ - sessionId: string | undefined; - /** The range to insert completions at. */ - range: monacoEditor.IRange; - /** Whether the cursor is immediately after a '$' character. */ - // TODO: WIP — isDollarPrefix is passed but not yet consumed by createCompletionItems(). - // Will be used to filter/prioritize $-prefixed operators vs constructors. - isDollarPrefix: boolean; - /** The Monaco editor API. */ - monaco: typeof monacoEditor; - /** - * Optional BSON types of the field the cursor is operating on. - * When provided, operators are sorted by type relevance: - * type-matching first, universal second, non-matching last. - */ - fieldBsonTypes?: readonly string[]; - /** - * Optional cursor context from the heuristic cursor position detector. - * When provided, completions are filtered based on the semantic position - * of the cursor (key, value, operator, array-element). - * When undefined, falls back to showing all completions (backward compatible). - */ - cursorContext?: CursorContext; -} - -/** - * Returns the completion meta tags appropriate for the given editor type. - * - * Exported for testing. - */ -export function getMetaTagsForEditorType(editorType: EditorType | undefined): readonly string[] { - switch (editorType) { - case EditorType.Filter: - return FILTER_COMPLETION_META; - case EditorType.Project: - case EditorType.Sort: - return PROJECTION_COMPLETION_META; - default: - // Default to filter completions for unknown/unmatched URIs - return FILTER_COMPLETION_META; - } -} - -/** - * Operator values that are valid at key position (root level of a query object). - * These are logical operators and top-level query operators that take a document-level position, - * as opposed to value-level operators like $gt, $regex, etc. - * - * Exported for testing. - */ -export const KEY_POSITION_OPERATORS = new Set([ - '$and', - '$or', - '$nor', - '$not', - '$comment', - '$expr', - '$jsonSchema', - '$text', - '$where', -]); - -/** - * Creates Monaco completion items based on the editor context. - * - * This function is the main entry point called by the CompletionItemProvider. - * It delegates to `documentdb-constants` for the operator data and maps - * each entry to a Monaco CompletionItem. - * - * When a `cursorContext` is provided, completions are filtered based on the - * semantic position of the cursor: - * - **key**: field names + key-position operators ($and, $or, etc.) - * - **value**: query operators (with braces in snippet) + BSON constructors - * - **operator**: query operators (without braces in snippet) with type-aware sorting - * - **array-element**: same as key position - * - **unknown**: all completions (backward compatible fallback) - */ -export function createCompletionItems(params: CreateCompletionItemsParams): monacoEditor.languages.CompletionItem[] { - const { editorType, sessionId, range, monaco, fieldBsonTypes, cursorContext } = params; - - // If no cursor context → fall back to showing everything (backward compatible) - if (!cursorContext || cursorContext.position === 'unknown') { - return createAllCompletions(editorType, sessionId, range, monaco, fieldBsonTypes); - } - - switch (cursorContext.position) { - case 'key': - case 'array-element': - return createKeyPositionCompletions(editorType, sessionId, range, monaco); - - case 'value': - return createValuePositionCompletions(editorType, range, monaco); - - case 'operator': { - const bsonTypes = cursorContext.fieldBsonType ? [cursorContext.fieldBsonType] : fieldBsonTypes; - return createOperatorPositionCompletions(editorType, range, monaco, bsonTypes); - } - - default: - return createAllCompletions(editorType, sessionId, range, monaco, fieldBsonTypes); - } -} - -/** - * Returns all completions (operators + fields) — the pre-4.5 behavior. - * Used as fallback when cursor context is unknown or not provided. - */ -function createAllCompletions( - editorType: EditorType | undefined, - sessionId: string | undefined, - range: monacoEditor.IRange, - monaco: typeof monacoEditor, - fieldBsonTypes: readonly string[] | undefined, -): monacoEditor.languages.CompletionItem[] { - const metaTags = getMetaTagsForEditorType(editorType); - const entries = getFilteredCompletions({ meta: [...metaTags] }); - const operatorItems = entries.map((entry) => mapOperatorToCompletionItem(entry, range, monaco, fieldBsonTypes)); - - const fieldItems = getFieldCompletionItems(sessionId, range, monaco); - return [...fieldItems, ...operatorItems]; -} - -/** - * Returns completions appropriate for key position: - * field names + key-position operators ($and, $or, $nor, $not, $comment, $expr, $jsonSchema, $text, $where). - * - * Fields get sort prefix `0_`, operators get `1_`. - */ -function createKeyPositionCompletions( - editorType: EditorType | undefined, - sessionId: string | undefined, - range: monacoEditor.IRange, - monaco: typeof monacoEditor, -): monacoEditor.languages.CompletionItem[] { - const metaTags = getMetaTagsForEditorType(editorType); - const allEntries = getFilteredCompletions({ meta: [...metaTags] }); - - // Filter to only key-position operators - const keyEntries = allEntries.filter((e) => KEY_POSITION_OPERATORS.has(e.value)); - const operatorItems = keyEntries.map((entry) => { - const item = mapOperatorToCompletionItem(entry, range, monaco); - // Give operators a `1_` prefix so fields sort first - item.sortText = `1_${entry.value}`; - return item; - }); - - const fieldItems = getFieldCompletionItems(sessionId, range, monaco); - return [...fieldItems, ...operatorItems]; -} - -/** - * Returns completions appropriate for value position: - * Query operators first (with full brace-wrapping snippets), then BSON constructors. - * - * Operators use their original snippets which include `{ }` — this is correct - * at value position because the user needs the nested object - * (e.g., `{ _id: }` → selecting `$gt` inserts `{ $gt: value }`). - */ -function createValuePositionCompletions( - editorType: EditorType | undefined, - range: monacoEditor.IRange, - monaco: typeof monacoEditor, -): monacoEditor.languages.CompletionItem[] { - const metaTags = getMetaTagsForEditorType(editorType); - const allEntries = getFilteredCompletions({ meta: [...metaTags] }); - - // Operators first (sort prefix 0_), excluding key-position-only operators - const operatorEntries = allEntries.filter( - (e) => e.meta !== 'bson' && e.meta !== 'variable' && !KEY_POSITION_OPERATORS.has(e.value), - ); - const operatorItems = operatorEntries.map((entry) => { - const item = mapOperatorToCompletionItem(entry, range, monaco); - item.sortText = `0_${entry.value}`; - return item; - }); - - // BSON constructors second (sort prefix 1_) - const bsonEntries = allEntries.filter((e) => e.meta === 'bson'); - const bsonItems = bsonEntries.map((entry) => { - const item = mapOperatorToCompletionItem(entry, range, monaco); - item.sortText = `1_${entry.value}`; - return item; - }); - - return [...operatorItems, ...bsonItems]; -} - -/** - * Returns completions appropriate for operator position (inside `{ field: { | } }`): - * Query operators (comparison, element, array, evaluation, bitwise) excluding key-position-only operators. - * Type-aware sorting is applied when field BSON types are available. - */ -function createOperatorPositionCompletions( - editorType: EditorType | undefined, - range: monacoEditor.IRange, - monaco: typeof monacoEditor, - fieldBsonTypes: readonly string[] | undefined, -): monacoEditor.languages.CompletionItem[] { - const metaTags = getMetaTagsForEditorType(editorType); - const allEntries = getFilteredCompletions({ meta: [...metaTags] }); - - // Exclude key-position-only operators and BSON constructors - const operatorEntries = allEntries.filter( - (e) => e.meta !== 'bson' && e.meta !== 'variable' && !KEY_POSITION_OPERATORS.has(e.value), - ); - // Strip outer braces from snippets — at operator position the user is already inside { } - return operatorEntries.map((entry) => mapOperatorToCompletionItem(entry, range, monaco, fieldBsonTypes, true)); -} - -/** - * Retrieves field completion items from the completion store for the given session. - */ -function getFieldCompletionItems( - sessionId: string | undefined, - range: monacoEditor.IRange, - monaco: typeof monacoEditor, -): monacoEditor.languages.CompletionItem[] { - const fieldItems: monacoEditor.languages.CompletionItem[] = []; - if (sessionId) { - const context = getCompletionContext(sessionId); - if (context) { - for (const field of context.fields) { - fieldItems.push(mapFieldToCompletionItem(field, range, monaco)); - } - } - } - return fieldItems; -} + * Barrel re-export for the completions module. + * + * The completion provider logic has been refactored into the `completions/` folder: + * - `completions/createCompletionItems.ts` — main entry point, context branching + * - `completions/mapCompletionItems.ts` — operator/field → CompletionItem mapping + * - `completions/typeSuggestions.ts` — type-aware value suggestions + * - `completions/snippetUtils.ts` — snippet text manipulation + * + * This file preserves the original import path for existing consumers. + */ + +// eslint-disable-next-line no-restricted-exports +export { + KEY_POSITION_OPERATORS, + createCompletionItems, + createTypeSuggestions, + escapeSnippetDollars, + getCategoryLabel, + getCompletionKindForMeta, + getMetaTagsForEditorType, + getOperatorSortPrefix, + mapFieldToCompletionItem, + mapOperatorToCompletionItem, + stripOuterBraces, + type CreateCompletionItemsParams, +} from './completions'; From c039c7713f864b430fd20f670ca95dc2e4c6173b Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Mar 2026 18:57:31 +0000 Subject: [PATCH 074/128] fix: align type suggestion keys with BSONTypes enum values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The schema analyzer uses BSONTypes enum strings ('boolean', 'int32', 'decimal128') while the type suggestions used shortened names ('bool', 'int', 'decimal'). Fix the TYPE_SUGGESTIONS keys to match: - bool → boolean - int → int32 - decimal → decimal128 - Added: number (generic BSONTypes.Number) Also noted the type-name mismatch between schema-analyzer BSONTypes ('int32') and documentdb-constants applicableBsonTypes ('int') — tracked as a future normalization task. --- .../completions/typeSuggestions.ts | 13 ++++++++++--- .../documentdbQueryCompletionProvider.test.ts | 15 +++++++++------ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/webviews/documentdbQuery/completions/typeSuggestions.ts b/src/webviews/documentdbQuery/completions/typeSuggestions.ts index ee99f5662..637c2c068 100644 --- a/src/webviews/documentdbQuery/completions/typeSuggestions.ts +++ b/src/webviews/documentdbQuery/completions/typeSuggestions.ts @@ -45,14 +45,21 @@ interface TypeSuggestionDef { * The suggestions use Monaco snippet syntax for tab stops. */ const TYPE_SUGGESTIONS: Record = { - bool: [ + // BSONTypes.Boolean = 'boolean' + boolean: [ { label: 'true', insertText: 'true', isSnippet: false, description: 'boolean literal' }, { label: 'false', insertText: 'false', isSnippet: false, description: 'boolean literal' }, ], - int: numberSuggestions(), + // BSONTypes.Int32 = 'int32' + int32: numberSuggestions(), + // BSONTypes.Double = 'double' double: numberSuggestions(), + // BSONTypes.Long = 'long' long: numberSuggestions(), - decimal: numberSuggestions(), + // BSONTypes.Decimal128 = 'decimal128' + decimal128: numberSuggestions(), + // BSONTypes.Number = 'number' (generic number without specific subtype) + number: numberSuggestions(), string: [ { label: '{ $regex: /▪/ }', diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index 4aa647bb7..6a2a1f741 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -1123,6 +1123,9 @@ describe('documentdbQueryCompletionProvider', () => { }); test('applies type-aware sorting when fieldBsonType is available', () => { + // Uses 'int' (documentdb-constants naming) rather than 'int32' (BSONTypes) + // because applicableBsonTypes in operators uses the constants naming. + // TODO: normalize type names between schema-analyzer and documentdb-constants const typedContext: CursorContext = { position: 'operator', fieldName: 'age', @@ -1273,7 +1276,7 @@ describe('documentdbQueryCompletionProvider', () => { }); test('returns true/false for boolean fields', () => { - const items = createTypeSuggestions('bool', testRange, mockMonaco); + const items = createTypeSuggestions('boolean', testRange, mockMonaco); expect(items).toHaveLength(2); const labels = items.map((i) => getLabelText(i.label)); @@ -1288,7 +1291,7 @@ describe('documentdbQueryCompletionProvider', () => { }); test('returns range query for int fields', () => { - const items = createTypeSuggestions('int', testRange, mockMonaco); + const items = createTypeSuggestions('int32', testRange, mockMonaco); expect(items.length).toBeGreaterThanOrEqual(1); const labels = items.map((i) => getLabelText(i.label)); @@ -1340,14 +1343,14 @@ describe('documentdbQueryCompletionProvider', () => { }); test('suggestions have sort prefix 00_ (highest priority)', () => { - const items = createTypeSuggestions('bool', testRange, mockMonaco); + const items = createTypeSuggestions('boolean', testRange, mockMonaco); for (const item of items) { expect(item.sortText).toMatch(/^00_/); } }); test('first suggestion is preselected', () => { - const items = createTypeSuggestions('int', testRange, mockMonaco); + const items = createTypeSuggestions('int32', testRange, mockMonaco); expect(items[0].preselect).toBe(true); }); }); @@ -1356,7 +1359,7 @@ describe('documentdbQueryCompletionProvider', () => { const mockMonaco = createMockMonaco(); test('boolean field at value position shows true/false first', () => { - const context: CursorContext = { position: 'value', fieldName: 'isActive', fieldBsonType: 'bool' }; + const context: CursorContext = { position: 'value', fieldName: 'isActive', fieldBsonType: 'boolean' }; const items = createCompletionItems({ editorType: EditorType.Filter, sessionId: undefined, @@ -1382,7 +1385,7 @@ describe('documentdbQueryCompletionProvider', () => { }); test('int field at value position shows range query first', () => { - const context: CursorContext = { position: 'value', fieldName: 'age', fieldBsonType: 'int' }; + const context: CursorContext = { position: 'value', fieldName: 'age', fieldBsonType: 'int32' }; const items = createCompletionItems({ editorType: EditorType.Filter, sessionId: undefined, From 0862db0f4326938f325676870c048cf86bfda619 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Mon, 16 Mar 2026 19:00:19 +0000 Subject: [PATCH 075/128] fix: use realistic example date in ISODate snippet placeholders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace format pattern 'yyyy-MM-ddTHH:mm:ssZ' with a valid example '2025-01-01T00:00:00Z'. The format pattern was confusing — users typed over it with values like '2222-11-11T11:11:111' which fail ISODate validation. Also update date range snippet with realistic start/end dates. --- packages/documentdb-constants/src/bsonConstructors.ts | 2 +- src/webviews/documentdbQuery/completions/typeSuggestions.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/documentdb-constants/src/bsonConstructors.ts b/packages/documentdb-constants/src/bsonConstructors.ts index 83377bbd1..5e08a22d7 100644 --- a/packages/documentdb-constants/src/bsonConstructors.ts +++ b/packages/documentdb-constants/src/bsonConstructors.ts @@ -22,7 +22,7 @@ const bsonConstructors: readonly OperatorEntry[] = [ value: 'ISODate', meta: META_BSON, description: 'Creates a date object from an ISO 8601 date string.', - snippet: 'ISODate("${1:yyyy-MM-ddTHH:mm:ssZ}")', + snippet: 'ISODate("${1:2025-01-01T00:00:00Z}")', }, { value: 'NumberLong', diff --git a/src/webviews/documentdbQuery/completions/typeSuggestions.ts b/src/webviews/documentdbQuery/completions/typeSuggestions.ts index 637c2c068..b7927bd54 100644 --- a/src/webviews/documentdbQuery/completions/typeSuggestions.ts +++ b/src/webviews/documentdbQuery/completions/typeSuggestions.ts @@ -78,13 +78,13 @@ const TYPE_SUGGESTIONS: Record = { date: [ { label: 'ISODate("▪")', - insertText: 'ISODate("${1:yyyy-MM-ddTHH:mm:ssZ}")', + insertText: 'ISODate("${1:2025-01-01T00:00:00Z}")', isSnippet: true, description: 'date value', }, { label: '{ $gt: ISODate("▪"), $lt: ISODate("▪") }', - insertText: '{ $gt: ISODate("${1:start}"), $lt: ISODate("${2:end}") }', + insertText: '{ $gt: ISODate("${1:2025-01-01T00:00:00Z}"), $lt: ISODate("${2:2025-12-31T23:59:59Z}") }', isSnippet: true, description: 'date range', documentation: 'Match documents where this date field falls within a range.', From d4a8b805792a7564159b872d14dfc77d8b5569f4 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Mar 2026 11:01:28 +0000 Subject: [PATCH 076/128] feat: enhance context-sensitive completions with structured knowledge and improved sorting --- .../documentdbQuery/completions/README.md | 97 +++++++++++++++ .../completions/completionKnowledge.ts | 95 +++++++++++++++ .../completions/createCompletionItems.ts | 57 ++++----- .../documentdbQuery/completions/index.ts | 1 + .../completions/mapCompletionItems.ts | 13 +- .../completions/typeSuggestions.ts | 77 ++++++++---- .../documentdbQueryCompletionProvider.test.ts | 115 ++++++++++++------ 7 files changed, 355 insertions(+), 100 deletions(-) create mode 100644 src/webviews/documentdbQuery/completions/README.md create mode 100644 src/webviews/documentdbQuery/completions/completionKnowledge.ts diff --git a/src/webviews/documentdbQuery/completions/README.md b/src/webviews/documentdbQuery/completions/README.md new file mode 100644 index 000000000..9e5a55205 --- /dev/null +++ b/src/webviews/documentdbQuery/completions/README.md @@ -0,0 +1,97 @@ +# Completions Module + +Context-sensitive completion items for the `documentdb-query` Monaco language. + +## Architecture + +``` +registerLanguage.ts + └─ provideCompletionItems() + │ + ├─ cursorContext.ts ← detect semantic cursor position + │ + └─ completions/ + ├─ createCompletionItems.ts ← main entry, context routing + ├─ mapCompletionItems.ts ← operator/field → CompletionItem + ├─ typeSuggestions.ts ← type-aware value suggestions + ├─ snippetUtils.ts ← snippet text manipulation + └─ completionKnowledge.ts ← curated domain rules & constants +``` + +### Flow + +1. Monaco calls `provideCompletionItems()` (registered in `registerLanguage.ts`) +2. `detectCursorContext()` scans backward from the cursor to determine the semantic position +3. `createCompletionItems()` routes to the appropriate builder: + - **key / array-element / unknown** → field names + key-position operators + - **value** → type suggestions + operators (with braces) + BSON constructors + - **operator** → operators only (braces stripped, type-aware sorting) + +## Sorting + +Completion items use `sortText` prefixes so Monaco displays them in the intended order. Lower prefixes appear higher in the list. + +### Value position + +| Prefix | Content | Example | +|--------|---------|---------| +| `00_00` – `00_99` | Type suggestions | `true` / `false` for boolean fields | +| `0_$eq` | Query operators | `{ $eq: … }`, `{ $gt: … }` | +| `1_ObjectId` | BSON constructors | `ObjectId(…)`, `ISODate(…)` | + +### Key position + +| Prefix | Content | Example | +|--------|---------|---------| +| `0_fieldName` | Schema field names | `age`, `name`, `_id` | +| `1_$and` | Key-position operators | `$and`, `$or`, `$nor` | + +### Operator position (type-aware) + +When the field's BSON type is known, operators are tiered by relevance: + +| Prefix | Tier | Meaning | +|--------|------|---------| +| `0_` | Type-relevant | Operator's `applicableBsonTypes` matches the field | +| `1a_` | Comparison (universal) | `$eq`, `$ne`, `$gt`, `$in`, etc. — no type restriction, most commonly used | +| `1b_` | Other universal | Element/evaluation/geospatial operators with no type restriction | +| `2_` | Non-matching | Operator has type restrictions that don't match the field | + +Within each tier, operators sort alphabetically by name (`$eq` < `$gt` < `$in`). + +**Example — boolean field `isActive`:** +- Tier `1a_`: `$eq`, `$gt`, `$gte`, `$in`, `$lt`, `$lte`, `$ne`, `$nin` (comparison) +- Tier `1b_`: `$exists`, `$type`, `$mod`, `$expr`, `$jsonSchema` (other universal) +- Tier `2_`: `$regex` (string-only), `$elemMatch` (array-only), `$bitsAllSet` (int/long-only) + +### Decision matrix + +``` +Has field type info? +├─ NO → no sortText override (Monaco default alphabetical) +├─ YES +│ ├─ Operator has applicableBsonTypes matching field? → "0_" +│ ├─ Operator has no applicableBsonTypes? +│ │ ├─ Is comparison operator (meta = query:comparison)? → "1a_" +│ │ └─ Other category? → "1b_" +│ └─ Operator has applicableBsonTypes NOT matching field? → "2_" +``` + +## Key concepts + +### `completionKnowledge.ts` + +Curated domain rules that go beyond the auto-generated operator registry in `documentdb-constants`. Contains: + +- **`KEY_POSITION_OPERATORS`** — operators valid only at query root level (`$and`, `$or`, etc.) +- **`LABEL_PLACEHOLDER`** — the `…` character used in display labels +- **`INFO_INDICATOR`** — the `ℹ` character prepended to example descriptions + +### Snippet handling + +Operator snippets in `documentdb-constants` include outer braces: `{ $gt: ${1:value} }`. + +- **Value position**: inserted as-is (user is replacing the entire value) +- **Operator position**: outer `{ }` stripped via `stripOuterBraces()` (user is already inside braces) +- **Key position**: outer `{ }` stripped (user is already inside the query object) +- **`$` escaping**: `escapeSnippetDollars()` prevents Monaco from treating `$gt` as a variable reference diff --git a/src/webviews/documentdbQuery/completions/completionKnowledge.ts b/src/webviews/documentdbQuery/completions/completionKnowledge.ts new file mode 100644 index 000000000..0f56e4fa4 --- /dev/null +++ b/src/webviews/documentdbQuery/completions/completionKnowledge.ts @@ -0,0 +1,95 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Completion knowledge — curated domain rules for the completion provider. + * + * This file centralises "knowledge" that is **not** part of the generic + * DocumentDB operator registry (`documentdb-constants`) but is essential for + * producing high-quality, context-sensitive completions in the query editor. + * + * ### Why this file exists + * + * The `documentdb-constants` package is auto-generated from the official + * operator reference and is intentionally kept generic — it describes *what* + * operators exist, not *where* they are syntactically valid. + * + * However the completion provider needs to know additional rules: + * + * 1. **Which operators are only valid at key (root) position?** + * `$and`, `$or`, `$nor`, etc. accept sub-queries, not field values. + * Showing them inside a field's operator list (`{ age: { $and … } }`) is + * misleading, so we need an explicit list to filter them out of + * operator-position completions and include them in key-position completions. + * + * 2. **Placeholder character for labels** + * A single Unicode character used in completion-list labels to represent + * "user fills this in". Must render well in all editors and at any font size. + * + * Adding new knowledge here keeps the completion provider self-documented and + * avoids magic values scattered across multiple files. + */ + +/** + * Operators that are syntactically valid only at the **key position** (the + * root level of a query document, or inside a `$and`/`$or`/`$nor` array + * element). + * + * These operators accept sub-expressions or arrays of sub-queries as their + * values — they do **not** operate on a specific field's BSON value. For + * example: + * + * ```js + * // ✅ Valid — key position + * { $and: [{ age: { $gt: 18 } }, { name: "Alice" }] } + * + * // ❌ Invalid — operator position on field 'age' + * { age: { $and: … } } + * ``` + * + * The completion provider uses this set to: + * - **Include** these operators at key position and array-element position + * - **Exclude** them from operator position (inside `{ field: { … } }`) + * - **Exclude** them from value position + * + * Source: DocumentDB query language specification — logical and meta operators. + */ +export const KEY_POSITION_OPERATORS = new Set([ + '$and', + '$or', + '$nor', + '$not', + '$comment', + '$expr', + '$jsonSchema', + '$text', + '$where', +]); + +/** + * Placeholder character used in completion-list **labels** to indicate where + * the user should type a value. + * + * This is purely cosmetic — the actual insertText uses Monaco snippet tab stops + * (`${1:placeholder}`). The label placeholder is what users see in the + * completion picker before selecting an item. + * + * We use the horizontal ellipsis `…` (U+2026) because: + * - It is universally understood as "something goes here" + * - It renders reliably across all monospace and proportional fonts + * - It is visually lightweight and does not distract from the operator syntax + * + * Previously we used `▪` (U+25AA, Black Small Square) but it was too subtle + * at small font sizes and less semantically clear. + */ +export const LABEL_PLACEHOLDER = '\u2026'; // … (horizontal ellipsis) + +/** + * Info indicator for completion descriptions that contain usage examples. + * + * Prepended to description strings that show example values to differentiate + * them from plain type labels (e.g., `"ℹ e.g. ends with '.com'"` vs `"string literal"`). + */ +export const INFO_INDICATOR = '\u2139'; // ℹ (information source) diff --git a/src/webviews/documentdbQuery/completions/createCompletionItems.ts b/src/webviews/documentdbQuery/completions/createCompletionItems.ts index 8d141b1a1..ea4417c1c 100644 --- a/src/webviews/documentdbQuery/completions/createCompletionItems.ts +++ b/src/webviews/documentdbQuery/completions/createCompletionItems.ts @@ -21,6 +21,7 @@ import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; import { getCompletionContext } from '../completionStore'; import { type CursorContext } from '../cursorContext'; import { EditorType } from '../languageConfig'; +import { KEY_POSITION_OPERATORS } from './completionKnowledge'; import { mapFieldToCompletionItem, mapOperatorToCompletionItem } from './mapCompletionItems'; import { createTypeSuggestions } from './typeSuggestions'; @@ -51,22 +52,9 @@ export interface CreateCompletionItemsParams { cursorContext?: CursorContext; } -/** - * Operator values that are valid at key position (root level of a query object). - * - * Exported for testing. - */ -export const KEY_POSITION_OPERATORS = new Set([ - '$and', - '$or', - '$nor', - '$not', - '$comment', - '$expr', - '$jsonSchema', - '$text', - '$where', -]); +// KEY_POSITION_OPERATORS is imported from ./completionKnowledge +// Re-export for backwards compatibility and testing +export { KEY_POSITION_OPERATORS } from './completionKnowledge'; /** * Returns the completion meta tags appropriate for the given editor type. @@ -101,7 +89,10 @@ export function createCompletionItems(params: CreateCompletionItemsParams): mona const { editorType, sessionId, range, monaco, fieldBsonTypes, cursorContext } = params; if (!cursorContext || cursorContext.position === 'unknown') { - return createAllCompletions(editorType, sessionId, range, monaco, fieldBsonTypes); + // When context is unknown (e.g., empty input, no braces), show the same + // completions as key position: field names first, then key-position operators. + // This is the common scenario when users clear the input box and start fresh. + return createKeyPositionCompletions(editorType, sessionId, range, monaco); } switch (cursorContext.position) { @@ -120,26 +111,12 @@ export function createCompletionItems(params: CreateCompletionItemsParams): mona } default: - return createAllCompletions(editorType, sessionId, range, monaco, fieldBsonTypes); + return createKeyPositionCompletions(editorType, sessionId, range, monaco); } } // ---------- Context-specific completion builders ---------- -function createAllCompletions( - editorType: EditorType | undefined, - sessionId: string | undefined, - range: monacoEditor.IRange, - monaco: typeof monacoEditor, - fieldBsonTypes: readonly string[] | undefined, -): monacoEditor.languages.CompletionItem[] { - const metaTags = getMetaTagsForEditorType(editorType); - const entries = getFilteredCompletions({ meta: [...metaTags] }); - const operatorItems = entries.map((entry) => mapOperatorToCompletionItem(entry, range, monaco, fieldBsonTypes)); - const fieldItems = getFieldCompletionItems(sessionId, range, monaco); - return [...fieldItems, ...operatorItems]; -} - function createKeyPositionCompletions( editorType: EditorType | undefined, sessionId: string | undefined, @@ -151,7 +128,9 @@ function createKeyPositionCompletions( const keyEntries = allEntries.filter((e) => KEY_POSITION_OPERATORS.has(e.value)); const operatorItems = keyEntries.map((entry) => { - const item = mapOperatorToCompletionItem(entry, range, monaco); + // Strip outer braces — the user is already inside `{ }` at key position, + // so inserting the full `{ $and: [...] }` would create double braces. + const item = mapOperatorToCompletionItem(entry, range, monaco, undefined, true); item.sortText = `1_${entry.value}`; return item; }); @@ -178,13 +157,19 @@ function createValuePositionCompletions( // 1. Type-aware suggestions (highest priority) const typeSuggestions = createTypeSuggestions(fieldBsonType, range, monaco); - // 2. Operators (sort prefix 0_), excluding key-position-only operators + // 2. Operators, excluding key-position-only operators. + // When fieldBsonType is known, apply type-aware sorting so comparison + // operators (e.g., $eq) appear above irrelevant ones (e.g., $bitsAllSet). + const fieldBsonTypes = fieldBsonType ? [fieldBsonType] : undefined; const operatorEntries = allEntries.filter( (e) => e.meta !== 'bson' && e.meta !== 'variable' && !KEY_POSITION_OPERATORS.has(e.value), ); const operatorItems = operatorEntries.map((entry) => { - const item = mapOperatorToCompletionItem(entry, range, monaco); - item.sortText = `0_${entry.value}`; + const item = mapOperatorToCompletionItem(entry, range, monaco, fieldBsonTypes); + // If type-aware sorting produced a prefix, keep it; otherwise default to 0_ + if (!item.sortText) { + item.sortText = `0_${entry.value}`; + } return item; }); diff --git a/src/webviews/documentdbQuery/completions/index.ts b/src/webviews/documentdbQuery/completions/index.ts index 2474f9ab3..1ae3c1be4 100644 --- a/src/webviews/documentdbQuery/completions/index.ts +++ b/src/webviews/documentdbQuery/completions/index.ts @@ -13,6 +13,7 @@ * - `snippetUtils.ts` — snippet text manipulation (brace stripping, $ escaping) */ +export { INFO_INDICATOR, LABEL_PLACEHOLDER } from './completionKnowledge'; export { KEY_POSITION_OPERATORS, createCompletionItems, diff --git a/src/webviews/documentdbQuery/completions/mapCompletionItems.ts b/src/webviews/documentdbQuery/completions/mapCompletionItems.ts index 692aef5df..14751f639 100644 --- a/src/webviews/documentdbQuery/completions/mapCompletionItems.ts +++ b/src/webviews/documentdbQuery/completions/mapCompletionItems.ts @@ -36,8 +36,11 @@ export function getCompletionKindForMeta( * Computes a sortText prefix for an operator based on its type relevance * to the given field BSON types. * + * Sorting tiers (ascending = higher priority): * - `"0_"` — Type-relevant: operator's `applicableBsonTypes` intersects with `fieldBsonTypes` - * - `"1_"` — Universal: operator has no `applicableBsonTypes` (works on any type) + * - `"1a_"` — Comparison operators (universal): `$eq`, `$ne`, `$gt`, `$in`, etc. + * These are the most commonly used operators for any field type. + * - `"1b_"` — Other universal operators: element, evaluation, geospatial, etc. * - `"2_"` — Non-matching: operator's `applicableBsonTypes` is set but doesn't match * * Returns `undefined` when no field type info is available (no sorting override). @@ -51,7 +54,8 @@ export function getOperatorSortPrefix( } if (!entry.applicableBsonTypes || entry.applicableBsonTypes.length === 0) { - return '1_'; + // Promote comparison operators above other universal operators + return entry.meta === 'query:comparison' ? '1a_' : '1b_'; } const hasMatch = entry.applicableBsonTypes.some((t) => fieldBsonTypes.includes(t)); @@ -122,6 +126,8 @@ export function mapOperatorToCompletionItem( * Maps a FieldCompletionData entry to a Monaco CompletionItem. * * Fields are given a sort prefix of `"0_"` so they appear before operators. + * The insert text includes a trailing `: $1` snippet so that selecting a + * field name immediately places the cursor at the value position. */ export function mapFieldToCompletionItem( field: FieldCompletionData, @@ -132,7 +138,8 @@ export function mapFieldToCompletionItem( return { label: field.fieldName, kind: monaco.languages.CompletionItemKind.Field, - insertText: field.insertText, + insertText: `${field.insertText}: \$1`, + insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet, detail: `${field.displayType}${sparseIndicator}`, sortText: `0_${field.fieldName}`, range, diff --git a/src/webviews/documentdbQuery/completions/typeSuggestions.ts b/src/webviews/documentdbQuery/completions/typeSuggestions.ts index b7927bd54..3f3770afd 100644 --- a/src/webviews/documentdbQuery/completions/typeSuggestions.ts +++ b/src/webviews/documentdbQuery/completions/typeSuggestions.ts @@ -22,8 +22,14 @@ // eslint-disable-next-line import/no-internal-modules import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; +import { INFO_INDICATOR, LABEL_PLACEHOLDER } from './completionKnowledge'; import { escapeSnippetDollars } from './snippetUtils'; +/** Shorthand for the placeholder glyph used in labels. */ +const P = LABEL_PLACEHOLDER; +/** Shorthand for the info indicator. */ +const I = INFO_INDICATOR; + /** A type suggestion definition. */ interface TypeSuggestionDef { /** Display label */ @@ -47,8 +53,8 @@ interface TypeSuggestionDef { const TYPE_SUGGESTIONS: Record = { // BSONTypes.Boolean = 'boolean' boolean: [ - { label: 'true', insertText: 'true', isSnippet: false, description: 'boolean literal' }, - { label: 'false', insertText: 'false', isSnippet: false, description: 'boolean literal' }, + { label: 'true', insertText: 'true', isSnippet: false, description: `${I} e.g. { isActive: true }` }, + { label: 'false', insertText: 'false', isSnippet: false, description: `${I} e.g. { isVerified: false }` }, ], // BSONTypes.Int32 = 'int32' int32: numberSuggestions(), @@ -62,56 +68,63 @@ const TYPE_SUGGESTIONS: Record = { number: numberSuggestions(), string: [ { - label: '{ $regex: /▪/ }', + label: `{ $regex: /${P}/ }`, insertText: '{ $regex: /${1:pattern}/ }', isSnippet: true, - description: 'pattern match', + description: `${I} e.g. ends with '.com'`, documentation: 'Match documents where this string field matches a regular expression pattern.', }, { label: '""', insertText: '"${1:text}"', isSnippet: true, - description: 'string literal', + description: `${I} e.g. "active", "pending"`, }, ], date: [ { - label: 'ISODate("▪")', - insertText: 'ISODate("${1:2025-01-01T00:00:00Z}")', + label: `ISODate("${P}")`, + insertText: `ISODate("\${1:${twoWeeksAgo()}}")`, isSnippet: true, - description: 'date value', + description: `${I} e.g. ISODate("${twoWeeksAgo()}")`, }, { - label: '{ $gt: ISODate("▪"), $lt: ISODate("▪") }', - insertText: '{ $gt: ISODate("${1:2025-01-01T00:00:00Z}"), $lt: ISODate("${2:2025-12-31T23:59:59Z}") }', + label: `{ $gt: ISODate("${P}"), $lt: ISODate("${P}") }`, + insertText: `{ $gt: ISODate("\${1:${twoWeeksAgo()}}"), $lt: ISODate("\${2:${todayISO()}}") }`, isSnippet: true, - description: 'date range', + description: `${I} e.g. last 2 weeks`, documentation: 'Match documents where this date field falls within a range.', }, + { + label: 'new Date(Date.now() - …)', + insertText: 'new Date(Date.now() - ${1:14} * 24 * 60 * 60 * 1000)', + isSnippet: true, + description: `${I} e.g. 14 days ago`, + documentation: 'Compute a date relative to now. Change the number to adjust the offset in days.', + }, ], objectid: [ { - label: 'ObjectId("▪")', + label: `ObjectId("${P}")`, insertText: 'ObjectId("${1:hex}")', isSnippet: true, - description: 'objectid value', + description: `${I} e.g. ObjectId("507f1f77...")`, }, ], - null: [{ label: 'null', insertText: 'null', isSnippet: false, description: 'null literal' }], + null: [{ label: 'null', insertText: 'null', isSnippet: false, description: `${I} e.g. { field: null }` }], array: [ { - label: '{ $elemMatch: { ▪ } }', + label: `{ $elemMatch: { ${P} } }`, insertText: '{ $elemMatch: { ${1:query} } }', isSnippet: true, - description: 'match array element', + description: `${I} e.g. tags with "urgent"`, documentation: 'Match documents where at least one array element matches the query.', }, { - label: '{ $size: ▪ }', + label: `{ $size: ${P} }`, insertText: '{ $size: ${1:length} }', isSnippet: true, - description: 'array length', + description: `${I} e.g. exactly 3 items`, documentation: 'Match documents where the array has the specified number of elements.', }, ], @@ -121,21 +134,41 @@ const TYPE_SUGGESTIONS: Record = { function numberSuggestions(): readonly TypeSuggestionDef[] { return [ { - label: '{ $gt: ▪, $lt: ▪ }', + label: `{ $gt: ${P}, $lt: ${P} }`, insertText: '{ $gt: ${1:min}, $lt: ${2:max} }', isSnippet: true, - description: 'range query', + description: `${I} e.g. between 18 and 65`, documentation: 'Match documents where this numeric field falls within a range.', }, { - label: '{ $gte: ▪ }', + label: `{ $gte: ${P} }`, insertText: '{ $gte: ${1:value} }', isSnippet: true, - description: 'minimum value', + description: `${I} e.g. at least 100`, }, ]; } +/** + * Returns an ISO 8601 timestamp for two weeks ago (UTC, midnight). + * Used as a sensible default date placeholder — recent enough to be practical. + */ +function twoWeeksAgo(): string { + const d = new Date(); + d.setUTCDate(d.getUTCDate() - 14); + d.setUTCHours(0, 0, 0, 0); + return d.toISOString().replace('.000Z', 'Z'); +} + +/** + * Returns an ISO 8601 timestamp for today (UTC, end of day). + */ +function todayISO(): string { + const d = new Date(); + d.setUTCHours(23, 59, 59, 0); + return d.toISOString().replace('.000Z', 'Z'); +} + /** * Creates type-aware value suggestions based on the field's BSON type. * diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index 6a2a1f741..e62b6ba16 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -272,13 +272,14 @@ describe('documentdbQueryCompletionProvider', () => { } }); - test('filter completions include query operators like $eq, $gt, $match', () => { + test('filter completions include query operators like $eq, $gt, $match at value position', () => { const items = createCompletionItems({ editorType: EditorType.Filter, sessionId: undefined, range: testRange, isDollarPrefix: false, monaco: mockMonaco, + cursorContext: { position: 'value', fieldName: 'x' }, }); const labels = items.map((item) => getLabelText(item.label)); @@ -287,13 +288,14 @@ describe('documentdbQueryCompletionProvider', () => { expect(labels).toContain('$in'); }); - test('filter completions include BSON constructors like ObjectId', () => { + test('filter completions include BSON constructors like ObjectId at value position', () => { const items = createCompletionItems({ editorType: EditorType.Filter, sessionId: undefined, range: testRange, isDollarPrefix: false, monaco: mockMonaco, + cursorContext: { position: 'value', fieldName: 'x' }, }); const labels = items.map((item) => getLabelText(item.label)); @@ -338,17 +340,20 @@ describe('documentdbQueryCompletionProvider', () => { expect(labels).not.toContain('$lookup'); }); - test('filter completions match getFilteredCompletions count for FILTER_COMPLETION_META', () => { + test('filter completions at value position match getFilteredCompletions count for FILTER_COMPLETION_META', () => { const items = createCompletionItems({ editorType: EditorType.Filter, sessionId: undefined, range: testRange, isDollarPrefix: false, monaco: mockMonaco, + cursorContext: { position: 'value', fieldName: 'x' }, }); const expected = getFilteredCompletions({ meta: [...FILTER_COMPLETION_META] }); - expect(items).toHaveLength(expected.length); + // Value position includes operators + BSON constructors (minus key-position operators) + expect(items.length).toBeGreaterThan(0); + expect(items.length).toBeLessThanOrEqual(expected.length); }); test('default (undefined editor type) matches filter completions', () => { @@ -389,7 +394,8 @@ describe('documentdbQueryCompletionProvider', () => { expect(item.label).toBe('age'); expect(item.kind).toBe(mockCompletionItemKind.Field); - expect(item.insertText).toBe('age'); + expect(item.insertText).toBe('age: $1'); + expect(item.insertTextRules).toBe(mockInsertTextRule.InsertAsSnippet); expect(item.detail).toBe('Number'); expect(item.sortText).toBe('0_age'); expect(item.range).toBe(testRange); @@ -423,7 +429,7 @@ describe('documentdbQueryCompletionProvider', () => { const item = mapFieldToCompletionItem(field, testRange, mockMonaco); expect(item.label).toBe('address.city'); - expect(item.insertText).toBe('"address.city"'); + expect(item.insertText).toBe('"address.city": $1'); }); }); @@ -494,12 +500,12 @@ describe('documentdbQueryCompletionProvider', () => { const fieldItem = items.find((i) => getLabelText(i.label) === 'name'); expect(fieldItem?.sortText).toBe('0_name'); - // Operators should not have a sort prefix starting with 0_ - const operatorItem = items.find((i) => getLabelText(i.label) === '$eq'); - expect(operatorItem?.sortText).toBeUndefined(); + // Key-position operators get "1_" prefix (below fields) + const andItem = items.find((i) => getLabelText(i.label) === '$and'); + expect(andItem?.sortText).toBe('1_$and'); }); - test('empty store returns only operator completions', () => { + test('empty store returns only key-position operator completions', () => { const items = createCompletionItems({ editorType: EditorType.Filter, sessionId: 'nonexistent-session', @@ -508,11 +514,14 @@ describe('documentdbQueryCompletionProvider', () => { monaco: mockMonaco, }); - const expected = getFilteredCompletions({ meta: [...FILTER_COMPLETION_META] }); - expect(items).toHaveLength(expected.length); + // Without cursorContext, falls back to key-position completions + const labels = items.map((i) => getLabelText(i.label)); + expect(labels).toContain('$and'); + expect(labels).toContain('$or'); + expect(labels).not.toContain('$gt'); }); - test('undefined sessionId returns only operator completions', () => { + test('undefined sessionId returns only key-position operator completions', () => { const items = createCompletionItems({ editorType: EditorType.Filter, sessionId: undefined, @@ -521,8 +530,11 @@ describe('documentdbQueryCompletionProvider', () => { monaco: mockMonaco, }); - const expected = getFilteredCompletions({ meta: [...FILTER_COMPLETION_META] }); - expect(items).toHaveLength(expected.length); + // Without cursorContext, falls back to key-position completions + const labels = items.map((i) => getLabelText(i.label)); + expect(labels).toContain('$and'); + expect(labels).toContain('$or'); + expect(labels).not.toContain('$gt'); }); }); @@ -537,13 +549,22 @@ describe('documentdbQueryCompletionProvider', () => { expect(getOperatorSortPrefix(entry, [])).toBeUndefined(); }); - test('returns "1_" for universal operator (no applicableBsonTypes)', () => { + test('returns "1a_" for universal comparison operator (no applicableBsonTypes)', () => { const entry: OperatorEntry = { value: '$eq', meta: 'query:comparison', description: 'Equals', }; - expect(getOperatorSortPrefix(entry, ['string'])).toBe('1_'); + expect(getOperatorSortPrefix(entry, ['string'])).toBe('1a_'); + }); + + test('returns "1b_" for universal non-comparison operator', () => { + const entry: OperatorEntry = { + value: '$exists', + meta: 'query:element', + description: 'Exists', + }; + expect(getOperatorSortPrefix(entry, ['string'])).toBe('1b_'); }); test('returns "0_" for type-relevant operator (applicableBsonTypes matches)', () => { @@ -611,14 +632,14 @@ describe('documentdbQueryCompletionProvider', () => { expect(item.sortText).toBeUndefined(); }); - test('universal operator gets "1_" prefix when fieldBsonTypes provided', () => { + test('universal comparison operator gets "1a_" prefix when fieldBsonTypes provided', () => { const entry: OperatorEntry = { value: '$eq', meta: 'query:comparison', description: 'Equals', }; const item = mapOperatorToCompletionItem(entry, testRange, mockMonaco, ['int']); - expect(item.sortText).toBe('1_$eq'); + expect(item.sortText).toBe('1a_$eq'); }); test('type-relevant operator gets "0_" prefix', () => { @@ -651,23 +672,25 @@ describe('documentdbQueryCompletionProvider', () => { clearAllCompletionContexts(); }); - test('without fieldBsonTypes, operators have no sortText (backward compatible)', () => { + test('without fieldBsonTypes, operators have no sortText at value position', () => { const items = createCompletionItems({ editorType: EditorType.Filter, sessionId: undefined, range: testRange, isDollarPrefix: false, monaco: mockMonaco, + cursorContext: { position: 'value', fieldName: 'x' }, }); const regexItem = items.find((i) => getLabelText(i.label) === '$regex'); - expect(regexItem?.sortText).toBeUndefined(); + // At value position, operators get sort prefix 0_ (not type-aware) + expect(regexItem?.sortText).toBe('0_$regex'); const eqItem = items.find((i) => getLabelText(i.label) === '$eq'); - expect(eqItem?.sortText).toBeUndefined(); + expect(eqItem?.sortText).toBe('0_$eq'); }); - test('with fieldBsonTypes=["string"], $regex gets "0_" and $size gets "2_"', () => { + test('with fieldBsonTypes=["string"] at operator position, $regex gets "0_" and $size gets "2_"', () => { const items = createCompletionItems({ editorType: EditorType.Filter, sessionId: undefined, @@ -675,6 +698,7 @@ describe('documentdbQueryCompletionProvider', () => { isDollarPrefix: false, monaco: mockMonaco, fieldBsonTypes: ['string'], + cursorContext: { position: 'operator', fieldName: 'x' }, }); const regexItem = items.find((i) => getLabelText(i.label) === '$regex'); @@ -683,12 +707,13 @@ describe('documentdbQueryCompletionProvider', () => { const sizeItem = items.find((i) => getLabelText(i.label) === '$size'); expect(sizeItem?.sortText).toBe('2_$size'); - // Universal operators like $eq get "1_" + // Comparison operators like $eq get "1a_" (promoted over other universals) const eqItem = items.find((i) => getLabelText(i.label) === '$eq'); - expect(eqItem?.sortText).toBe('1_$eq'); + expect(eqItem?.sortText).toBe('1a_$eq'); }); - test('with fieldBsonTypes=["int"], $regex gets "2_" (demoted, still present)', () => { + test('with fieldBsonTypes=["int"] at operator position, $regex gets "2_" (demoted, still present)', () => { + const context: CursorContext = { position: 'operator', fieldName: 'x' }; const items = createCompletionItems({ editorType: EditorType.Filter, sessionId: undefined, @@ -696,6 +721,7 @@ describe('documentdbQueryCompletionProvider', () => { isDollarPrefix: false, monaco: mockMonaco, fieldBsonTypes: ['int'], + cursorContext: context, }); const labels = items.map((i) => getLabelText(i.label)); @@ -710,13 +736,14 @@ describe('documentdbQueryCompletionProvider', () => { expect(bitsAllSetItem?.sortText).toBe('0_$bitsAllSet'); }); - test('all operators still present regardless of fieldBsonTypes', () => { + test('all operators still present regardless of fieldBsonTypes at operator position', () => { const itemsWithoutType = createCompletionItems({ editorType: EditorType.Filter, sessionId: undefined, range: testRange, isDollarPrefix: false, monaco: mockMonaco, + cursorContext: { position: 'operator', fieldName: 'x' }, }); const itemsWithType = createCompletionItems({ @@ -726,6 +753,7 @@ describe('documentdbQueryCompletionProvider', () => { isDollarPrefix: false, monaco: mockMonaco, fieldBsonTypes: ['int'], + cursorContext: { position: 'operator', fieldName: 'x' }, }); // Same number of items — nothing filtered out @@ -753,6 +781,7 @@ describe('documentdbQueryCompletionProvider', () => { isDollarPrefix: false, monaco: mockMonaco, fieldBsonTypes: ['int'], + cursorContext: { position: 'key', depth: 1 }, }); const fieldItem = items.find((i) => getLabelText(i.label) === 'age'); @@ -1149,9 +1178,9 @@ describe('documentdbQueryCompletionProvider', () => { const bitsItem = items.find((i) => getLabelText(i.label) === '$bitsAllSet'); expect(bitsItem?.sortText).toBe('0_$bitsAllSet'); - // $eq is universal → middle + // $eq is universal comparison → promoted tier const eqItem = items.find((i) => getLabelText(i.label) === '$eq'); - expect(eqItem?.sortText).toBe('1_$eq'); + expect(eqItem?.sortText).toBe('1a_$eq'); }); test('strips outer braces from operator snippets (Issue A fix)', () => { @@ -1219,7 +1248,7 @@ describe('documentdbQueryCompletionProvider', () => { describe('unknown position', () => { const unknownContext: CursorContext = { position: 'unknown' }; - test('falls back to showing all completions', () => { + test('falls back to key-position completions', () => { const itemsWithContext = createCompletionItems({ editorType: EditorType.Filter, sessionId: undefined, @@ -1237,13 +1266,17 @@ describe('documentdbQueryCompletionProvider', () => { monaco: mockMonaco, }); - // Same number of items + // Both should produce the same key-position completions expect(itemsWithContext).toHaveLength(itemsWithoutContext.length); + const labels = itemsWithContext.map((i) => getLabelText(i.label)); + expect(labels).toContain('$and'); + expect(labels).toContain('$or'); + expect(labels).not.toContain('$gt'); }); }); describe('no cursorContext (undefined)', () => { - test('falls back to showing all completions (backward compatible)', () => { + test('falls back to key-position completions (fields + key operators)', () => { const items = createCompletionItems({ editorType: EditorType.Filter, sessionId: undefined, @@ -1253,8 +1286,12 @@ describe('documentdbQueryCompletionProvider', () => { cursorContext: undefined, }); - const expected = getFilteredCompletions({ meta: [...FILTER_COMPLETION_META] }); - expect(items).toHaveLength(expected.length); + // Without cursorContext, shows key-position completions (fields + key operators) + const labels = items.map((i) => getLabelText(i.label)); + expect(labels).toContain('$and'); + expect(labels).toContain('$or'); + expect(labels).not.toContain('$gt'); + expect(labels).not.toContain('ObjectId'); }); }); }); @@ -1307,7 +1344,7 @@ describe('documentdbQueryCompletionProvider', () => { expect(items.length).toBeGreaterThanOrEqual(1); const labels = items.map((i) => getLabelText(i.label)); - expect(labels).toContain('{ $regex: /▪/ }'); + expect(labels).toContain('{ $regex: /…/ }'); }); test('returns ISODate for date fields', () => { @@ -1315,14 +1352,14 @@ describe('documentdbQueryCompletionProvider', () => { expect(items.length).toBeGreaterThanOrEqual(1); const labels = items.map((i) => getLabelText(i.label)); - expect(labels).toContain('ISODate("▪")'); + expect(labels).toContain('ISODate("…")'); }); test('returns ObjectId for objectid fields', () => { const items = createTypeSuggestions('objectid', testRange, mockMonaco); expect(items).toHaveLength(1); - expect(getLabelText(items[0].label)).toBe('ObjectId("▪")'); + expect(getLabelText(items[0].label)).toBe('ObjectId("…")'); }); test('returns null for null fields', () => { @@ -1338,8 +1375,8 @@ describe('documentdbQueryCompletionProvider', () => { expect(items.length).toBeGreaterThanOrEqual(2); const labels = items.map((i) => getLabelText(i.label)); - expect(labels).toContain('{ $elemMatch: { ▪ } }'); - expect(labels).toContain('{ $size: ▪ }'); + expect(labels).toContain('{ $elemMatch: { … } }'); + expect(labels).toContain('{ $size: … }'); }); test('suggestions have sort prefix 00_ (highest priority)', () => { From fa9aa8221999ed6ef1cb792486259dd6ae6583bd Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Mar 2026 11:03:37 +0000 Subject: [PATCH 077/128] feat: enhance type suggestions with improved descriptions and documentation --- .../completions/typeSuggestions.ts | 89 +++++++++++-------- 1 file changed, 54 insertions(+), 35 deletions(-) diff --git a/src/webviews/documentdbQuery/completions/typeSuggestions.ts b/src/webviews/documentdbQuery/completions/typeSuggestions.ts index 3f3770afd..2ea1d9c17 100644 --- a/src/webviews/documentdbQuery/completions/typeSuggestions.ts +++ b/src/webviews/documentdbQuery/completions/typeSuggestions.ts @@ -22,14 +22,9 @@ // eslint-disable-next-line import/no-internal-modules import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; -import { INFO_INDICATOR, LABEL_PLACEHOLDER } from './completionKnowledge'; +import { LABEL_PLACEHOLDER } from './completionKnowledge'; import { escapeSnippetDollars } from './snippetUtils'; -/** Shorthand for the placeholder glyph used in labels. */ -const P = LABEL_PLACEHOLDER; -/** Shorthand for the info indicator. */ -const I = INFO_INDICATOR; - /** A type suggestion definition. */ interface TypeSuggestionDef { /** Display label */ @@ -53,8 +48,20 @@ interface TypeSuggestionDef { const TYPE_SUGGESTIONS: Record = { // BSONTypes.Boolean = 'boolean' boolean: [ - { label: 'true', insertText: 'true', isSnippet: false, description: `${I} e.g. { isActive: true }` }, - { label: 'false', insertText: 'false', isSnippet: false, description: `${I} e.g. { isVerified: false }` }, + { + label: 'true', + insertText: 'true', + isSnippet: false, + description: 'boolean literal', + documentation: `Boolean literal \`true\`.\n\nExample: \`{ field: true }\``, + }, + { + label: 'false', + insertText: 'false', + isSnippet: false, + description: 'boolean literal', + documentation: `Boolean literal \`false\`.\n\nExample: \`{ field: false }\``, + }, ], // BSONTypes.Int32 = 'int32' int32: numberSuggestions(), @@ -68,64 +75,75 @@ const TYPE_SUGGESTIONS: Record = { number: numberSuggestions(), string: [ { - label: `{ $regex: /${P}/ }`, + label: `{ $regex: /${LABEL_PLACEHOLDER}/ }`, insertText: '{ $regex: /${1:pattern}/ }', isSnippet: true, - description: `${I} e.g. ends with '.com'`, - documentation: 'Match documents where this string field matches a regular expression pattern.', + description: 'pattern match', + documentation: `Match string fields with a regex.\n\nExample: \`{ $regex: /\\.com$/ }\` — ends with ".com"`, }, { label: '""', insertText: '"${1:text}"', isSnippet: true, - description: `${I} e.g. "active", "pending"`, + description: 'string literal', + documentation: `Exact string match.\n\nExample: \`"active"\`, \`"pending"\``, }, ], date: [ { - label: `ISODate("${P}")`, + label: `ISODate("${LABEL_PLACEHOLDER}")`, insertText: `ISODate("\${1:${twoWeeksAgo()}}")`, isSnippet: true, - description: `${I} e.g. ISODate("${twoWeeksAgo()}")`, + description: 'date value', + documentation: `Match a specific date.\n\nExample: \`ISODate("${twoWeeksAgo()}")\``, }, { - label: `{ $gt: ISODate("${P}"), $lt: ISODate("${P}") }`, + label: `{ $gt: ISODate("${LABEL_PLACEHOLDER}"), $lt: ISODate("${LABEL_PLACEHOLDER}") }`, insertText: `{ $gt: ISODate("\${1:${twoWeeksAgo()}}"), $lt: ISODate("\${2:${todayISO()}}") }`, isSnippet: true, - description: `${I} e.g. last 2 weeks`, - documentation: 'Match documents where this date field falls within a range.', + description: 'date range', + documentation: `Match dates within a range.\n\nExample: last 2 weeks — \`{ $gt: ISODate("${twoWeeksAgo()}"), $lt: ISODate("${todayISO()}") }\``, }, { - label: 'new Date(Date.now() - …)', - insertText: 'new Date(Date.now() - ${1:14} * 24 * 60 * 60 * 1000)', + label: `{ $gt: new Date(Date.now() - ${LABEL_PLACEHOLDER}) }`, + insertText: '{ $gt: new Date(Date.now() - ${1:14} * 24 * 60 * 60 * 1000) }', isSnippet: true, - description: `${I} e.g. 14 days ago`, - documentation: 'Compute a date relative to now. Change the number to adjust the offset in days.', + description: 'last N days', + documentation: `Match dates in the last N days relative to now.\n\nExample: last 14 days — \`{ $gt: new Date(Date.now() - 14 * 24 * 60 * 60 * 1000) }\``, }, ], objectid: [ { - label: `ObjectId("${P}")`, + label: `ObjectId("${LABEL_PLACEHOLDER}")`, insertText: 'ObjectId("${1:hex}")', isSnippet: true, - description: `${I} e.g. ObjectId("507f1f77...")`, + description: 'ObjectId value', + documentation: `Match by ObjectId.\n\nExample: \`ObjectId("507f1f77bcf86cd799439011")\``, + }, + ], + null: [ + { + label: 'null', + insertText: 'null', + isSnippet: false, + description: 'null literal', + documentation: `Match null or missing fields.\n\nExample: \`{ field: null }\``, }, ], - null: [{ label: 'null', insertText: 'null', isSnippet: false, description: `${I} e.g. { field: null }` }], array: [ { - label: `{ $elemMatch: { ${P} } }`, + label: `{ $elemMatch: { ${LABEL_PLACEHOLDER} } }`, insertText: '{ $elemMatch: { ${1:query} } }', isSnippet: true, - description: `${I} e.g. tags with "urgent"`, - documentation: 'Match documents where at least one array element matches the query.', + description: 'match element', + documentation: `Match arrays with at least one element satisfying the query.\n\nExample: \`{ $elemMatch: { status: "urgent" } }\``, }, { - label: `{ $size: ${P} }`, + label: `{ $size: ${LABEL_PLACEHOLDER} }`, insertText: '{ $size: ${1:length} }', isSnippet: true, - description: `${I} e.g. exactly 3 items`, - documentation: 'Match documents where the array has the specified number of elements.', + description: 'array length', + documentation: `Match arrays with exactly N elements.\n\nExample: \`{ $size: 3 }\``, }, ], }; @@ -134,17 +152,18 @@ const TYPE_SUGGESTIONS: Record = { function numberSuggestions(): readonly TypeSuggestionDef[] { return [ { - label: `{ $gt: ${P}, $lt: ${P} }`, + label: `{ $gt: ${LABEL_PLACEHOLDER}, $lt: ${LABEL_PLACEHOLDER} }`, insertText: '{ $gt: ${1:min}, $lt: ${2:max} }', isSnippet: true, - description: `${I} e.g. between 18 and 65`, - documentation: 'Match documents where this numeric field falls within a range.', + description: 'range query', + documentation: `Match numbers within a range.\n\nExample: between 18 and 65 — \`{ $gt: 18, $lt: 65 }\``, }, { - label: `{ $gte: ${P} }`, + label: `{ $gte: ${LABEL_PLACEHOLDER} }`, insertText: '{ $gte: ${1:value} }', isSnippet: true, - description: `${I} e.g. at least 100`, + description: 'minimum value', + documentation: `Match numbers greater than or equal to a value.\n\nExample: at least 100 — \`{ $gte: 100 }\``, }, ]; } From 2ce99e4a73436573db20075c78142279d29eb21b Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Mar 2026 11:26:14 +0000 Subject: [PATCH 078/128] feat: update sort prefixes for BSON constructors and enhance regex documentation --- src/webviews/documentdbQuery/completions/README.md | 4 ++-- .../completions/createCompletionItems.ts | 4 ++-- .../documentdbQuery/completions/typeSuggestions.ts | 12 +++++++++++- .../documentdbQueryCompletionProvider.test.ts | 2 +- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/webviews/documentdbQuery/completions/README.md b/src/webviews/documentdbQuery/completions/README.md index 9e5a55205..d65b99fff 100644 --- a/src/webviews/documentdbQuery/completions/README.md +++ b/src/webviews/documentdbQuery/completions/README.md @@ -36,8 +36,8 @@ Completion items use `sortText` prefixes so Monaco displays them in the intended | Prefix | Content | Example | |--------|---------|---------| | `00_00` – `00_99` | Type suggestions | `true` / `false` for boolean fields | -| `0_$eq` | Query operators | `{ $eq: … }`, `{ $gt: … }` | -| `1_ObjectId` | BSON constructors | `ObjectId(…)`, `ISODate(…)` | +| `0_$eq` – `2_$op` | Query operators (type-aware) | `{ $eq: … }`, `{ $gt: … }` | +| `3_ObjectId` | BSON constructors | `ObjectId(…)`, `ISODate(…)` | ### Key position diff --git a/src/webviews/documentdbQuery/completions/createCompletionItems.ts b/src/webviews/documentdbQuery/completions/createCompletionItems.ts index ea4417c1c..58fe8f417 100644 --- a/src/webviews/documentdbQuery/completions/createCompletionItems.ts +++ b/src/webviews/documentdbQuery/completions/createCompletionItems.ts @@ -173,11 +173,11 @@ function createValuePositionCompletions( return item; }); - // 3. BSON constructors (sort prefix 1_) + // 3. BSON constructors (sort prefix 3_ — after all operator tiers: 0_, 1a_, 1b_, 2_) const bsonEntries = allEntries.filter((e) => e.meta === 'bson'); const bsonItems = bsonEntries.map((entry) => { const item = mapOperatorToCompletionItem(entry, range, monaco); - item.sortText = `1_${entry.value}`; + item.sortText = `3_${entry.value}`; return item; }); diff --git a/src/webviews/documentdbQuery/completions/typeSuggestions.ts b/src/webviews/documentdbQuery/completions/typeSuggestions.ts index 2ea1d9c17..575e0f45b 100644 --- a/src/webviews/documentdbQuery/completions/typeSuggestions.ts +++ b/src/webviews/documentdbQuery/completions/typeSuggestions.ts @@ -79,7 +79,17 @@ const TYPE_SUGGESTIONS: Record = { insertText: '{ $regex: /${1:pattern}/ }', isSnippet: true, description: 'pattern match', - documentation: `Match string fields with a regex.\n\nExample: \`{ $regex: /\\.com$/ }\` — ends with ".com"`, + documentation: + 'Match string fields with a regex pattern.\n\n' + + 'Example — ends with `.com`:\n```\n{ $regex: /\\.com$/ }\n```', + }, + { + label: '{ $regex: /\\.com$/ }', + insertText: '{ $regex: /${1:\\.com$}/ }', + isSnippet: true, + description: `ends with .com - pattern match`, + documentation: + 'Example pattern match for: ends with `.com`:\n```\n{ $regex: /\\.com$/ }\n```', }, { label: '""', diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index e62b6ba16..e51eecad5 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -1025,7 +1025,7 @@ describe('documentdbQueryCompletionProvider', () => { const gtItem = items.find((i) => getLabelText(i.label) === '$gt'); const objectIdItem = items.find((i) => getLabelText(i.label) === 'ObjectId'); expect(gtItem?.sortText).toBe('0_$gt'); - expect(objectIdItem?.sortText).toBe('1_ObjectId'); + expect(objectIdItem?.sortText).toBe('3_ObjectId'); }); test('does NOT show key-position operators ($and, $or)', () => { From a352a7575a29c39e6ec4bcb9da084726f82aca54 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Mar 2026 11:43:19 +0000 Subject: [PATCH 079/128] feat: enhance completion item structure and improve error diagnostics for unknown identifiers --- .../completions/mapCompletionItems.ts | 6 +++-- .../documentdbQueryCompletionProvider.test.ts | 7 +++--- .../documentdbQueryValidator.test.ts | 23 ++++++++++++++---- .../documentdbQueryValidator.ts | 24 +++++++++++++++---- 4 files changed, 46 insertions(+), 14 deletions(-) diff --git a/src/webviews/documentdbQuery/completions/mapCompletionItems.ts b/src/webviews/documentdbQuery/completions/mapCompletionItems.ts index 14751f639..43305c836 100644 --- a/src/webviews/documentdbQuery/completions/mapCompletionItems.ts +++ b/src/webviews/documentdbQuery/completions/mapCompletionItems.ts @@ -136,11 +136,13 @@ export function mapFieldToCompletionItem( ): monacoEditor.languages.CompletionItem { const sparseIndicator = field.isSparse ? ' (sparse)' : ''; return { - label: field.fieldName, + label: { + label: field.fieldName, + description: `${field.displayType}${sparseIndicator}`, + }, kind: monaco.languages.CompletionItemKind.Field, insertText: `${field.insertText}: \$1`, insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet, - detail: `${field.displayType}${sparseIndicator}`, sortText: `0_${field.fieldName}`, range, }; diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index e51eecad5..b095d4336 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -392,11 +392,10 @@ describe('documentdbQueryCompletionProvider', () => { const item = mapFieldToCompletionItem(field, testRange, mockMonaco); - expect(item.label).toBe('age'); + expect(item.label).toEqual({ label: 'age', description: 'Number' }); expect(item.kind).toBe(mockCompletionItemKind.Field); expect(item.insertText).toBe('age: $1'); expect(item.insertTextRules).toBe(mockInsertTextRule.InsertAsSnippet); - expect(item.detail).toBe('Number'); expect(item.sortText).toBe('0_age'); expect(item.range).toBe(testRange); }); @@ -413,7 +412,7 @@ describe('documentdbQueryCompletionProvider', () => { const item = mapFieldToCompletionItem(field, testRange, mockMonaco); - expect(item.detail).toBe('String (sparse)'); + expect((item.label as { description: string }).description).toBe('String (sparse)'); }); test('uses pre-escaped insertText for special field names', () => { @@ -428,7 +427,7 @@ describe('documentdbQueryCompletionProvider', () => { const item = mapFieldToCompletionItem(field, testRange, mockMonaco); - expect(item.label).toBe('address.city'); + expect((item.label as { label: string }).label).toBe('address.city'); expect(item.insertText).toBe('"address.city": $1'); }); }); diff --git a/src/webviews/documentdbQuery/documentdbQueryValidator.test.ts b/src/webviews/documentdbQuery/documentdbQueryValidator.test.ts index 756e077a8..6095dd89d 100644 --- a/src/webviews/documentdbQuery/documentdbQueryValidator.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryValidator.test.ts @@ -63,11 +63,12 @@ describe('documentdbQueryValidator', () => { expect(warnings[0].message).toContain('ObjectId'); }); - test('unknown identifier foo used as function is not flagged if not near BSON constructor', () => { - // "foo" is not close to any BSON constructor name (Levenshtein > 2) + test('unknown identifier foo used as function produces error', () => { + // "foo" is not close to any known identifier (Levenshtein > 2) const diagnostics = validateExpression('{ id: foo("abc") }'); - const warnings = diagnostics.filter((d) => d.severity === 'warning'); - expect(warnings).toHaveLength(0); + const errors = diagnostics.filter((d) => d.severity === 'error'); + expect(errors).toHaveLength(1); + expect(errors[0].message).toContain("Unknown function 'foo'"); }); test('unknown identifier as field name is not flagged', () => { @@ -128,6 +129,20 @@ describe('documentdbQueryValidator', () => { expect(warnings[0].message).toContain('Number'); }); + test('completely unknown member call UdddddduaD.now() produces error', () => { + const diagnostics = validateExpression('{ _id: UdddddduaD.now() }'); + const errors = diagnostics.filter((d) => d.severity === 'error'); + expect(errors).toHaveLength(1); + expect(errors[0].message).toContain("Unknown identifier 'UdddddduaD'"); + }); + + test('completely unknown direct call XyzAbc() produces error', () => { + const diagnostics = validateExpression('{ _id: XyzAbc("123") }'); + const errors = diagnostics.filter((d) => d.severity === 'error'); + expect(errors).toHaveLength(1); + expect(errors[0].message).toContain("Unknown function 'XyzAbc'"); + }); + test('Date.nodw() does NOT produce a warning (method validation is out of scope)', () => { // We validate the object (Date) but not individual method names. // Date is a known global, so no warning. The .nodw() method name diff --git a/src/webviews/documentdbQuery/documentdbQueryValidator.ts b/src/webviews/documentdbQuery/documentdbQueryValidator.ts index 9baca90a0..cbbb41536 100644 --- a/src/webviews/documentdbQuery/documentdbQueryValidator.ts +++ b/src/webviews/documentdbQuery/documentdbQueryValidator.ts @@ -222,15 +222,23 @@ export function validateExpression(code: string): Diagnostic[] { } const nearMiss = findNearMissKnownIdentifier(name); + const startOffset = node.callee.start - 1; + const endOffset = node.callee.end - 1; if (nearMiss) { - const startOffset = node.callee.start - 1; - const endOffset = node.callee.end - 1; diagnostics.push({ startOffset, endOffset, severity: 'warning', message: `Did you mean '${nearMiss.match}'?`, }); + } else { + // No near-miss found — unknown function call will fail at runtime + diagnostics.push({ + startOffset, + endOffset, + severity: 'error', + message: `Unknown function '${name}'. Expected a BSON constructor (e.g., ObjectId, ISODate) or a known global (e.g., Date, Math).`, + }); } } @@ -249,15 +257,23 @@ export function validateExpression(code: string): Diagnostic[] { } const nearMiss = findNearMissKnownIdentifier(objName); + const startOffset = node.callee.object.start - 1; + const endOffset = node.callee.object.end - 1; if (nearMiss) { - const startOffset = node.callee.object.start - 1; - const endOffset = node.callee.object.end - 1; diagnostics.push({ startOffset, endOffset, severity: 'warning', message: `Did you mean '${nearMiss.match}'?`, }); + } else { + // No near-miss found — unknown object will fail at runtime + diagnostics.push({ + startOffset, + endOffset, + severity: 'error', + message: `Unknown identifier '${objName}'. Expected a known global (e.g., Date, Math).`, + }); } } }, From f3112de6b728a6f63146c5464195356bdd594d6f Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Mar 2026 12:18:43 +0000 Subject: [PATCH 080/128] feat: add JavaScript global completions (Date, Math, RegExp) to completion items --- .../documentdbQuery/completions/README.md | 1 + .../completions/createCompletionItems.ts | 11 +- .../documentdbQuery/completions/index.ts | 9 +- .../documentdbQuery/completions/jsGlobals.ts | 142 ++++++++++++++++++ .../documentdbQueryCompletionProvider.test.ts | 21 +++ 5 files changed, 177 insertions(+), 7 deletions(-) create mode 100644 src/webviews/documentdbQuery/completions/jsGlobals.ts diff --git a/src/webviews/documentdbQuery/completions/README.md b/src/webviews/documentdbQuery/completions/README.md index d65b99fff..85b738be9 100644 --- a/src/webviews/documentdbQuery/completions/README.md +++ b/src/webviews/documentdbQuery/completions/README.md @@ -38,6 +38,7 @@ Completion items use `sortText` prefixes so Monaco displays them in the intended | `00_00` – `00_99` | Type suggestions | `true` / `false` for boolean fields | | `0_$eq` – `2_$op` | Query operators (type-aware) | `{ $eq: … }`, `{ $gt: … }` | | `3_ObjectId` | BSON constructors | `ObjectId(…)`, `ISODate(…)` | +| `4_Date` | JS globals | `Date`, `Math`, `RegExp`, `Infinity` | ### Key position diff --git a/src/webviews/documentdbQuery/completions/createCompletionItems.ts b/src/webviews/documentdbQuery/completions/createCompletionItems.ts index 58fe8f417..94dd9bb41 100644 --- a/src/webviews/documentdbQuery/completions/createCompletionItems.ts +++ b/src/webviews/documentdbQuery/completions/createCompletionItems.ts @@ -22,6 +22,7 @@ import { getCompletionContext } from '../completionStore'; import { type CursorContext } from '../cursorContext'; import { EditorType } from '../languageConfig'; import { KEY_POSITION_OPERATORS } from './completionKnowledge'; +import { createJsGlobalCompletionItems } from './jsGlobals'; import { mapFieldToCompletionItem, mapOperatorToCompletionItem } from './mapCompletionItems'; import { createTypeSuggestions } from './typeSuggestions'; @@ -142,8 +143,9 @@ function createKeyPositionCompletions( /** * Value position completions: * 1. Type-aware suggestions (sort `00_`) — e.g., `true`/`false` for booleans - * 2. Query operators with brace-wrapping snippets (sort `0_`) - * 3. BSON constructors (sort `1_`) + * 2. Query operators with brace-wrapping snippets (sort `0_`–`2_`) + * 3. BSON constructors (sort `3_`) + * 4. JS globals: Date, Math, RegExp, etc. (sort `4_`) */ function createValuePositionCompletions( editorType: EditorType | undefined, @@ -181,7 +183,10 @@ function createValuePositionCompletions( return item; }); - return [...typeSuggestions, ...operatorItems, ...bsonItems]; + // 4. JS globals: Date, Math, RegExp, Infinity, NaN, undefined (sort prefix 4_) + const jsGlobals = createJsGlobalCompletionItems(range, monaco); + + return [...typeSuggestions, ...operatorItems, ...bsonItems, ...jsGlobals]; } function createOperatorPositionCompletions( diff --git a/src/webviews/documentdbQuery/completions/index.ts b/src/webviews/documentdbQuery/completions/index.ts index 1ae3c1be4..05a9a4737 100644 --- a/src/webviews/documentdbQuery/completions/index.ts +++ b/src/webviews/documentdbQuery/completions/index.ts @@ -10,22 +10,23 @@ * - `createCompletionItems.ts` — main entry point, context branching * - `mapCompletionItems.ts` — operator/field → CompletionItem mapping * - `typeSuggestions.ts` — type-aware value suggestions (bool → true/false, etc.) + * - `jsGlobals.ts` — JS globals available in the shell-bson-parser sandbox (Date, Math, etc.) * - `snippetUtils.ts` — snippet text manipulation (brace stripping, $ escaping) */ export { INFO_INDICATOR, LABEL_PLACEHOLDER } from './completionKnowledge'; export { - KEY_POSITION_OPERATORS, createCompletionItems, - getMetaTagsForEditorType, - type CreateCompletionItemsParams, + getMetaTagsForEditorType, KEY_POSITION_OPERATORS, type CreateCompletionItemsParams } from './createCompletionItems'; +export { createJsGlobalCompletionItems } from './jsGlobals'; export { getCategoryLabel, getCompletionKindForMeta, getOperatorSortPrefix, mapFieldToCompletionItem, - mapOperatorToCompletionItem, + mapOperatorToCompletionItem } from './mapCompletionItems'; export { escapeSnippetDollars, stripOuterBraces } from './snippetUtils'; export { createTypeSuggestions } from './typeSuggestions'; + diff --git a/src/webviews/documentdbQuery/completions/jsGlobals.ts b/src/webviews/documentdbQuery/completions/jsGlobals.ts new file mode 100644 index 000000000..e6d581ec5 --- /dev/null +++ b/src/webviews/documentdbQuery/completions/jsGlobals.ts @@ -0,0 +1,142 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * JavaScript global completions for the `documentdb-query` language. + * + * The `documentdb-query` language uses `@mongodb-js/shell-bson-parser` to + * execute queries. That parser runs in a sandboxed scope that exposes a + * limited set of JavaScript globals beyond the BSON constructors (which are + * already registered in `documentdb-constants`). + * + * This module provides completion items for those JS globals so they appear + * in the value-position completion list. They are NOT added to + * `documentdb-constants` because they are runtime JS constructs, not + * DocumentDB API operators. + * + * ### Supported JS globals (from shell-bson-parser's sandbox scope) + * + * **Class expressions** (object with whitelisted methods): + * - `Date` — `new Date()`, `Date()`, `Date.now()`, plus instance methods + * - `Math` — `Math.floor()`, `Math.min()`, `Math.max()`, etc. + * + * **Globals** (primitive values): + * - `Infinity`, `NaN`, `undefined` + * + * **Constructor functions** (SCOPE_ANY / SCOPE_NEW / SCOPE_CALL): + * - `RegExp` — already handled by the JS tokenizer, but listed for completeness + * + * Source: `node_modules/@mongodb-js/shell-bson-parser/dist/scope.js` + * (SCOPE_ANY, SCOPE_NEW, SCOPE_CALL, GLOBALS, ALLOWED_CLASS_EXPRESSIONS) + */ + +// eslint-disable-next-line import/no-internal-modules +import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; +import { escapeSnippetDollars } from './snippetUtils'; + +/** A JS global completion definition. */ +interface JsGlobalDef { + /** Display label (e.g., "Date") */ + label: string; + /** Optional snippet to insert (otherwise label is used) */ + snippet?: string; + /** Short description shown right-aligned in the completion list */ + description: string; + /** Documentation shown in the details panel */ + documentation: string; +} + +/** + * JS globals available in shell-bson-parser's sandbox. + * + * These are the class expressions and global values that the parser's + * sandboxed eval supports. BSON constructors (ObjectId, ISODate, etc.) + * are already provided by `documentdb-constants` and are NOT duplicated here. + */ +const JS_GLOBALS: readonly JsGlobalDef[] = [ + { + label: 'Date', + snippet: 'new Date(${1})', + description: 'JS global', + documentation: + 'JavaScript Date constructor.\n\n' + + 'Usages:\n' + + '- `new Date()` — current time\n' + + '- `new Date("2025-01-01")` — specific date\n' + + '- `Date.now()` — milliseconds since epoch\n' + + '- `new Date(Date.now() - 14 * 24 * 60 * 60 * 1000)` — 14 days ago', + }, + { + label: 'Math', + description: 'JS global', + documentation: + 'JavaScript Math object.\n\n' + + 'Common methods:\n' + + '- `Math.floor(n)` — round down\n' + + '- `Math.ceil(n)` — round up\n' + + '- `Math.min(a, b)` — minimum\n' + + '- `Math.max(a, b)` — maximum\n' + + '- `Math.round(n)` — nearest integer', + }, + { + label: 'RegExp', + snippet: 'RegExp("${1:pattern}")', + description: 'JS global', + documentation: 'JavaScript RegExp constructor.\n\nExample: `RegExp("^test")`\n\nPrefer regex literals: `/^test/`', + }, + { + label: 'Infinity', + description: 'JS global', + documentation: 'Numeric value representing infinity.\n\nExample: `{ $lt: Infinity }`', + }, + { + label: 'NaN', + description: 'JS global', + documentation: 'Numeric value representing Not-a-Number.\n\nExample: `{ $ne: NaN }`', + }, + { + label: 'undefined', + description: 'JS global', + documentation: 'The undefined value.\n\nExample: `{ field: undefined }` — matches missing fields.', + }, +]; + +/** + * Creates completion items for JavaScript globals supported by the + * shell-bson-parser sandbox. + * + * These are shown at value position with sort prefix `4_` (after BSON + * constructors at `3_`). + * + * @param range - the insertion range + * @param monaco - the Monaco API + */ +export function createJsGlobalCompletionItems( + range: monacoEditor.IRange, + monaco: typeof monacoEditor, +): monacoEditor.languages.CompletionItem[] { + return JS_GLOBALS.map((def) => { + const hasSnippet = !!def.snippet; + let insertText = hasSnippet ? def.snippet! : def.label; + if (hasSnippet) { + insertText = escapeSnippetDollars(insertText); + } + + return { + label: { + label: def.label, + description: def.description, + }, + kind: hasSnippet + ? monaco.languages.CompletionItemKind.Constructor + : monaco.languages.CompletionItemKind.Constant, + insertText, + insertTextRules: hasSnippet ? monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet : undefined, + documentation: { value: def.documentation }, + sortText: `4_${def.label}`, + range, + }; + }); +} diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index b095d4336..78bfc9255 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -1027,6 +1027,27 @@ describe('documentdbQueryCompletionProvider', () => { expect(objectIdItem?.sortText).toBe('3_ObjectId'); }); + test('includes JS globals (Date, Math) after BSON constructors', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: valueContext, + }); + + const labels = items.map((i) => getLabelText(i.label)); + expect(labels).toContain('Date'); + expect(labels).toContain('Math'); + expect(labels).toContain('RegExp'); + expect(labels).toContain('Infinity'); + + // JS globals sort after BSON constructors (4_ > 3_) + const dateItem = items.find((i) => getLabelText(i.label) === 'Date'); + expect(dateItem?.sortText).toBe('4_Date'); + }); + test('does NOT show key-position operators ($and, $or)', () => { const items = createCompletionItems({ editorType: EditorType.Filter, From d727c31110ceba108672c41f25b5a9f71d3ce16a Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Mar 2026 12:33:43 +0000 Subject: [PATCH 081/128] fix: validate NewExpression constructors for unknown identifiers Previously `new Daddddte()` was not flagged because the validator only handled CallExpression nodes. NewExpression has the same callee shape but was not visited. Now unknown constructors in `new Foo()` produce error diagnostics (red squiggles), and near-miss typos like `new Dae()` produce warnings. --- .../documentdbQueryValidator.test.ts | 24 +++++++++++++ .../documentdbQueryValidator.ts | 34 +++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/src/webviews/documentdbQuery/documentdbQueryValidator.test.ts b/src/webviews/documentdbQuery/documentdbQueryValidator.test.ts index 6095dd89d..969c80af0 100644 --- a/src/webviews/documentdbQuery/documentdbQueryValidator.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryValidator.test.ts @@ -143,6 +143,30 @@ describe('documentdbQueryValidator', () => { expect(errors[0].message).toContain("Unknown function 'XyzAbc'"); }); + test('new Daddddte() produces error for unknown constructor', () => { + const diagnostics = validateExpression('{ date: { $gt: new Daddddte(Date.now() - 14 * 24 * 60 * 60 * 1000) } }'); + const errors = diagnostics.filter((d) => d.severity === 'error'); + expect(errors).toHaveLength(1); + expect(errors[0].message).toContain("Unknown constructor 'Daddddte'"); + }); + + test('new Dae() produces warning for near-miss constructor', () => { + const diagnostics = validateExpression('{ date: new Dae("2025-01-01") }'); + const warnings = diagnostics.filter((d) => d.severity === 'warning'); + expect(warnings).toHaveLength(1); + expect(warnings[0].message).toContain('Date'); + }); + + test('new Date() produces no diagnostics', () => { + const diagnostics = validateExpression('{ date: new Date() }'); + expect(diagnostics).toHaveLength(0); + }); + + test('new RegExp() produces no diagnostics', () => { + const diagnostics = validateExpression('{ name: { $regex: new RegExp("^test") } }'); + expect(diagnostics).toHaveLength(0); + }); + test('Date.nodw() does NOT produce a warning (method validation is out of scope)', () => { // We validate the object (Date) but not individual method names. // Date is a known global, so no warning. The .nodw() method name diff --git a/src/webviews/documentdbQuery/documentdbQueryValidator.ts b/src/webviews/documentdbQuery/documentdbQueryValidator.ts index cbbb41536..95690247c 100644 --- a/src/webviews/documentdbQuery/documentdbQueryValidator.ts +++ b/src/webviews/documentdbQuery/documentdbQueryValidator.ts @@ -277,6 +277,40 @@ export function validateExpression(code: string): Diagnostic[] { } } }, + // NewExpression has the same callee shape as CallExpression. + // e.g., `new Daddddte()` — the callee is an Identifier node. + NewExpression( + node: acorn.Node & { + callee: acorn.Node & { name?: string; type: string }; + }, + ) { + if (node.callee.type === 'Identifier' && node.callee.name) { + const name = node.callee.name; + + if (KNOWN_GLOBALS.has(name)) { + return; + } + + const nearMiss = findNearMissKnownIdentifier(name); + const startOffset = node.callee.start - 1; + const endOffset = node.callee.end - 1; + if (nearMiss) { + diagnostics.push({ + startOffset, + endOffset, + severity: 'warning', + message: `Did you mean '${nearMiss.match}'?`, + }); + } else { + diagnostics.push({ + startOffset, + endOffset, + severity: 'error', + message: `Unknown constructor '${name}'. Expected a BSON constructor (e.g., ObjectId, ISODate) or a known global (e.g., Date, RegExp).`, + }); + } + } + }, }); } catch { // If walking fails, just return syntax diagnostics we already have From 11407a313a2509d3ed63ce6da49db15072e0d1d2 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Mar 2026 12:34:49 +0000 Subject: [PATCH 082/128] feat: add Date.now() and common Math methods to JS global completions Add Date.now(), Math.floor(), Math.ceil(), Math.round(), Math.min(), Math.max() as individual completion items alongside the class-level Date/Math entries. Removed the bare `Math` entry since the individual methods are more useful. All entries use sort prefix 4_ (after BSON constructors at 3_). --- .../documentdbQuery/completions/jsGlobals.ts | 48 +++++++++++++++---- .../documentdbQueryCompletionProvider.test.ts | 10 +++- 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/src/webviews/documentdbQuery/completions/jsGlobals.ts b/src/webviews/documentdbQuery/completions/jsGlobals.ts index e6d581ec5..93302ff00 100644 --- a/src/webviews/documentdbQuery/completions/jsGlobals.ts +++ b/src/webviews/documentdbQuery/completions/jsGlobals.ts @@ -56,6 +56,7 @@ interface JsGlobalDef { * are already provided by `documentdb-constants` and are NOT duplicated here. */ const JS_GLOBALS: readonly JsGlobalDef[] = [ + // -- Class constructors -- { label: 'Date', snippet: 'new Date(${1})', @@ -65,20 +66,13 @@ const JS_GLOBALS: readonly JsGlobalDef[] = [ 'Usages:\n' + '- `new Date()` — current time\n' + '- `new Date("2025-01-01")` — specific date\n' + - '- `Date.now()` — milliseconds since epoch\n' + '- `new Date(Date.now() - 14 * 24 * 60 * 60 * 1000)` — 14 days ago', }, { - label: 'Math', + label: 'Date.now()', + snippet: 'Date.now()', description: 'JS global', - documentation: - 'JavaScript Math object.\n\n' + - 'Common methods:\n' + - '- `Math.floor(n)` — round down\n' + - '- `Math.ceil(n)` — round up\n' + - '- `Math.min(a, b)` — minimum\n' + - '- `Math.max(a, b)` — maximum\n' + - '- `Math.round(n)` — nearest integer', + documentation: 'Returns milliseconds since Unix epoch (Jan 1, 1970).\n\nUseful for relative date queries:\n```\n{ $gt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) }\n```', }, { label: 'RegExp', @@ -86,6 +80,40 @@ const JS_GLOBALS: readonly JsGlobalDef[] = [ description: 'JS global', documentation: 'JavaScript RegExp constructor.\n\nExample: `RegExp("^test")`\n\nPrefer regex literals: `/^test/`', }, + + // -- Math methods -- + { + label: 'Math.floor()', + snippet: 'Math.floor(${1:value})', + description: 'JS global', + documentation: 'Round down to the nearest integer.\n\nExample: `Math.floor(3.7)` → `3`', + }, + { + label: 'Math.ceil()', + snippet: 'Math.ceil(${1:value})', + description: 'JS global', + documentation: 'Round up to the nearest integer.\n\nExample: `Math.ceil(3.2)` → `4`', + }, + { + label: 'Math.round()', + snippet: 'Math.round(${1:value})', + description: 'JS global', + documentation: 'Round to the nearest integer.\n\nExample: `Math.round(3.5)` → `4`', + }, + { + label: 'Math.min()', + snippet: 'Math.min(${1:a}, ${2:b})', + description: 'JS global', + documentation: 'Return the smaller of two values.\n\nExample: `Math.min(1.7, 2)` → `1.7`', + }, + { + label: 'Math.max()', + snippet: 'Math.max(${1:a}, ${2:b})', + description: 'JS global', + documentation: 'Return the larger of two values.\n\nExample: `Math.max(1.7, 2)` → `2`', + }, + + // -- Primitive globals -- { label: 'Infinity', description: 'JS global', diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index 78bfc9255..93c323d73 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -1027,7 +1027,7 @@ describe('documentdbQueryCompletionProvider', () => { expect(objectIdItem?.sortText).toBe('3_ObjectId'); }); - test('includes JS globals (Date, Math) after BSON constructors', () => { + test('includes JS globals and common methods after BSON constructors', () => { const items = createCompletionItems({ editorType: EditorType.Filter, sessionId: undefined, @@ -1038,9 +1038,15 @@ describe('documentdbQueryCompletionProvider', () => { }); const labels = items.map((i) => getLabelText(i.label)); + // Class constructors expect(labels).toContain('Date'); - expect(labels).toContain('Math'); expect(labels).toContain('RegExp'); + // Static methods + expect(labels).toContain('Date.now()'); + expect(labels).toContain('Math.floor()'); + expect(labels).toContain('Math.min()'); + expect(labels).toContain('Math.max()'); + // Primitives expect(labels).toContain('Infinity'); // JS globals sort after BSON constructors (4_ > 3_) From be3b3610f59c9246999853a5618d5e4b05f0b732 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Mar 2026 12:35:35 +0000 Subject: [PATCH 083/128] docs: update 4.5 plan with steps 15-16 --- .../04.5-context-sensitive-completions.md | 459 ++++++++++++++++++ 1 file changed, 459 insertions(+) create mode 100644 docs/plan/04.5-context-sensitive-completions.md diff --git a/docs/plan/04.5-context-sensitive-completions.md b/docs/plan/04.5-context-sensitive-completions.md new file mode 100644 index 000000000..1fdaa9780 --- /dev/null +++ b/docs/plan/04.5-context-sensitive-completions.md @@ -0,0 +1,459 @@ +# Step 4.5: Context-Sensitive Completions — Implementation Plan + +> **Prerequisites:** Step 4 complete (PR #518). The `documentdb-query` language, `CompletionItemProvider`, `completionStore`, and `documentdb-constants` infrastructure are all in place. + +## Status: ✅ Complete + +--- + +## Problem + +The current completion provider (`createCompletionItems`) returns a **flat list** of all operators + all field names regardless of cursor position. For example, in: + +``` +{ _id: } +``` + +The user sees `$gt`, `$eq`, `address`, `name`, `$regex`, etc. — the same list as when the cursor is at `{ }`. + +A better experience would be: + +| Cursor position | Example | Should show | Should NOT show | +| ------------------------------------ | --------------------------------------------- | ------------------------------------------------ | ---------------------------------------- | +| **Key position** (root) | `{ }` | Field names, `$and`, `$or`, `$nor`, `$comment` | Value operators (`$gt`, `$lt`, `$regex`) | +| **Value position** | `{ _id: }` | BSON constructors (`ObjectId`, `UUID`), literals | Field names, query operators | +| **Nested operator position** | `{ age: { } }` | `$gt`, `$lt`, `$eq`, `$in`, `$exists`, etc. | Field names, logical operators | +| **Nested operator position (typed)** | `{ age: { } }` where `age` is Number | `$gt`, `$gte`, `$lt`, `$lte` first, then others | `$regex` (string-only) demoted to end | +| **`$and`/`$or` array element** | `{ $and: [ ] }` | Same as root key position | — | + +Compass's query bar does **not** do this — it returns the same flat list. This would be a differentiating feature. + +--- + +## Existing Infrastructure (Ready to Use) + +The Step 4 implementation already built all the pieces needed: + +| Component | Status | What it provides | +| --------------------------------------- | ---------------------------------------------------------- | -------------------------------------------------------------------------------------- | +| `acorn` dependency | ✅ In place | JS expression parser for AST | +| `acorn-walk` dependency | ✅ In place | AST traversal | +| `documentdbQueryValidator.ts` | ✅ Already uses `acorn` to parse expressions and walk ASTs | +| `OperatorEntry.applicableBsonTypes` | ✅ Defined in `documentdb-constants/types.ts` | Per-operator BSON type affinity (e.g., `$regex` → `['string']`, `$size` → `['array']`) | +| `getFilteredCompletions({ bsonTypes })` | ✅ Built + tested | Filters operators by BSON type | +| `FieldCompletionData.bsonType` | ✅ Available | Raw BSON type string per field from schema | +| `completionStore` | ✅ In place | Provides per-session field data with types | + +**Key insight:** No new dependencies or packages are needed. This is pure logic work in the completion provider, using `acorn` (already a dependency) to parse the expression and determine cursor context. + +--- + +## Design: Cursor Context Detection + +### AST-Based Approach + +Parse the editor content with `acorn` and determine the cursor's semantic position by walking the AST. The cursor is a character offset; find which AST node contains it. + +```typescript +export type CursorContext = + | { position: 'key'; depth: 0 } // Root key position: { } + | { position: 'key'; depth: number } // Nested key position (inside $elemMatch, etc.) + | { position: 'value'; fieldName: string; fieldBsonType?: string } + // Value position: { fieldName: } + | { position: 'operator'; fieldName: string; fieldBsonType?: string } + // Nested operator: { fieldName: { } } + | { position: 'array-element'; parentOperator: string } + // Inside $and/$or/$nor array: { $and: [ ] } + | { position: 'unknown' }; // Can't determine — show everything (safe fallback) +``` + +### Partial-Input Challenge + +The main difficulty is that acorn **cannot parse incomplete expressions**. When the cursor is at `{ age: { $` the expression is syntactically invalid. Strategies: + +1. **Dummy completion:** Insert a placeholder at the cursor position to make the expression parseable. For example, replace `{ age: { $` with `{ age: { $__placeholder__: 0 } }` and parse that. +2. **Heuristic fallback:** If acorn fails, fall back to a simpler text-based analysis: + - Count unmatched `{` and `}` to estimate nesting depth + - Look backward from cursor for `:` (value position), `{` (key/operator position), `[` (array element) + - Check if the enclosing key starts with `$` (operator position vs key position) +3. **Hybrid:** Try acorn first, fall back to heuristic on parse failure. + +**Recommendation:** Start with approach (2) — the heuristic. It handles the common cases without the complexity of AST surgery on partial input. The fallback to the full list (current behavior) for ambiguous cases is acceptable; users still get completions, just not perfectly filtered. + +### Heuristic Algorithm + +``` +function detectCursorContext(text: string, cursorOffset: number): CursorContext: + 1. Find the character immediately before the cursor (skip whitespace) + 2. If char is ':' → VALUE position + - Walk backward to find the key name + - Look up the key in the completion store to get bsonType + 3. If char is '{': + - Walk backward to find what's before this '{' + - If preceded by ':' and a key name → OPERATOR position (nested object) + - The key name is the field name → look up bsonType + - If preceded by nothing / start-of-input → KEY position (root) + 4. If char is '[': + - Walk backward to find what precedes the '[' + - If preceded by '$and', '$or', '$nor' → ARRAY-ELEMENT position + 5. If char is ',': + - Determine whether we're inside an object or array + - Object → same as KEY position at current depth + - Array of $and/$or/$nor → ARRAY-ELEMENT position + 6. Else → UNKNOWN (show everything) +``` + +--- + +## Completion Rules Per Context + +| Context | Operators to show | Fields to show | Sort priority | +| ------------------------- | ------------------------------------------------------------------------------- | -------------- | --------------------------------------------------------------------------------------- | +| `key` (root) | Logical only: `$and`, `$or`, `$nor`, `$not`, `$comment`, `$expr`, `$jsonSchema` | All fields | Fields first (sort prefix `0_`), logical operators second (`1_`) | +| `value` | BSON constructors only | None | Constructors first | +| `operator` (no type info) | All query operators (comparison, element, array, etc.) | None | Default sort | +| `operator` (typed) | **All** query operators — type-relevant first, non-matching demoted to end | None | Type-relevant operators first (`0_`), universal second (`1_`), non-matching last (`2_`) | +| `array-element` | Same as `key` (root) | All fields | Same as `key` | +| `unknown` | All (current behavior) | All | Current behavior | + +### Type-Aware Operator Ordering + +When the field type is known, **all operators are still shown** — nothing is excluded. The ordering uses `sortText` prefixes to rank operators by type relevance: + +1. **`0_`** — Type-relevant operators: those whose `applicableBsonTypes` includes the field's type (e.g., `$regex` for strings, `$size` for arrays) +2. **`1_`** — Universal operators: those with no `applicableBsonTypes` set (e.g., `$eq`, `$ne`, `$in`, `$exists`) +3. **`2_`** — Non-matching operators: those whose `applicableBsonTypes` is set but does NOT include the field's type (e.g., `$regex` when the field is a Number) + +This ensures completions still show `$regex` for a Number field (in case the field is sometimes a string), but it appears at the bottom of the list, not the top. + +> **Design rationale:** A field like `age` may be a Number 98% of the time but occasionally a String. Completely hiding `$regex` would be incorrect. Demoting it to the end of each section preserves discoverability while keeping the most relevant operators front and center. + +Example for `{ age: { } }` where `age` is `Number`: + +``` +$gt 0_$gt (no applicableBsonTypes → universal, but commonly number-relevant) +$gte 0_$gte +$lt 0_$lt +$lte 0_$lte +$eq 1_$eq (universal — no applicableBsonTypes) +$ne 1_$ne +$in 1_$in +$exists 1_$exists +$regex 2_$regex (applicableBsonTypes=['string'], doesn't match 'number' → demoted) +$all 2_$all (applicableBsonTypes=['array'], doesn't match 'number' → demoted) +$size 2_$size (applicableBsonTypes=['array'], doesn't match 'number' → demoted) +``` + +**Note:** Comparison operators like `$gt`, `$lt` etc. are universal (no `applicableBsonTypes`), so they get sort prefix `1_`. In practice, this is the right behavior — they work on all types. Only operators with an explicit type restriction get boosted (`0_`) or demoted (`2_`). + +**Pre-step (can be done in current PR):** Before the full cursor context detection (Steps 1–3) is implemented, the type-aware sorting can be applied as a standalone enhancement to `createCompletionItems()` / `mapOperatorToCompletionItem()`. When a `fieldBsonType` is available (e.g., from a future `CursorContext`), pass it through and use it for `sortText` assignment. + +--- + +## Implementation Steps + +### Step 1: Create Cursor Context Detector ✅ + +**Goal:** A pure function that determines the semantic cursor position from editor text + offset. + +**File created:** + +- `src/webviews/documentdbQuery/cursorContext.ts` +- `src/webviews/documentdbQuery/cursorContext.test.ts` + +**Implementation:** + +1. Implement `detectCursorContext(text: string, cursorOffset: number, fieldLookup?: (fieldName: string) => string | undefined): CursorContext` +2. The `fieldLookup` callback resolves a field name to its BSON type string (from the completion store) +3. Start with the heuristic approach — character scanning backward from cursor +4. Handle edge cases: empty input, cursor at offset 0, cursor at end, nested structures + +**Test cases:** + +- `{ | }` → `key` at depth 0 +- `{ _id: | }` → `value` with fieldName `_id` +- `{ age: { | } }` → `operator` with fieldName `age` +- `{ $and: [ | ] }` → `array-element` with parentOperator `$and` +- `{ name: "Alice", | }` → `key` at depth 0 (after comma) +- `{ age: { $gt: 5, | } }` → `operator` with fieldName `age` (after comma inside nested object) +- (empty) → `unknown` + +### Step 1.5: Tests for Incomplete / Broken Input ✅ + +**Goal:** Verify that `detectCursorContext` gracefully handles partially-typed expressions — i.e., the exact state the editor is in while the user is actively typing. + +**File updated:** + +- `src/webviews/documentdbQuery/cursorContext.test.ts` (extended from Step 1) + +**Test cases:** + +| Input (cursor = end) | Expected context | Rationale | +| -------------------- | --------------------------------------------- | -------------------------------------------------------------- | +| `{ age: ` | `value` with `fieldName: 'age'` | Colon just typed — user is about to enter a value | +| `{ age: $` | `value` with `fieldName: 'age'` | Started typing a BSON constructor like `$` (or accidental `$`) | +| `{ age: $ }` | `value` with `fieldName: 'age'` | Same as above but closing brace is present | +| `{ age: {` | `operator` with `fieldName: 'age'` | Opened nested object — expects comparison operators | +| `{ age: { $` | `operator` with `fieldName: 'age'` | Began typing an operator like `$gt` | +| `{ age: { $ }` | `operator` with `fieldName: 'age'` | Incomplete operator inside nested object | +| `{ age: { $g` | `operator` with `fieldName: 'age'` | Partially typed `$gt` | +| `{ ` | `key` at depth 0 | Opened root object, haven't typed a field yet | +| `{ a` | `key` at depth 0 | Partially typed a field name | +| `{ name: "Alice", ` | `key` at depth 0 | Comma after first pair, new key expected | +| `{ name: "Alice", a` | `key` at depth 0 | Partially typed second field name | +| `{ $and: [` | `array-element` with `parentOperator: '$and'` | Opened array for logical operator | +| `{ $and: [ {` | `key` at depth 1 (or `array-element`) | Inside an `$and` array element object | +| `{ age: { $gt: 5, ` | `operator` with `fieldName: 'age'` | After comma inside nested operator object | +| `{` | `key` at depth 0 | Just the opening brace | +| (empty string) | `unknown` | Nothing typed yet | + +**Key principle:** Every partially-typed state must produce a _useful_ context (not `unknown`) whenever possible. The fallback to `unknown` should only occur when there is genuinely no signal — not just because the input fails to parse. + +#### Why Not Use a "Dummy Completion" Strategy? + +The "dummy completion" approach works by inserting a synthetic placeholder at the cursor position (e.g., replacing `{ age: { $` with `{ age: { $__placeholder__: 0 } }`) to make the expression parseable by `acorn`, then inspecting the resulting AST to determine cursor context. + +While conceptually clean, this strategy has several practical problems that make it **unsuitable as the primary approach**: + +1. **Ambiguity of placeholder semantics.** Where exactly to insert the placeholder and what it should look like depends on context — the very thing we're trying to determine. For `{ age: $`, should the placeholder be a value (`{ age: $__placeholder__ }`) or a nested key (`{ age: { $__placeholder__: 0 } }`)? The answer changes the AST shape and therefore the detected context. This creates a chicken-and-egg problem. + +2. **Fragility with multiple parse errors.** Real mid-typing states often have _multiple_ syntax issues: missing closing braces, unterminated strings, trailing commas, bare `$` tokens, etc. Patching one error with a placeholder doesn't guarantee the rest of the expression becomes valid. The repair logic quickly becomes its own mini-parser — defeating the purpose of leveraging `acorn`. + +3. **Hard-to-test edge cases.** Each incomplete state requires a specific repair heuristic. Testing that `{ age: { $gt: 5, ` becomes `{ age: { $gt: 5, __placeholder__: 0 } }` (and not some other shape) is one test case — but there are dozens of partially-typed states, each needing its own repair rule. The heuristic scanner, by contrast, operates uniformly: it scans backward from the cursor and classifies based on the nearest structural character. + +4. **Performance overhead.** Every completion request would require string surgery (insert placeholder, possibly add closing braces) followed by a full `acorn` parse. The heuristic scanner is `O(n)` backward from the cursor with no parsing step, making it faster for the hot path that fires on every keystroke. + +5. **Maintenance burden.** The repair heuristics are tightly coupled to `acorn`'s error behavior. If `acorn` changes how it reports or recovers from errors, the repair logic may silently break. The heuristic approach has no such dependency — it looks at raw characters. + +**Bottom line:** The heuristic scanner is more predictable, easier to test exhaustively (as this Step 1.5 demonstrates), and avoids the fundamental ambiguity of trying to "fix" broken input before understanding it. The dummy-completion strategy can be revisited as an _enhancement_ for deeply-nested cases where the heuristic loses signal, but it should not be the foundation. + +--- + +### Step 2: Update CompletionItemProvider to Use Context ✅ + +**Goal:** Wire cursor context into the completion pipeline. + +**Files modified:** + +- `src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts` +- `src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts` + +**Implementation:** + +1. Add `cursorContext: CursorContext` to `CreateCompletionItemsParams` +2. In `createCompletionItems()`, branch on `cursorContext.position`: + - `key` → return field completions + logical operator subset + - `value` → return BSON constructors only (meta `'bson'`) + - `operator` → return query operators, optionally filtered by `fieldBsonType` + - `array-element` → same as `key` + - `unknown` → current behavior (all operators + all fields) +3. Apply sort prefixes based on type relevance + +### Step 3: Wire Context Detection in registerLanguage.ts ✅ + +**Goal:** Call `detectCursorContext()` in the completion provider and pass it through. + +**Files modified:** + +- `src/webviews/documentdbQuery/registerLanguage.ts` + +**Implementation:** + +1. In `provideCompletionItems`, compute cursor offset from position: + ```typescript + const cursorOffset = model.getOffsetAt(position); + const text = model.getValue(); + const context = detectCursorContext(text, cursorOffset, fieldLookup); + ``` +2. Create `fieldLookup` from the completion store: + ```typescript + const fieldLookup = (fieldName: string) => { + const ctx = getCompletionContext(parsed?.sessionId ?? ''); + return ctx?.fields.find((f) => f.fieldName === fieldName)?.bsonType; + }; + ``` +3. Pass `cursorContext` to `createCompletionItems()` + +### Step 4: Tests and Verification ✅ + +**Verification checklist:** + +- [x] `{ }` → shows field names + logical operators only +- [x] `{ _id: }` → shows BSON constructors (ObjectId, UUID, etc.) +- [x] `{ age: { } }` → shows comparison/element/array query operators +- [x] `{ age: { } }` with `age` typed as Number → `$regex` demoted, `$bitsAllSet` promoted, `$eq` universal +- [x] `{ $and: [ ] }` → shows field names + logical operators (root-like) +- [x] Unknown/ambiguous positions → falls back to full list (no regressions) +- [x] All existing tests continue to pass (48 original + 16 context-sensitive + 41 cursor context = 105 new tests) +- [x] `npm run build` succeeds +- [x] `npm run lint` passes + +**Implementation notes:** + +- The plan originally expected `depth: 0` for root-level key positions. The implementation uses `depth: 1` because the root `{` counts as depth 1 (0 would mean "outside all braces"). Tests adjusted accordingly. +- `KEY_POSITION_OPERATORS` is defined as a `Set` of operator values rather than filtering by meta tag, because `query:evaluation` contains both key-position operators (`$expr`, `$jsonSchema`) and operator-position operators (`$regex`, `$mod`). A value-based set is more precise. +- `$text` and `$where` are included in `KEY_POSITION_OPERATORS` because they are top-level query operators (appear at key position in a query document), not inside nested `{ field: { ... } }` objects. + +--- + +## File Map + +### New files + +| File | Purpose | +| ---------------------------------------------------- | ------------------------------- | +| `src/webviews/documentdbQuery/cursorContext.ts` | Cursor position detection logic | +| `src/webviews/documentdbQuery/cursorContext.test.ts` | Unit tests | + +### Modified files + +| File | Change | +| ------------------------------------------------------------------------ | ---------------------------------------- | +| `src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts` | Branch completions by cursor context | +| `src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts` | New tests for context-sensitive behavior | +| `src/webviews/documentdbQuery/registerLanguage.ts` | Wire context detection into provider | + +--- + +## Additional Steps (PR #530) + +The following steps were completed as part of PR #530, extending the original plan with improvements discovered during review and manual testing. + +### Step 5: Refactor completions into folder + type-aware value suggestions ✅ + +**Goal:** Organize completions code into a structured folder and add type-aware value suggestions. + +**Files created:** +- `src/webviews/documentdbQuery/completions/createCompletionItems.ts` — main entry point +- `src/webviews/documentdbQuery/completions/mapCompletionItems.ts` — operator/field mapping +- `src/webviews/documentdbQuery/completions/typeSuggestions.ts` — type-aware value suggestions (boolean → true/false, number → range queries, etc.) +- `src/webviews/documentdbQuery/completions/snippetUtils.ts` — snippet text utilities +- `src/webviews/documentdbQuery/completions/index.ts` — barrel export +- `src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts` — updated to re-export from folder + +**Changes:** +- Extracted `KEY_POSITION_OPERATORS`, completion builder functions, and mapping functions into the `completions/` subfolder +- Added `TypeSuggestionDef` system: when the field's BSON type is known, value-position completions include type-specific suggestions (sort prefix `00_`) above operators + +### Step 6: Create completion knowledge configuration ✅ + +**Goal:** Centralise curated domain rules that are not part of `documentdb-constants` but are needed for context-sensitive completions. + +**File created:** +- `src/webviews/documentdbQuery/completions/completionKnowledge.ts` + +**Contents:** +- `KEY_POSITION_OPERATORS` — operators valid only at root query level (`$and`, `$or`, `$nor`, `$not`, `$comment`, `$expr`, `$jsonSchema`, `$text`, `$where`), with documentation explaining why each is key-position-only +- `LABEL_PLACEHOLDER` — the `…` (U+2026) character for completion labels +- `INFO_INDICATOR` — the `ℹ` (U+2139) character for example descriptions + +**Rationale:** `documentdb-constants` is auto-generated from operator reference and is intentionally generic. The knowledge file captures syntactic rules about _where_ operators are valid that the generic registry does not encode. + +### Step 7: Fix $and/$or double-brace bug ✅ + +**Goal:** Fix bug where selecting `$and` from the completion list at key position produces double braces: `{ { $and: [...] } }`. + +**Root cause:** `createKeyPositionCompletions` called `mapOperatorToCompletionItem()` without `shouldStripBraces: true`. The `$and` snippet from `documentdb-constants` is `{ $and: [{ ${1:expression} }] }` (includes outer braces). At key position, the user is already inside `{ }`, so inserting the full snippet created double-nesting. + +**Fix:** Pass `shouldStripBraces: true` in `createKeyPositionCompletions` so outer `{ }` are stripped, producing `$and: [{ ${1:expression} }]`. + +### Step 8: Empty/unknown input shows key-position completions ✅ + +**Goal:** When the input box is empty or context is unknown, show field names + key-position operators (same as `{ | }`) instead of all operators. + +**Change:** `createCompletionItems` now routes `unknown` and `undefined` cursor contexts to `createKeyPositionCompletions` instead of `createAllCompletions`. The `createAllCompletions` function was removed as it is no longer called. + +**Rationale:** When users clear the input box, they most commonly want to start with a field name. Showing all operators (including value-position ones like `$gt`) was confusing. + +### Step 9: Type-aware operator sorting at value position ✅ + +**Goal:** When the BSON field type is known and the user is at value position, sort operators by type relevance. + +**Changes:** +- `createValuePositionCompletions` now passes `fieldBsonTypes` to `mapOperatorToCompletionItem` for type-aware sorting +- `getOperatorSortPrefix` now distinguishes comparison operators from other universal operators: + - `0_` — type-relevant (operator's `applicableBsonTypes` matches field) + - `1a_` — comparison operators (universal, most commonly used: `$eq`, `$gt`, `$ne`, etc.) + - `1b_` — other universal operators (`$exists`, `$type`, `$mod`, etc.) + - `2_` — non-matching (operator has type restrictions that don't match) + - `3_` — BSON constructors (`ObjectId`, `ISODate`, etc.) + - `4_` — JS globals (`Date`, `Math`, `RegExp`, `Infinity`, etc.) + +### Step 10: Field completion inserts `: $1` snippet ✅ + +**Goal:** Selecting a field name from completions should insert `fieldName: |` with the cursor positioned at the value. + +**Change:** `mapFieldToCompletionItem` now uses snippet insert text `${field.insertText}: $1` with `InsertAsSnippet` rule, instead of plain text. Also changed `label` from a plain string to `{ label: fieldName, description: displayType }` so the type info renders right-aligned (matching operator label style). + +### Step 11: Improved type suggestion labels and documentation ✅ + +**Goal:** Make type suggestions more useful with shorter descriptions, examples in documentation, and practical defaults. + +**Changes:** +- Replaced `▪` (U+25AA) placeholder with `…` (U+2026, horizontal ellipsis) +- Moved examples from inline descriptions to the `documentation` panel +- Shortened descriptions to fit the completion list width (e.g., "pattern match", "range query", "last N days") +- Date suggestions now use dynamic defaults: `twoWeeksAgo()` and `todayISO()` for realistic placeholders +- Added `{ $gt: new Date(Date.now() - …) }` suggestion for relative date queries +- Added concrete regex example `{ $regex: /\.com$/ }` with documentation + +### Step 12: Error diagnostics for unknown function calls ✅ + +**Goal:** Flag unknown function call identifiers as red errors (not just yellow near-miss warnings). + +**Problem:** Previously, `UdddddduaD.now()` and `XyzAbc("123")` produced no diagnostic at all — the Levenshtein distance was > 2 so no near-miss warning fired, but there was also no error path. These calls will always fail at runtime. + +**Fix:** In `documentdbQueryValidator.ts`, the `CallExpression` handler now falls through to an error diagnostic when no near-miss is found: +- Direct calls: `Unknown function 'XyzAbc'. Expected a BSON constructor (e.g., ObjectId, ISODate) or a known global (e.g., Date, Math).` +- Member calls: `Unknown identifier 'UdddddduaD'. Expected a known global (e.g., Date, Math).` + +### Step 13: JS globals in value-position completions ✅ + +**Goal:** Restore `Date`, `Math`, `RegExp`, `Infinity`, `NaN`, and `undefined` as completion items at value position. + +**Problem:** When Step 4 (PR #518) replaced the Monaco JS language with the custom `documentdb-query` language, JavaScript global completions that were previously provided by the built-in Monaco JS language worker disappeared. These globals are valid in queries because `@mongodb-js/shell-bson-parser` supports them in its sandboxed scope. + +**Solution:** Created `src/webviews/documentdbQuery/completions/jsGlobals.ts` — a webview-side module (NOT in `documentdb-constants`) that provides completion items for the JS globals supported by shell-bson-parser's sandbox. These are shown at value position with sort prefix `4_` (after BSON constructors at `3_`). + +**Source of truth:** The supported globals are derived from shell-bson-parser's `scope.js`: +- `SCOPE_CALL/SCOPE_NEW`: `Date` (as constructor) +- `ALLOWED_CLASS_EXPRESSIONS`: `Math` (with whitelisted methods), `Date` (with whitelisted methods) +- `SCOPE_ANY`: `RegExp` (constructor) +- `GLOBALS`: `Infinity`, `NaN`, `undefined` + +**Rationale:** These are NOT added to `documentdb-constants` because they are JavaScript runtime constructs, not DocumentDB API operators. They live in the webview completions module alongside other webview-specific completion logic. + +### Step 14: Completions README ✅ + +**File created:** `src/webviews/documentdbQuery/completions/README.md` + +Documents the completions folder architecture, sorting tiers, and decision matrix for sort prefix assignment. + +### Step 15: Validate `new` expressions for unknown constructors ✅ + +**Goal:** Flag `new Daddddte()` and similar unknown constructors as errors. + +**Problem:** The validator's `CallExpression` handler checks direct calls (`Foo()`) and member calls (`Foo.bar()`), but `new Foo()` is a `NewExpression` in the acorn AST — a different node type with the same `callee` shape. Unknown constructors in `new` expressions were silently ignored. + +**Fix:** Added a `NewExpression` visitor to the acorn walker in `documentdbQueryValidator.ts` that performs the same identifier check: known globals pass, near-misses produce a warning ("Did you mean Date?"), and unknown constructors produce an error. + +### Step 16: Add Date.now() and Math method completions ✅ + +**Goal:** Provide commonly-used JS method completions as individual items. + +**Changes to `jsGlobals.ts`:** +- Added `Date.now()` as a separate completion item alongside the `Date` constructor +- Replaced bare `Math` entry with individual method entries: `Math.floor()`, `Math.ceil()`, `Math.round()`, `Math.min()`, `Math.max()` +- All use sort prefix `4_` (grouped with JS globals) + +--- + +## What is NOT in Scope + +| Item | Reason | +| ------------------------------------------------------- | --------------------------------------------------------- | +| Aggregation pipeline stage-aware completions | Step 8 | +| `SignatureHelpProvider` for operator argument structure | Step 7/8 | +| TS Language Service integration (`.d.ts`) | Future work (P2) | +| Populating `returnType` on `OperatorEntry` | Separate task — not needed for cursor context | +| Deep nesting (3+ levels) context detection | Diminishing returns — fallback to `unknown` is acceptable | From 23927df0a03ed91083c5b5f371439536a42a513d Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Mar 2026 12:37:12 +0000 Subject: [PATCH 084/128] fix: include projection operators and BSON constructors in PROJECTION_COMPLETION_META MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PROJECTION_COMPLETION_META was ['field:identifier'] which returned 0 static entries — projection operators ($slice, $elemMatch, $) and BSON constructors were never shown in project/sort editors. Added 'query:projection' and 'bson' to the meta preset. --- .../src/getFilteredCompletions.test.ts | 8 ++++++-- packages/documentdb-constants/src/metaTags.ts | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/documentdb-constants/src/getFilteredCompletions.test.ts b/packages/documentdb-constants/src/getFilteredCompletions.test.ts index 046146832..02e683e5d 100644 --- a/packages/documentdb-constants/src/getFilteredCompletions.test.ts +++ b/packages/documentdb-constants/src/getFilteredCompletions.test.ts @@ -215,10 +215,14 @@ describe('completion context presets', () => { expect(metaPrefixes).toContain('variable'); }); - test('PROJECTION_COMPLETION_META looks for field:identifier (empty since runtime-injected)', () => { + test('PROJECTION_COMPLETION_META returns projection operators + BSON constructors', () => { const results = getFilteredCompletions({ meta: PROJECTION_COMPLETION_META }); // field:identifier entries are injected at runtime, not statically registered - expect(results.length).toBe(0); + // But projection operators ($, $elemMatch, $slice) and BSON constructors are static + expect(results.length).toBeGreaterThan(0); + const metas = [...new Set(results.map((r) => r.meta))]; + expect(metas).toContain('query:projection'); + expect(metas).toContain('bson'); }); }); diff --git a/packages/documentdb-constants/src/metaTags.ts b/packages/documentdb-constants/src/metaTags.ts index 6e939a58c..7a4dd7add 100644 --- a/packages/documentdb-constants/src/metaTags.ts +++ b/packages/documentdb-constants/src/metaTags.ts @@ -111,8 +111,8 @@ export const ALL_META_TAGS = [ /** Query filter contexts: find filter bar, $match stage body */ export const FILTER_COMPLETION_META: readonly string[] = ['query', 'bson', 'variable']; -/** Projection/sort contexts */ -export const PROJECTION_COMPLETION_META: readonly string[] = ['field:identifier']; +/** Projection/sort contexts: field names + projection operators */ +export const PROJECTION_COMPLETION_META: readonly string[] = ['field:identifier', 'query:projection', 'bson']; /** $group/$project/$addFields stage body: expressions + accumulators */ export const GROUP_EXPRESSION_COMPLETION_META: readonly string[] = ['expr', 'accumulator', 'bson', 'variable']; From fe42fefb22539b3b6d9cfe21c2c90a7bb1ca596a Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Mar 2026 12:38:01 +0000 Subject: [PATCH 085/128] docs: add completion provider enhancements to future work --- docs/plan/future-work.md | 431 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 431 insertions(+) create mode 100644 docs/plan/future-work.md diff --git a/docs/plan/future-work.md b/docs/plan/future-work.md new file mode 100644 index 000000000..4219de901 --- /dev/null +++ b/docs/plan/future-work.md @@ -0,0 +1,431 @@ +# Future Work + +Items moved outside the scope of the current project (filter/shell/scrapbook) or ideas generated during development. + +--- + +## SchemaAnalyzer Enhancements + +### Computed Probabilities on `getSchema()` + +`SchemaAnalyzer` currently stores `x-occurrence` per field and `x-documentsInspected` on the schema root, allowing probability to be derived as `occurrence / documentsInspected`. However, probabilities are not pre-computed on the schema output. + +**Proposal:** Add an optional `computeProbabilities` flag to `getSchema()` (default: `false`) that, when enabled, computes and includes `x-probability` (a number between 0 and 1) on every field entry in the schema output. + +It should differentiate between "global" and "local" probability. local is within the path, so if a field "name" actually exists, then it's relevant to know when e.g. 90% is a string and 10% are numbers (would suggest an error). better than having a type as "global probability" for such a field. +Similarly it makes sense for fields in a subdocument: address exists in 10% of documents, then address.name exists in 10% of documents globally, but we are more likely to look at the "local" probability, as the information would be "name" exists in 100% of "address". + +```typescript +// Proposed API change: +interface GetSchemaOptions { + /** When true, adds x-probability to every field (occurrence / documentsInspected). Default: false. */ + computeProbabilities?: boolean; +} + +getSchema(options?: GetSchemaOptions): JSONSchema; +``` + +**Use cases:** + +- Schema statistics UI — show users which fields are sparse +- Query optimization hints — warn about queries on highly sparse fields +- LLM prompt enrichment — include field probability in schema definitions for smarter query generation + +**Effort:** Low (~0.5 day). The data (`x-occurrence`, `x-documentsInspected`) is already tracked; this is a traversal + division operation during `getSchema()`. + +--- + +## Field Statistics in Completion Items + +### Problem + +`FieldCompletionData` currently shows only the BSON type and a sparse/not-sparse flag in the completion list (e.g., `"String"` or `"String (sparse)"`). The underlying `SchemaAnalyzer` already computes rich per-field statistics — occurrence counts, type distributions, value ranges — but none of this reaches the completion UI. + +A completion item for `age` could show `Number · 98% · 17–82` instead of just `Number`. This gives users immediate context about the data without running a query. + +### Available Statistics (Already Computed by SchemaAnalyzer) + +The schema's `x-` extension fields provide everything needed: + +| Schema field | What it tells you | Example display | +| ---------------------------------------- | ---------------------------------------- | ------------------------ | +| `x-occurrence` / `x-documentsInspected` | Field presence rate | `98%` or `sparse (12%)` | +| `x-typeOccurrence` (per type in `anyOf`) | Type distribution for polymorphic fields | `80% String, 20% Number` | +| `x-minValue` / `x-maxValue` | Numeric range | `17–82` | +| `x-minLength` / `x-maxLength` | String length range | `len 3–64` | +| `x-minDate` / `x-maxDate` | Date range | `2021-01–2024-12` | +| `x-trueCount` / `x-falseCount` | Boolean distribution | `73% true` | +| `x-minItems` / `x-maxItems` | Array size range | `[2–15] items` | + +### Proposal: Add `description` to `FieldCompletionData` + +The simplest approach: add a pre-compiled `description` string to `FieldCompletionData`, built during `toFieldCompletionItems()` from the schema stats. Monaco renders this in the completion detail/documentation panel. + +```typescript +export interface FieldCompletionData { + // ... existing fields ... + + /** + * Human-readable summary of field statistics from the schema sample. + * Pre-compiled from SchemaAnalyzer's x- extension fields. + * + * Examples: + * "Number · 98% · range 17–82" + * "String · 100% · len 3–64" + * "Boolean · 12% (sparse) · 73% true" + * "80% String, 20% Number · 95%" + */ + description?: string; +} +``` + +This keeps the interface simple — one optional string — while the compilation logic lives in `toFieldCompletionItems()` which already has access to the schema. The completion provider maps `description` to `CompletionItem.documentation` (shown in the detail panel on focus). + +### Alternative: Structured Stats Object + +For consumers that need programmatic access (e.g., type-aware operator ordering in Step 4.5, or a schema statistics UI): + +```typescript +export interface FieldStats { + /** Field presence rate (0–1), e.g. 0.98 means present in 98% of documents */ + presenceRate?: number; + /** Type distribution for polymorphic fields, e.g. { "string": 0.8, "number": 0.2 } */ + typeDistribution?: Record; + /** Numeric value range */ + numericRange?: { min: number; max: number }; + /** String length range */ + stringLengthRange?: { min: number; max: number }; + /** Date range */ + dateRange?: { min: string; max: string }; + /** Boolean true rate (0–1) */ + booleanTrueRate?: number; + /** Array size range */ + arraySizeRange?: { min: number; max: number }; +} + +export interface FieldCompletionData { + // ... existing fields ... + stats?: FieldStats; + description?: string; // compiled from stats for display +} +``` + +Both approaches can coexist — `stats` for programmatic use, `description` for display. The compilation from `stats` to `description` is a simple formatting function. + +### Implementation Path + +1. Extend `FieldEntry` in `schema-analyzer` to carry raw stats (occurrence count, type occurrence counts, value ranges) — the data is already in the schema, just not surfaced on `FieldEntry` +2. Extend `toFieldCompletionItems()` to compile stats into a `description` string +3. Map `description` to `CompletionItem.documentation` in `documentdbQueryCompletionProvider.ts` + +### Effort + +Low (~1 day). The statistics are already computed and stored in the schema. This is a data-threading exercise — expose them on `FieldEntry`, format them in `toFieldCompletionItems()`, and display in the completion item. + +--- + +## MongoDB Constants Package + +When the extension connects to a MongoDB instance (not DocumentDB), the completion providers should offer the full MongoDB operator set. This requires a separate constants package: + +- **Package:** `packages/mongodb-constants/` (or reuse `@mongodb-js/mongodb-constants` under Apache-2.0) +- **Interface:** Exports the same `OperatorEntry[]` interface as `documentdb-constants` +- **Scope:** Full MongoDB 8.0 operator set (superset of DocumentDB) +- The switching logic is already designed — `isDocumentDB(connection)` determines which constants to load + +**Dependency:** Requires `documentdb-constants` to be built first (establishes the shared interface). + +--- + +## Schema Statistics UI + +A dedicated schema visualization panel showing: + +- Field presence probability (occurrence / documents inspected) +- Type distribution per field (polymorphic fields) +- Value range statistics (min/max for numbers, dates, string lengths) +- Array size distributions + +**Potential dependency:** `mongodb-schema` package for reservoir-sampled representative values and unique value detection (features `SchemaAnalyzer` does not provide). See 01-high-level-plan.md "When might mongodb-schema become attractive?" section. + +--- + +## Document Editor Schema Integration (F1) + +Wire `SchemaAnalyzer` output into Monaco's `setDiagnosticsOptions()` for the document view editor. This provides real-time validation and autocomplete when editing individual documents. + +**Status:** Deferred from the main plan (listed as component F1 in 01-high-level-plan.md). + +--- + +## Lazy / On-Demand Operator Data Loading + +**Context:** `documentdb-constants` currently calls `loadOperators()` eagerly at module load time (in `index.ts`), which registers all ~300 operator entries — expression operators, stages, accumulators, window operators, BSON constructors, update operators, etc. — into memory on first import. For completions that are only relevant inside an aggregation pipeline, or only inside an `$update` call, there is no reason to load all categories at extension startup. + +The refactor in PR #513 already lays the groundwork: each data module exports an independent `loadXxx()` function, and `loadOperators()` simply calls all of them. The architecture now supports selective loading without further restructuring. + +### What to revisit + +1. **Audit which categories are needed at launch vs. on-demand.** + Categories needed for the most common use case (filter bar, shell prompt) are a subset: + - Always load at launch: `query*`, `variable`, `bson` (small, universally needed) + - Load on first aggregation: `stage`, `accumulator`, `window`, `expr*` (bulk of the data) + - Load on first update: `update*` + +2. **Introduce category-group load functions** in `index.ts`: + + ```typescript + export function loadCoreCompletions(): void { + /* query, variable, bson */ + } + export function loadAggregationCompletions(): void { + /* stage, accumulator, window, expr* */ + } + export function loadUpdateCompletions(): void { + /* update* */ + } + ``` + + The registry's idempotency guard (Set-based dedup added in PR #513) means calling these multiple times is safe — call them lazily on first need. + +3. **Wire into CompletionItemProviders** (Steps 4–8): each provider calls its relevant load group before returning completions. Because the registry is module-global and dedup-guarded, the load is a no-op on subsequent invocations. + +4. **Measure the impact.** Profile `getAllCompletions()` time and initial `import` time before and after. The bulk is `expressionOperators.ts` (~143 entries) and `queryOperators.ts` (~43 entries). Both are synchronous array allocations, so the gain may be modest — measure first, optimize based on data. + +### Related: other static data in the extension + +Audit other eagerly-loaded static tables elsewhere in the extension for the same pattern: + +- Grammar files (`grammar/`) +- Any `const` arrays populated at module scope in `src/` that are only used in specific views or commands + +**Effort:** Medium (~1 day for the constants package split + provider wiring). Measurement first (~0.5 day). + +**Dependency:** CompletionItemProvider implementation (Steps 4–8) must be at least partially in place before the wiring step is meaningful. + +--- + +## Stage-Aware Aggregation Pipeline Preview + +Compass implements per-stage preview (showing stage output next to the pipeline editor). This is a differentiating feature we could implement: + +- Each stage shows a live preview of documents at that pipeline point +- Schema propagation between stages (what Compass does NOT implement — a competitive advantage) + +**Dependency:** Requires Aggregation `CompletionItemProvider` (Step 8) to be complete first. + +--- + +## TS Language Service for Advanced Completions (P2) + +The analysis documents (17-implementation-recommendations.md) identified Monaco's built-in TypeScript Language Service as a P2 optional enhancement for completions: + +- Load shell API `.d.ts` plus per-collection schema `.d.ts` into Monaco's TS worker via `addExtraLib()` +- Provides hover docs, type inference, and richer completions beyond static constant lists +- Complements (does not replace) `documentdb-constants`-based completions + +**Prerequisite:** Shell API `.d.ts` generation (Step 5 in 01-high-level-plan.md). + +--- + +## Index Advisor Integration with Completions + +The index advisor feature could suggest index-friendly query patterns when users are writing queries. For example: + +- When typing a `$match` stage, suggest fields that have indexes +- Warn when queries use operators that can't leverage existing indexes + +**Dependency:** Requires both `documentdb-constants` and the index advisor to be operational. + +--- + +## Agentic Workflow: Operator Reference Freshness Check + +An automated agentic workflow that periodically re-scrapes the DocumentDB compatibility docs and detects external drift (new operators, changed descriptions, URL restructuring, deprecated operators). + +### Motivation + +The `documentdb-constants` package has CI tests that verify internal consistency — the implementation matches the checked-in dump and overrides. But these tests will never fail on their own because they only compare files within the repo. External drift (DocumentDB adds a new operator, changes a description, restructures docs URLs) is invisible until someone manually re-runs the scraper. + +### Workflow Steps + +``` +1. npm run scrape + → Fetches latest compatibility page + per-operator doc pages + → Regenerates resources/operator-reference-scraped.md + +2. git diff resources/operator-reference-scraped.md + → If no diff: "No upstream changes. Done." → exit + → If diff: continue + +3. npm run evaluate + → Reports: new gaps (operators with empty descriptions), + redundant overrides (override provides description that now + exists upstream), coverage stats + +4. npm run generate + → Regenerates .ts files from updated dump + existing overrides + +5. npm test + → Runs all CI tests against the updated code + → Failures indicate drift that needs attention: + - New operator in dump but missing from generated code + - Description changed upstream (override may mask or conflict) + - Doc URL changed (link verification test catches this) + - Operator removed upstream (no-extras test catches this) + +6. If diff or test failures exist: + → Open a PR with: + - Updated operator-reference-scraped.md + - Updated generated .ts files (if generate succeeded) + - Summary of what changed (from git diff) + - List of test failures (if any) + - Evaluation report (gaps, redundant overrides) + → Assign for human review + +7. Human reviews: + → New operators: verify descriptions, add overrides if needed + → Changed descriptions: decide whether to keep override or adopt upstream + → Removed operators: confirm deprecation, update not-listed section + → URL changes: verify links still resolve +``` + +### Schedule + +Weekly or monthly. DocumentDB compatibility updates are typically tied to major/minor version releases (a few times per year), so monthly is sufficient. Weekly provides earlier detection. + +### Agent Prompt (Draft) + +``` +You are maintaining the documentdb-constants package in vscode-documentdb. + +1. Run: cd packages/documentdb-constants && npm run scrape +2. Check: git diff resources/operator-reference-scraped.md +3. If no changes: report "No upstream drift detected" and stop. +4. If changes: run npm run evaluate, then npm run generate, then npm test. +5. If tests pass: commit all changes and open a PR titled + "chore: update documentdb-constants operator reference" + with a summary of what changed. +6. If tests fail: open a PR anyway with the failures noted, + flagged for human review. +``` + +### Prerequisites + +- The scraper (`scripts/scrape-operator-docs.ts`) must remain functional — it depends on the structure of the upstream docs repo +- GitHub Actions or equivalent CI runner with network access for the scraper +- Agent must have permission to create branches and open PRs + +### Existing Infrastructure + +| Component | Status | Location | +| -------------------------------- | ------------ | ------------------------------------------- | +| Scraper | ✅ Built | `scripts/scrape-operator-docs.ts` | +| Override system | ✅ Built | `resources/operator-reference-overrides.md` | +| Generator | ✅ Built | `scripts/generate-from-reference.ts` | +| Evaluator | ✅ Built | `scripts/evaluate-overrides.ts` | +| CI tests (internal consistency) | ✅ Built | `src/operatorReference.test.ts` | +| CI tests (merged dump+overrides) | ✅ Built | `src/operatorReference.test.ts` | +| GitHub Actions workflow | ❌ Not built | Needs `.github/workflows/` YAML | + +--- + +## Additional Monaco Language Feature Providers + +### Context + +Beyond `CompletionItemProvider` and `HoverProvider` (implemented in Step 4), Monaco exposes many more language feature providers. The table below catalogues all of them with a per-editor-type usefulness rating. + +### Provider Reference Table + +| Provider | Query Editors (filter/project/sort) | Aggregation Pipeline | Scrapbook | Notes | +|---|---|---|---|---| +| **CompletionItemProvider** | **Implemented** | Planned (Step 8) | Planned (Step 7) | Static operators + dynamic fields | +| **HoverProvider** | **Implemented** | Planned | Planned | Operator docs on hover | +| **SignatureHelpProvider** | **High** | **High** | **High** | Parameter hints for BSON constructors, e.g. `ObjectId(│hex│)` | +| **CodeActionProvider** | **High** | **High** | Medium | Quick-fix for near-miss warnings → auto-replace typo | +| **InlayHintsProvider** | **High** | Medium | Low | Inline type annotations, e.g. `{ age: ▸int 25 }` | +| **DocumentFormattingEditProvider** | Medium | **High** | **High** | Auto-format/prettify; low value for single-line filters | +| **FoldingRangeProvider** | Low | **High** | **High** | Fold pipeline stages, nested objects | +| **DocumentSymbolProvider** | Low | **High** | **High** | Outline / breadcrumbs — pipeline stages as symbols | +| **CodeLensProvider** | Medium | Medium | **High** | "Run" / "Run Stage" above code blocks | +| **LinkProvider** | Medium | Medium | Low | Clickable operator names → docs (currently shown in hover only) | +| **RenameProvider** | Low | Medium | **High** | Rename field references across pipeline or script | +| **DocumentRangeFormattingEditProvider** | Low | Medium | Medium | Format selection only | +| **OnTypeFormattingEditProvider** | Medium | Medium | Medium | Auto-indent on `{`, `}`, `,` | +| **DocumentSemanticTokensProvider** | Medium | Medium | Medium | Richer coloring: operators vs fields vs constructors | +| **InlineCompletionProvider** | Low | Medium | Medium | Ghost-text suggestions (Copilot-style); needs AI backend | +| **DocumentHighlightProvider** | Low | Low | Medium | Highlight all occurrences of a symbol | +| **DefinitionProvider** | Low | Low | Medium | Go to definition (only meaningful with `let`/`const`) | +| **ReferenceProvider** | Low | Low | Medium | Find all references | +| **LinkedEditingRangeProvider** | Low | Low | Low | Simultaneous edit of matching tags; not applicable | +| **DeclarationProvider** | Low | Low | Low | Mostly redundant with DefinitionProvider | +| **ColorProvider** | Low | Low | Low | Color picker — not applicable | + +### Recommended Next Providers + +#### 1. SignatureHelpProvider + +**Usefulness:** High across all editor types. + +Shows parameter hints when typing inside BSON constructor or function calls — e.g., `ObjectId(|hex string|)`, `NumberDecimal(|value|)`, `ISODate(|ISO 8601 string|)`. + +The metadata is already available: `OperatorEntry.snippet` defines the parameter structure with tab stops (`${1:hex}`). The provider parses the snippet definition to extract parameter names and types, then shows them as the user types between parentheses. + +**Effort:** Low (~0.5 day). Trigger characters: `(`, `,`. Parse the matching `OperatorEntry.snippet` for the current function name. + +#### 2. CodeActionProvider + +**Usefulness:** High for query editors and aggregation pipelines. + +Provides quick-fix actions for the near-miss warnings already produced by the `acorn` validator. When the validator emits "Did you mean 'Date'?" for `Daate.now()`, the CodeActionProvider offers a one-click fix that replaces `Daate` with `Date`. + +This pairs directly with the existing `Diagnostic` infrastructure — each warning diagnostic becomes a `CodeAction` with a `WorkspaceEdit` that performs the replacement. + +**Effort:** Low (~0.5 day). The validator already computes the exact offset range and the suggested replacement. The CodeActionProvider maps diagnostics to edits. + +#### 3. FoldingRangeProvider + +**Usefulness:** High for aggregation pipelines and scrapbook, low for single-line query editors. + +Enables code folding for nested objects, arrays, and pipeline stages. In a multi-stage aggregation pipeline, each stage can be collapsed independently. In scrapbook scripts, function bodies and complex expressions can be folded. + +**Effort:** Low (~0.5 day). Can be implemented with simple brace/bracket matching or by reusing the `acorn` AST to identify foldable regions. + +--- + +## Completion Provider Enhancements + +### Dot-triggered method completions for JS globals + +When the user types `Date.` or `Math.`, trigger method-specific completions dynamically instead of showing the full completion list. This requires detecting the word before the `.` trigger character and returning method completions for that specific object. + +**Approach:** In the completion provider, when charBefore is `.` and the word before the dot is a known JS global (`Date`, `Math`), return whitelisted methods from shell-bson-parser's `ALLOWED_CLASS_EXPRESSIONS`. + +**Effort:** Medium (~1 day). Requires changes to cursor context detection and a new method resolution path in the completion provider. + +### Projection/sort value suggestions + +Project editors need `1` / `0` / `true` / `false` as value-position suggestions (include/exclude fields). Sort editors need `1` / `-1` (ascending/descending). Currently no type suggestions are shown at value position in these editors because the BSON field type is not relevant for projection semantics. + +**Approach:** Detect `EditorType.Project` or `EditorType.Sort` in `createValuePositionCompletions` and return editor-specific value suggestions instead of BSON-type-based ones. + +**Effort:** Low (~0.5 day). + +### Method-level validation for JS globals + +The validator currently checks object-level identifiers (`Date` → known, `Daate` → warning) but does not validate method names (`Date.nodw()` → no diagnostic). Adding method-level validation would require maintaining a whitelist of methods per global class, matching shell-bson-parser's `ALLOWED_CLASS_EXPRESSIONS`. + +**Effort:** Low (~0.5 day). The whitelist already exists in shell-bson-parser's scope.js. + +### Field name validation against schema + +The validator intentionally does not flag unknown field names (`{ nonExistentField: 1 }` produces no diagnostic). With the completion store holding known fields per session, field names could be validated against the schema with severity `'info'` (hint) — "Field 'nonExistentField' not found in the sampled schema." + +**Effort:** Medium (~1 day). Requires wiring the completion store into the validator, which currently has no Monaco or session dependencies. + +### Deep nesting context detection (3+ levels) + +The cursor context heuristic scans backward through 1-2 levels of nesting. At 3+ levels (e.g., `{ $and: [{ age: { $gt: { $numberLong: | } } }] }`), it may fall back to `unknown`. An AST-based approach (dummy completion insertion) could improve accuracy for deeply nested positions. + +**Effort:** High (~2 days). The dummy completion strategy has fundamental ambiguity issues (see 4.5 plan "Why Not Use a Dummy Completion Strategy"). From 14694e1323b81fe1b7b701519bf1e2573aab96d9 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Mar 2026 13:29:28 +0000 Subject: [PATCH 086/128] chore: remove gitignored docs/plan files from tracking --- .../04.5-context-sensitive-completions.md | 459 ------------------ docs/plan/future-work.md | 431 ---------------- 2 files changed, 890 deletions(-) delete mode 100644 docs/plan/04.5-context-sensitive-completions.md delete mode 100644 docs/plan/future-work.md diff --git a/docs/plan/04.5-context-sensitive-completions.md b/docs/plan/04.5-context-sensitive-completions.md deleted file mode 100644 index 1fdaa9780..000000000 --- a/docs/plan/04.5-context-sensitive-completions.md +++ /dev/null @@ -1,459 +0,0 @@ -# Step 4.5: Context-Sensitive Completions — Implementation Plan - -> **Prerequisites:** Step 4 complete (PR #518). The `documentdb-query` language, `CompletionItemProvider`, `completionStore`, and `documentdb-constants` infrastructure are all in place. - -## Status: ✅ Complete - ---- - -## Problem - -The current completion provider (`createCompletionItems`) returns a **flat list** of all operators + all field names regardless of cursor position. For example, in: - -``` -{ _id: } -``` - -The user sees `$gt`, `$eq`, `address`, `name`, `$regex`, etc. — the same list as when the cursor is at `{ }`. - -A better experience would be: - -| Cursor position | Example | Should show | Should NOT show | -| ------------------------------------ | --------------------------------------------- | ------------------------------------------------ | ---------------------------------------- | -| **Key position** (root) | `{ }` | Field names, `$and`, `$or`, `$nor`, `$comment` | Value operators (`$gt`, `$lt`, `$regex`) | -| **Value position** | `{ _id: }` | BSON constructors (`ObjectId`, `UUID`), literals | Field names, query operators | -| **Nested operator position** | `{ age: { } }` | `$gt`, `$lt`, `$eq`, `$in`, `$exists`, etc. | Field names, logical operators | -| **Nested operator position (typed)** | `{ age: { } }` where `age` is Number | `$gt`, `$gte`, `$lt`, `$lte` first, then others | `$regex` (string-only) demoted to end | -| **`$and`/`$or` array element** | `{ $and: [ ] }` | Same as root key position | — | - -Compass's query bar does **not** do this — it returns the same flat list. This would be a differentiating feature. - ---- - -## Existing Infrastructure (Ready to Use) - -The Step 4 implementation already built all the pieces needed: - -| Component | Status | What it provides | -| --------------------------------------- | ---------------------------------------------------------- | -------------------------------------------------------------------------------------- | -| `acorn` dependency | ✅ In place | JS expression parser for AST | -| `acorn-walk` dependency | ✅ In place | AST traversal | -| `documentdbQueryValidator.ts` | ✅ Already uses `acorn` to parse expressions and walk ASTs | -| `OperatorEntry.applicableBsonTypes` | ✅ Defined in `documentdb-constants/types.ts` | Per-operator BSON type affinity (e.g., `$regex` → `['string']`, `$size` → `['array']`) | -| `getFilteredCompletions({ bsonTypes })` | ✅ Built + tested | Filters operators by BSON type | -| `FieldCompletionData.bsonType` | ✅ Available | Raw BSON type string per field from schema | -| `completionStore` | ✅ In place | Provides per-session field data with types | - -**Key insight:** No new dependencies or packages are needed. This is pure logic work in the completion provider, using `acorn` (already a dependency) to parse the expression and determine cursor context. - ---- - -## Design: Cursor Context Detection - -### AST-Based Approach - -Parse the editor content with `acorn` and determine the cursor's semantic position by walking the AST. The cursor is a character offset; find which AST node contains it. - -```typescript -export type CursorContext = - | { position: 'key'; depth: 0 } // Root key position: { } - | { position: 'key'; depth: number } // Nested key position (inside $elemMatch, etc.) - | { position: 'value'; fieldName: string; fieldBsonType?: string } - // Value position: { fieldName: } - | { position: 'operator'; fieldName: string; fieldBsonType?: string } - // Nested operator: { fieldName: { } } - | { position: 'array-element'; parentOperator: string } - // Inside $and/$or/$nor array: { $and: [ ] } - | { position: 'unknown' }; // Can't determine — show everything (safe fallback) -``` - -### Partial-Input Challenge - -The main difficulty is that acorn **cannot parse incomplete expressions**. When the cursor is at `{ age: { $` the expression is syntactically invalid. Strategies: - -1. **Dummy completion:** Insert a placeholder at the cursor position to make the expression parseable. For example, replace `{ age: { $` with `{ age: { $__placeholder__: 0 } }` and parse that. -2. **Heuristic fallback:** If acorn fails, fall back to a simpler text-based analysis: - - Count unmatched `{` and `}` to estimate nesting depth - - Look backward from cursor for `:` (value position), `{` (key/operator position), `[` (array element) - - Check if the enclosing key starts with `$` (operator position vs key position) -3. **Hybrid:** Try acorn first, fall back to heuristic on parse failure. - -**Recommendation:** Start with approach (2) — the heuristic. It handles the common cases without the complexity of AST surgery on partial input. The fallback to the full list (current behavior) for ambiguous cases is acceptable; users still get completions, just not perfectly filtered. - -### Heuristic Algorithm - -``` -function detectCursorContext(text: string, cursorOffset: number): CursorContext: - 1. Find the character immediately before the cursor (skip whitespace) - 2. If char is ':' → VALUE position - - Walk backward to find the key name - - Look up the key in the completion store to get bsonType - 3. If char is '{': - - Walk backward to find what's before this '{' - - If preceded by ':' and a key name → OPERATOR position (nested object) - - The key name is the field name → look up bsonType - - If preceded by nothing / start-of-input → KEY position (root) - 4. If char is '[': - - Walk backward to find what precedes the '[' - - If preceded by '$and', '$or', '$nor' → ARRAY-ELEMENT position - 5. If char is ',': - - Determine whether we're inside an object or array - - Object → same as KEY position at current depth - - Array of $and/$or/$nor → ARRAY-ELEMENT position - 6. Else → UNKNOWN (show everything) -``` - ---- - -## Completion Rules Per Context - -| Context | Operators to show | Fields to show | Sort priority | -| ------------------------- | ------------------------------------------------------------------------------- | -------------- | --------------------------------------------------------------------------------------- | -| `key` (root) | Logical only: `$and`, `$or`, `$nor`, `$not`, `$comment`, `$expr`, `$jsonSchema` | All fields | Fields first (sort prefix `0_`), logical operators second (`1_`) | -| `value` | BSON constructors only | None | Constructors first | -| `operator` (no type info) | All query operators (comparison, element, array, etc.) | None | Default sort | -| `operator` (typed) | **All** query operators — type-relevant first, non-matching demoted to end | None | Type-relevant operators first (`0_`), universal second (`1_`), non-matching last (`2_`) | -| `array-element` | Same as `key` (root) | All fields | Same as `key` | -| `unknown` | All (current behavior) | All | Current behavior | - -### Type-Aware Operator Ordering - -When the field type is known, **all operators are still shown** — nothing is excluded. The ordering uses `sortText` prefixes to rank operators by type relevance: - -1. **`0_`** — Type-relevant operators: those whose `applicableBsonTypes` includes the field's type (e.g., `$regex` for strings, `$size` for arrays) -2. **`1_`** — Universal operators: those with no `applicableBsonTypes` set (e.g., `$eq`, `$ne`, `$in`, `$exists`) -3. **`2_`** — Non-matching operators: those whose `applicableBsonTypes` is set but does NOT include the field's type (e.g., `$regex` when the field is a Number) - -This ensures completions still show `$regex` for a Number field (in case the field is sometimes a string), but it appears at the bottom of the list, not the top. - -> **Design rationale:** A field like `age` may be a Number 98% of the time but occasionally a String. Completely hiding `$regex` would be incorrect. Demoting it to the end of each section preserves discoverability while keeping the most relevant operators front and center. - -Example for `{ age: { } }` where `age` is `Number`: - -``` -$gt 0_$gt (no applicableBsonTypes → universal, but commonly number-relevant) -$gte 0_$gte -$lt 0_$lt -$lte 0_$lte -$eq 1_$eq (universal — no applicableBsonTypes) -$ne 1_$ne -$in 1_$in -$exists 1_$exists -$regex 2_$regex (applicableBsonTypes=['string'], doesn't match 'number' → demoted) -$all 2_$all (applicableBsonTypes=['array'], doesn't match 'number' → demoted) -$size 2_$size (applicableBsonTypes=['array'], doesn't match 'number' → demoted) -``` - -**Note:** Comparison operators like `$gt`, `$lt` etc. are universal (no `applicableBsonTypes`), so they get sort prefix `1_`. In practice, this is the right behavior — they work on all types. Only operators with an explicit type restriction get boosted (`0_`) or demoted (`2_`). - -**Pre-step (can be done in current PR):** Before the full cursor context detection (Steps 1–3) is implemented, the type-aware sorting can be applied as a standalone enhancement to `createCompletionItems()` / `mapOperatorToCompletionItem()`. When a `fieldBsonType` is available (e.g., from a future `CursorContext`), pass it through and use it for `sortText` assignment. - ---- - -## Implementation Steps - -### Step 1: Create Cursor Context Detector ✅ - -**Goal:** A pure function that determines the semantic cursor position from editor text + offset. - -**File created:** - -- `src/webviews/documentdbQuery/cursorContext.ts` -- `src/webviews/documentdbQuery/cursorContext.test.ts` - -**Implementation:** - -1. Implement `detectCursorContext(text: string, cursorOffset: number, fieldLookup?: (fieldName: string) => string | undefined): CursorContext` -2. The `fieldLookup` callback resolves a field name to its BSON type string (from the completion store) -3. Start with the heuristic approach — character scanning backward from cursor -4. Handle edge cases: empty input, cursor at offset 0, cursor at end, nested structures - -**Test cases:** - -- `{ | }` → `key` at depth 0 -- `{ _id: | }` → `value` with fieldName `_id` -- `{ age: { | } }` → `operator` with fieldName `age` -- `{ $and: [ | ] }` → `array-element` with parentOperator `$and` -- `{ name: "Alice", | }` → `key` at depth 0 (after comma) -- `{ age: { $gt: 5, | } }` → `operator` with fieldName `age` (after comma inside nested object) -- (empty) → `unknown` - -### Step 1.5: Tests for Incomplete / Broken Input ✅ - -**Goal:** Verify that `detectCursorContext` gracefully handles partially-typed expressions — i.e., the exact state the editor is in while the user is actively typing. - -**File updated:** - -- `src/webviews/documentdbQuery/cursorContext.test.ts` (extended from Step 1) - -**Test cases:** - -| Input (cursor = end) | Expected context | Rationale | -| -------------------- | --------------------------------------------- | -------------------------------------------------------------- | -| `{ age: ` | `value` with `fieldName: 'age'` | Colon just typed — user is about to enter a value | -| `{ age: $` | `value` with `fieldName: 'age'` | Started typing a BSON constructor like `$` (or accidental `$`) | -| `{ age: $ }` | `value` with `fieldName: 'age'` | Same as above but closing brace is present | -| `{ age: {` | `operator` with `fieldName: 'age'` | Opened nested object — expects comparison operators | -| `{ age: { $` | `operator` with `fieldName: 'age'` | Began typing an operator like `$gt` | -| `{ age: { $ }` | `operator` with `fieldName: 'age'` | Incomplete operator inside nested object | -| `{ age: { $g` | `operator` with `fieldName: 'age'` | Partially typed `$gt` | -| `{ ` | `key` at depth 0 | Opened root object, haven't typed a field yet | -| `{ a` | `key` at depth 0 | Partially typed a field name | -| `{ name: "Alice", ` | `key` at depth 0 | Comma after first pair, new key expected | -| `{ name: "Alice", a` | `key` at depth 0 | Partially typed second field name | -| `{ $and: [` | `array-element` with `parentOperator: '$and'` | Opened array for logical operator | -| `{ $and: [ {` | `key` at depth 1 (or `array-element`) | Inside an `$and` array element object | -| `{ age: { $gt: 5, ` | `operator` with `fieldName: 'age'` | After comma inside nested operator object | -| `{` | `key` at depth 0 | Just the opening brace | -| (empty string) | `unknown` | Nothing typed yet | - -**Key principle:** Every partially-typed state must produce a _useful_ context (not `unknown`) whenever possible. The fallback to `unknown` should only occur when there is genuinely no signal — not just because the input fails to parse. - -#### Why Not Use a "Dummy Completion" Strategy? - -The "dummy completion" approach works by inserting a synthetic placeholder at the cursor position (e.g., replacing `{ age: { $` with `{ age: { $__placeholder__: 0 } }`) to make the expression parseable by `acorn`, then inspecting the resulting AST to determine cursor context. - -While conceptually clean, this strategy has several practical problems that make it **unsuitable as the primary approach**: - -1. **Ambiguity of placeholder semantics.** Where exactly to insert the placeholder and what it should look like depends on context — the very thing we're trying to determine. For `{ age: $`, should the placeholder be a value (`{ age: $__placeholder__ }`) or a nested key (`{ age: { $__placeholder__: 0 } }`)? The answer changes the AST shape and therefore the detected context. This creates a chicken-and-egg problem. - -2. **Fragility with multiple parse errors.** Real mid-typing states often have _multiple_ syntax issues: missing closing braces, unterminated strings, trailing commas, bare `$` tokens, etc. Patching one error with a placeholder doesn't guarantee the rest of the expression becomes valid. The repair logic quickly becomes its own mini-parser — defeating the purpose of leveraging `acorn`. - -3. **Hard-to-test edge cases.** Each incomplete state requires a specific repair heuristic. Testing that `{ age: { $gt: 5, ` becomes `{ age: { $gt: 5, __placeholder__: 0 } }` (and not some other shape) is one test case — but there are dozens of partially-typed states, each needing its own repair rule. The heuristic scanner, by contrast, operates uniformly: it scans backward from the cursor and classifies based on the nearest structural character. - -4. **Performance overhead.** Every completion request would require string surgery (insert placeholder, possibly add closing braces) followed by a full `acorn` parse. The heuristic scanner is `O(n)` backward from the cursor with no parsing step, making it faster for the hot path that fires on every keystroke. - -5. **Maintenance burden.** The repair heuristics are tightly coupled to `acorn`'s error behavior. If `acorn` changes how it reports or recovers from errors, the repair logic may silently break. The heuristic approach has no such dependency — it looks at raw characters. - -**Bottom line:** The heuristic scanner is more predictable, easier to test exhaustively (as this Step 1.5 demonstrates), and avoids the fundamental ambiguity of trying to "fix" broken input before understanding it. The dummy-completion strategy can be revisited as an _enhancement_ for deeply-nested cases where the heuristic loses signal, but it should not be the foundation. - ---- - -### Step 2: Update CompletionItemProvider to Use Context ✅ - -**Goal:** Wire cursor context into the completion pipeline. - -**Files modified:** - -- `src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts` -- `src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts` - -**Implementation:** - -1. Add `cursorContext: CursorContext` to `CreateCompletionItemsParams` -2. In `createCompletionItems()`, branch on `cursorContext.position`: - - `key` → return field completions + logical operator subset - - `value` → return BSON constructors only (meta `'bson'`) - - `operator` → return query operators, optionally filtered by `fieldBsonType` - - `array-element` → same as `key` - - `unknown` → current behavior (all operators + all fields) -3. Apply sort prefixes based on type relevance - -### Step 3: Wire Context Detection in registerLanguage.ts ✅ - -**Goal:** Call `detectCursorContext()` in the completion provider and pass it through. - -**Files modified:** - -- `src/webviews/documentdbQuery/registerLanguage.ts` - -**Implementation:** - -1. In `provideCompletionItems`, compute cursor offset from position: - ```typescript - const cursorOffset = model.getOffsetAt(position); - const text = model.getValue(); - const context = detectCursorContext(text, cursorOffset, fieldLookup); - ``` -2. Create `fieldLookup` from the completion store: - ```typescript - const fieldLookup = (fieldName: string) => { - const ctx = getCompletionContext(parsed?.sessionId ?? ''); - return ctx?.fields.find((f) => f.fieldName === fieldName)?.bsonType; - }; - ``` -3. Pass `cursorContext` to `createCompletionItems()` - -### Step 4: Tests and Verification ✅ - -**Verification checklist:** - -- [x] `{ }` → shows field names + logical operators only -- [x] `{ _id: }` → shows BSON constructors (ObjectId, UUID, etc.) -- [x] `{ age: { } }` → shows comparison/element/array query operators -- [x] `{ age: { } }` with `age` typed as Number → `$regex` demoted, `$bitsAllSet` promoted, `$eq` universal -- [x] `{ $and: [ ] }` → shows field names + logical operators (root-like) -- [x] Unknown/ambiguous positions → falls back to full list (no regressions) -- [x] All existing tests continue to pass (48 original + 16 context-sensitive + 41 cursor context = 105 new tests) -- [x] `npm run build` succeeds -- [x] `npm run lint` passes - -**Implementation notes:** - -- The plan originally expected `depth: 0` for root-level key positions. The implementation uses `depth: 1` because the root `{` counts as depth 1 (0 would mean "outside all braces"). Tests adjusted accordingly. -- `KEY_POSITION_OPERATORS` is defined as a `Set` of operator values rather than filtering by meta tag, because `query:evaluation` contains both key-position operators (`$expr`, `$jsonSchema`) and operator-position operators (`$regex`, `$mod`). A value-based set is more precise. -- `$text` and `$where` are included in `KEY_POSITION_OPERATORS` because they are top-level query operators (appear at key position in a query document), not inside nested `{ field: { ... } }` objects. - ---- - -## File Map - -### New files - -| File | Purpose | -| ---------------------------------------------------- | ------------------------------- | -| `src/webviews/documentdbQuery/cursorContext.ts` | Cursor position detection logic | -| `src/webviews/documentdbQuery/cursorContext.test.ts` | Unit tests | - -### Modified files - -| File | Change | -| ------------------------------------------------------------------------ | ---------------------------------------- | -| `src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts` | Branch completions by cursor context | -| `src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts` | New tests for context-sensitive behavior | -| `src/webviews/documentdbQuery/registerLanguage.ts` | Wire context detection into provider | - ---- - -## Additional Steps (PR #530) - -The following steps were completed as part of PR #530, extending the original plan with improvements discovered during review and manual testing. - -### Step 5: Refactor completions into folder + type-aware value suggestions ✅ - -**Goal:** Organize completions code into a structured folder and add type-aware value suggestions. - -**Files created:** -- `src/webviews/documentdbQuery/completions/createCompletionItems.ts` — main entry point -- `src/webviews/documentdbQuery/completions/mapCompletionItems.ts` — operator/field mapping -- `src/webviews/documentdbQuery/completions/typeSuggestions.ts` — type-aware value suggestions (boolean → true/false, number → range queries, etc.) -- `src/webviews/documentdbQuery/completions/snippetUtils.ts` — snippet text utilities -- `src/webviews/documentdbQuery/completions/index.ts` — barrel export -- `src/webviews/documentdbQuery/documentdbQueryCompletionProvider.ts` — updated to re-export from folder - -**Changes:** -- Extracted `KEY_POSITION_OPERATORS`, completion builder functions, and mapping functions into the `completions/` subfolder -- Added `TypeSuggestionDef` system: when the field's BSON type is known, value-position completions include type-specific suggestions (sort prefix `00_`) above operators - -### Step 6: Create completion knowledge configuration ✅ - -**Goal:** Centralise curated domain rules that are not part of `documentdb-constants` but are needed for context-sensitive completions. - -**File created:** -- `src/webviews/documentdbQuery/completions/completionKnowledge.ts` - -**Contents:** -- `KEY_POSITION_OPERATORS` — operators valid only at root query level (`$and`, `$or`, `$nor`, `$not`, `$comment`, `$expr`, `$jsonSchema`, `$text`, `$where`), with documentation explaining why each is key-position-only -- `LABEL_PLACEHOLDER` — the `…` (U+2026) character for completion labels -- `INFO_INDICATOR` — the `ℹ` (U+2139) character for example descriptions - -**Rationale:** `documentdb-constants` is auto-generated from operator reference and is intentionally generic. The knowledge file captures syntactic rules about _where_ operators are valid that the generic registry does not encode. - -### Step 7: Fix $and/$or double-brace bug ✅ - -**Goal:** Fix bug where selecting `$and` from the completion list at key position produces double braces: `{ { $and: [...] } }`. - -**Root cause:** `createKeyPositionCompletions` called `mapOperatorToCompletionItem()` without `shouldStripBraces: true`. The `$and` snippet from `documentdb-constants` is `{ $and: [{ ${1:expression} }] }` (includes outer braces). At key position, the user is already inside `{ }`, so inserting the full snippet created double-nesting. - -**Fix:** Pass `shouldStripBraces: true` in `createKeyPositionCompletions` so outer `{ }` are stripped, producing `$and: [{ ${1:expression} }]`. - -### Step 8: Empty/unknown input shows key-position completions ✅ - -**Goal:** When the input box is empty or context is unknown, show field names + key-position operators (same as `{ | }`) instead of all operators. - -**Change:** `createCompletionItems` now routes `unknown` and `undefined` cursor contexts to `createKeyPositionCompletions` instead of `createAllCompletions`. The `createAllCompletions` function was removed as it is no longer called. - -**Rationale:** When users clear the input box, they most commonly want to start with a field name. Showing all operators (including value-position ones like `$gt`) was confusing. - -### Step 9: Type-aware operator sorting at value position ✅ - -**Goal:** When the BSON field type is known and the user is at value position, sort operators by type relevance. - -**Changes:** -- `createValuePositionCompletions` now passes `fieldBsonTypes` to `mapOperatorToCompletionItem` for type-aware sorting -- `getOperatorSortPrefix` now distinguishes comparison operators from other universal operators: - - `0_` — type-relevant (operator's `applicableBsonTypes` matches field) - - `1a_` — comparison operators (universal, most commonly used: `$eq`, `$gt`, `$ne`, etc.) - - `1b_` — other universal operators (`$exists`, `$type`, `$mod`, etc.) - - `2_` — non-matching (operator has type restrictions that don't match) - - `3_` — BSON constructors (`ObjectId`, `ISODate`, etc.) - - `4_` — JS globals (`Date`, `Math`, `RegExp`, `Infinity`, etc.) - -### Step 10: Field completion inserts `: $1` snippet ✅ - -**Goal:** Selecting a field name from completions should insert `fieldName: |` with the cursor positioned at the value. - -**Change:** `mapFieldToCompletionItem` now uses snippet insert text `${field.insertText}: $1` with `InsertAsSnippet` rule, instead of plain text. Also changed `label` from a plain string to `{ label: fieldName, description: displayType }` so the type info renders right-aligned (matching operator label style). - -### Step 11: Improved type suggestion labels and documentation ✅ - -**Goal:** Make type suggestions more useful with shorter descriptions, examples in documentation, and practical defaults. - -**Changes:** -- Replaced `▪` (U+25AA) placeholder with `…` (U+2026, horizontal ellipsis) -- Moved examples from inline descriptions to the `documentation` panel -- Shortened descriptions to fit the completion list width (e.g., "pattern match", "range query", "last N days") -- Date suggestions now use dynamic defaults: `twoWeeksAgo()` and `todayISO()` for realistic placeholders -- Added `{ $gt: new Date(Date.now() - …) }` suggestion for relative date queries -- Added concrete regex example `{ $regex: /\.com$/ }` with documentation - -### Step 12: Error diagnostics for unknown function calls ✅ - -**Goal:** Flag unknown function call identifiers as red errors (not just yellow near-miss warnings). - -**Problem:** Previously, `UdddddduaD.now()` and `XyzAbc("123")` produced no diagnostic at all — the Levenshtein distance was > 2 so no near-miss warning fired, but there was also no error path. These calls will always fail at runtime. - -**Fix:** In `documentdbQueryValidator.ts`, the `CallExpression` handler now falls through to an error diagnostic when no near-miss is found: -- Direct calls: `Unknown function 'XyzAbc'. Expected a BSON constructor (e.g., ObjectId, ISODate) or a known global (e.g., Date, Math).` -- Member calls: `Unknown identifier 'UdddddduaD'. Expected a known global (e.g., Date, Math).` - -### Step 13: JS globals in value-position completions ✅ - -**Goal:** Restore `Date`, `Math`, `RegExp`, `Infinity`, `NaN`, and `undefined` as completion items at value position. - -**Problem:** When Step 4 (PR #518) replaced the Monaco JS language with the custom `documentdb-query` language, JavaScript global completions that were previously provided by the built-in Monaco JS language worker disappeared. These globals are valid in queries because `@mongodb-js/shell-bson-parser` supports them in its sandboxed scope. - -**Solution:** Created `src/webviews/documentdbQuery/completions/jsGlobals.ts` — a webview-side module (NOT in `documentdb-constants`) that provides completion items for the JS globals supported by shell-bson-parser's sandbox. These are shown at value position with sort prefix `4_` (after BSON constructors at `3_`). - -**Source of truth:** The supported globals are derived from shell-bson-parser's `scope.js`: -- `SCOPE_CALL/SCOPE_NEW`: `Date` (as constructor) -- `ALLOWED_CLASS_EXPRESSIONS`: `Math` (with whitelisted methods), `Date` (with whitelisted methods) -- `SCOPE_ANY`: `RegExp` (constructor) -- `GLOBALS`: `Infinity`, `NaN`, `undefined` - -**Rationale:** These are NOT added to `documentdb-constants` because they are JavaScript runtime constructs, not DocumentDB API operators. They live in the webview completions module alongside other webview-specific completion logic. - -### Step 14: Completions README ✅ - -**File created:** `src/webviews/documentdbQuery/completions/README.md` - -Documents the completions folder architecture, sorting tiers, and decision matrix for sort prefix assignment. - -### Step 15: Validate `new` expressions for unknown constructors ✅ - -**Goal:** Flag `new Daddddte()` and similar unknown constructors as errors. - -**Problem:** The validator's `CallExpression` handler checks direct calls (`Foo()`) and member calls (`Foo.bar()`), but `new Foo()` is a `NewExpression` in the acorn AST — a different node type with the same `callee` shape. Unknown constructors in `new` expressions were silently ignored. - -**Fix:** Added a `NewExpression` visitor to the acorn walker in `documentdbQueryValidator.ts` that performs the same identifier check: known globals pass, near-misses produce a warning ("Did you mean Date?"), and unknown constructors produce an error. - -### Step 16: Add Date.now() and Math method completions ✅ - -**Goal:** Provide commonly-used JS method completions as individual items. - -**Changes to `jsGlobals.ts`:** -- Added `Date.now()` as a separate completion item alongside the `Date` constructor -- Replaced bare `Math` entry with individual method entries: `Math.floor()`, `Math.ceil()`, `Math.round()`, `Math.min()`, `Math.max()` -- All use sort prefix `4_` (grouped with JS globals) - ---- - -## What is NOT in Scope - -| Item | Reason | -| ------------------------------------------------------- | --------------------------------------------------------- | -| Aggregation pipeline stage-aware completions | Step 8 | -| `SignatureHelpProvider` for operator argument structure | Step 7/8 | -| TS Language Service integration (`.d.ts`) | Future work (P2) | -| Populating `returnType` on `OperatorEntry` | Separate task — not needed for cursor context | -| Deep nesting (3+ levels) context detection | Diminishing returns — fallback to `unknown` is acceptable | diff --git a/docs/plan/future-work.md b/docs/plan/future-work.md deleted file mode 100644 index 4219de901..000000000 --- a/docs/plan/future-work.md +++ /dev/null @@ -1,431 +0,0 @@ -# Future Work - -Items moved outside the scope of the current project (filter/shell/scrapbook) or ideas generated during development. - ---- - -## SchemaAnalyzer Enhancements - -### Computed Probabilities on `getSchema()` - -`SchemaAnalyzer` currently stores `x-occurrence` per field and `x-documentsInspected` on the schema root, allowing probability to be derived as `occurrence / documentsInspected`. However, probabilities are not pre-computed on the schema output. - -**Proposal:** Add an optional `computeProbabilities` flag to `getSchema()` (default: `false`) that, when enabled, computes and includes `x-probability` (a number between 0 and 1) on every field entry in the schema output. - -It should differentiate between "global" and "local" probability. local is within the path, so if a field "name" actually exists, then it's relevant to know when e.g. 90% is a string and 10% are numbers (would suggest an error). better than having a type as "global probability" for such a field. -Similarly it makes sense for fields in a subdocument: address exists in 10% of documents, then address.name exists in 10% of documents globally, but we are more likely to look at the "local" probability, as the information would be "name" exists in 100% of "address". - -```typescript -// Proposed API change: -interface GetSchemaOptions { - /** When true, adds x-probability to every field (occurrence / documentsInspected). Default: false. */ - computeProbabilities?: boolean; -} - -getSchema(options?: GetSchemaOptions): JSONSchema; -``` - -**Use cases:** - -- Schema statistics UI — show users which fields are sparse -- Query optimization hints — warn about queries on highly sparse fields -- LLM prompt enrichment — include field probability in schema definitions for smarter query generation - -**Effort:** Low (~0.5 day). The data (`x-occurrence`, `x-documentsInspected`) is already tracked; this is a traversal + division operation during `getSchema()`. - ---- - -## Field Statistics in Completion Items - -### Problem - -`FieldCompletionData` currently shows only the BSON type and a sparse/not-sparse flag in the completion list (e.g., `"String"` or `"String (sparse)"`). The underlying `SchemaAnalyzer` already computes rich per-field statistics — occurrence counts, type distributions, value ranges — but none of this reaches the completion UI. - -A completion item for `age` could show `Number · 98% · 17–82` instead of just `Number`. This gives users immediate context about the data without running a query. - -### Available Statistics (Already Computed by SchemaAnalyzer) - -The schema's `x-` extension fields provide everything needed: - -| Schema field | What it tells you | Example display | -| ---------------------------------------- | ---------------------------------------- | ------------------------ | -| `x-occurrence` / `x-documentsInspected` | Field presence rate | `98%` or `sparse (12%)` | -| `x-typeOccurrence` (per type in `anyOf`) | Type distribution for polymorphic fields | `80% String, 20% Number` | -| `x-minValue` / `x-maxValue` | Numeric range | `17–82` | -| `x-minLength` / `x-maxLength` | String length range | `len 3–64` | -| `x-minDate` / `x-maxDate` | Date range | `2021-01–2024-12` | -| `x-trueCount` / `x-falseCount` | Boolean distribution | `73% true` | -| `x-minItems` / `x-maxItems` | Array size range | `[2–15] items` | - -### Proposal: Add `description` to `FieldCompletionData` - -The simplest approach: add a pre-compiled `description` string to `FieldCompletionData`, built during `toFieldCompletionItems()` from the schema stats. Monaco renders this in the completion detail/documentation panel. - -```typescript -export interface FieldCompletionData { - // ... existing fields ... - - /** - * Human-readable summary of field statistics from the schema sample. - * Pre-compiled from SchemaAnalyzer's x- extension fields. - * - * Examples: - * "Number · 98% · range 17–82" - * "String · 100% · len 3–64" - * "Boolean · 12% (sparse) · 73% true" - * "80% String, 20% Number · 95%" - */ - description?: string; -} -``` - -This keeps the interface simple — one optional string — while the compilation logic lives in `toFieldCompletionItems()` which already has access to the schema. The completion provider maps `description` to `CompletionItem.documentation` (shown in the detail panel on focus). - -### Alternative: Structured Stats Object - -For consumers that need programmatic access (e.g., type-aware operator ordering in Step 4.5, or a schema statistics UI): - -```typescript -export interface FieldStats { - /** Field presence rate (0–1), e.g. 0.98 means present in 98% of documents */ - presenceRate?: number; - /** Type distribution for polymorphic fields, e.g. { "string": 0.8, "number": 0.2 } */ - typeDistribution?: Record; - /** Numeric value range */ - numericRange?: { min: number; max: number }; - /** String length range */ - stringLengthRange?: { min: number; max: number }; - /** Date range */ - dateRange?: { min: string; max: string }; - /** Boolean true rate (0–1) */ - booleanTrueRate?: number; - /** Array size range */ - arraySizeRange?: { min: number; max: number }; -} - -export interface FieldCompletionData { - // ... existing fields ... - stats?: FieldStats; - description?: string; // compiled from stats for display -} -``` - -Both approaches can coexist — `stats` for programmatic use, `description` for display. The compilation from `stats` to `description` is a simple formatting function. - -### Implementation Path - -1. Extend `FieldEntry` in `schema-analyzer` to carry raw stats (occurrence count, type occurrence counts, value ranges) — the data is already in the schema, just not surfaced on `FieldEntry` -2. Extend `toFieldCompletionItems()` to compile stats into a `description` string -3. Map `description` to `CompletionItem.documentation` in `documentdbQueryCompletionProvider.ts` - -### Effort - -Low (~1 day). The statistics are already computed and stored in the schema. This is a data-threading exercise — expose them on `FieldEntry`, format them in `toFieldCompletionItems()`, and display in the completion item. - ---- - -## MongoDB Constants Package - -When the extension connects to a MongoDB instance (not DocumentDB), the completion providers should offer the full MongoDB operator set. This requires a separate constants package: - -- **Package:** `packages/mongodb-constants/` (or reuse `@mongodb-js/mongodb-constants` under Apache-2.0) -- **Interface:** Exports the same `OperatorEntry[]` interface as `documentdb-constants` -- **Scope:** Full MongoDB 8.0 operator set (superset of DocumentDB) -- The switching logic is already designed — `isDocumentDB(connection)` determines which constants to load - -**Dependency:** Requires `documentdb-constants` to be built first (establishes the shared interface). - ---- - -## Schema Statistics UI - -A dedicated schema visualization panel showing: - -- Field presence probability (occurrence / documents inspected) -- Type distribution per field (polymorphic fields) -- Value range statistics (min/max for numbers, dates, string lengths) -- Array size distributions - -**Potential dependency:** `mongodb-schema` package for reservoir-sampled representative values and unique value detection (features `SchemaAnalyzer` does not provide). See 01-high-level-plan.md "When might mongodb-schema become attractive?" section. - ---- - -## Document Editor Schema Integration (F1) - -Wire `SchemaAnalyzer` output into Monaco's `setDiagnosticsOptions()` for the document view editor. This provides real-time validation and autocomplete when editing individual documents. - -**Status:** Deferred from the main plan (listed as component F1 in 01-high-level-plan.md). - ---- - -## Lazy / On-Demand Operator Data Loading - -**Context:** `documentdb-constants` currently calls `loadOperators()` eagerly at module load time (in `index.ts`), which registers all ~300 operator entries — expression operators, stages, accumulators, window operators, BSON constructors, update operators, etc. — into memory on first import. For completions that are only relevant inside an aggregation pipeline, or only inside an `$update` call, there is no reason to load all categories at extension startup. - -The refactor in PR #513 already lays the groundwork: each data module exports an independent `loadXxx()` function, and `loadOperators()` simply calls all of them. The architecture now supports selective loading without further restructuring. - -### What to revisit - -1. **Audit which categories are needed at launch vs. on-demand.** - Categories needed for the most common use case (filter bar, shell prompt) are a subset: - - Always load at launch: `query*`, `variable`, `bson` (small, universally needed) - - Load on first aggregation: `stage`, `accumulator`, `window`, `expr*` (bulk of the data) - - Load on first update: `update*` - -2. **Introduce category-group load functions** in `index.ts`: - - ```typescript - export function loadCoreCompletions(): void { - /* query, variable, bson */ - } - export function loadAggregationCompletions(): void { - /* stage, accumulator, window, expr* */ - } - export function loadUpdateCompletions(): void { - /* update* */ - } - ``` - - The registry's idempotency guard (Set-based dedup added in PR #513) means calling these multiple times is safe — call them lazily on first need. - -3. **Wire into CompletionItemProviders** (Steps 4–8): each provider calls its relevant load group before returning completions. Because the registry is module-global and dedup-guarded, the load is a no-op on subsequent invocations. - -4. **Measure the impact.** Profile `getAllCompletions()` time and initial `import` time before and after. The bulk is `expressionOperators.ts` (~143 entries) and `queryOperators.ts` (~43 entries). Both are synchronous array allocations, so the gain may be modest — measure first, optimize based on data. - -### Related: other static data in the extension - -Audit other eagerly-loaded static tables elsewhere in the extension for the same pattern: - -- Grammar files (`grammar/`) -- Any `const` arrays populated at module scope in `src/` that are only used in specific views or commands - -**Effort:** Medium (~1 day for the constants package split + provider wiring). Measurement first (~0.5 day). - -**Dependency:** CompletionItemProvider implementation (Steps 4–8) must be at least partially in place before the wiring step is meaningful. - ---- - -## Stage-Aware Aggregation Pipeline Preview - -Compass implements per-stage preview (showing stage output next to the pipeline editor). This is a differentiating feature we could implement: - -- Each stage shows a live preview of documents at that pipeline point -- Schema propagation between stages (what Compass does NOT implement — a competitive advantage) - -**Dependency:** Requires Aggregation `CompletionItemProvider` (Step 8) to be complete first. - ---- - -## TS Language Service for Advanced Completions (P2) - -The analysis documents (17-implementation-recommendations.md) identified Monaco's built-in TypeScript Language Service as a P2 optional enhancement for completions: - -- Load shell API `.d.ts` plus per-collection schema `.d.ts` into Monaco's TS worker via `addExtraLib()` -- Provides hover docs, type inference, and richer completions beyond static constant lists -- Complements (does not replace) `documentdb-constants`-based completions - -**Prerequisite:** Shell API `.d.ts` generation (Step 5 in 01-high-level-plan.md). - ---- - -## Index Advisor Integration with Completions - -The index advisor feature could suggest index-friendly query patterns when users are writing queries. For example: - -- When typing a `$match` stage, suggest fields that have indexes -- Warn when queries use operators that can't leverage existing indexes - -**Dependency:** Requires both `documentdb-constants` and the index advisor to be operational. - ---- - -## Agentic Workflow: Operator Reference Freshness Check - -An automated agentic workflow that periodically re-scrapes the DocumentDB compatibility docs and detects external drift (new operators, changed descriptions, URL restructuring, deprecated operators). - -### Motivation - -The `documentdb-constants` package has CI tests that verify internal consistency — the implementation matches the checked-in dump and overrides. But these tests will never fail on their own because they only compare files within the repo. External drift (DocumentDB adds a new operator, changes a description, restructures docs URLs) is invisible until someone manually re-runs the scraper. - -### Workflow Steps - -``` -1. npm run scrape - → Fetches latest compatibility page + per-operator doc pages - → Regenerates resources/operator-reference-scraped.md - -2. git diff resources/operator-reference-scraped.md - → If no diff: "No upstream changes. Done." → exit - → If diff: continue - -3. npm run evaluate - → Reports: new gaps (operators with empty descriptions), - redundant overrides (override provides description that now - exists upstream), coverage stats - -4. npm run generate - → Regenerates .ts files from updated dump + existing overrides - -5. npm test - → Runs all CI tests against the updated code - → Failures indicate drift that needs attention: - - New operator in dump but missing from generated code - - Description changed upstream (override may mask or conflict) - - Doc URL changed (link verification test catches this) - - Operator removed upstream (no-extras test catches this) - -6. If diff or test failures exist: - → Open a PR with: - - Updated operator-reference-scraped.md - - Updated generated .ts files (if generate succeeded) - - Summary of what changed (from git diff) - - List of test failures (if any) - - Evaluation report (gaps, redundant overrides) - → Assign for human review - -7. Human reviews: - → New operators: verify descriptions, add overrides if needed - → Changed descriptions: decide whether to keep override or adopt upstream - → Removed operators: confirm deprecation, update not-listed section - → URL changes: verify links still resolve -``` - -### Schedule - -Weekly or monthly. DocumentDB compatibility updates are typically tied to major/minor version releases (a few times per year), so monthly is sufficient. Weekly provides earlier detection. - -### Agent Prompt (Draft) - -``` -You are maintaining the documentdb-constants package in vscode-documentdb. - -1. Run: cd packages/documentdb-constants && npm run scrape -2. Check: git diff resources/operator-reference-scraped.md -3. If no changes: report "No upstream drift detected" and stop. -4. If changes: run npm run evaluate, then npm run generate, then npm test. -5. If tests pass: commit all changes and open a PR titled - "chore: update documentdb-constants operator reference" - with a summary of what changed. -6. If tests fail: open a PR anyway with the failures noted, - flagged for human review. -``` - -### Prerequisites - -- The scraper (`scripts/scrape-operator-docs.ts`) must remain functional — it depends on the structure of the upstream docs repo -- GitHub Actions or equivalent CI runner with network access for the scraper -- Agent must have permission to create branches and open PRs - -### Existing Infrastructure - -| Component | Status | Location | -| -------------------------------- | ------------ | ------------------------------------------- | -| Scraper | ✅ Built | `scripts/scrape-operator-docs.ts` | -| Override system | ✅ Built | `resources/operator-reference-overrides.md` | -| Generator | ✅ Built | `scripts/generate-from-reference.ts` | -| Evaluator | ✅ Built | `scripts/evaluate-overrides.ts` | -| CI tests (internal consistency) | ✅ Built | `src/operatorReference.test.ts` | -| CI tests (merged dump+overrides) | ✅ Built | `src/operatorReference.test.ts` | -| GitHub Actions workflow | ❌ Not built | Needs `.github/workflows/` YAML | - ---- - -## Additional Monaco Language Feature Providers - -### Context - -Beyond `CompletionItemProvider` and `HoverProvider` (implemented in Step 4), Monaco exposes many more language feature providers. The table below catalogues all of them with a per-editor-type usefulness rating. - -### Provider Reference Table - -| Provider | Query Editors (filter/project/sort) | Aggregation Pipeline | Scrapbook | Notes | -|---|---|---|---|---| -| **CompletionItemProvider** | **Implemented** | Planned (Step 8) | Planned (Step 7) | Static operators + dynamic fields | -| **HoverProvider** | **Implemented** | Planned | Planned | Operator docs on hover | -| **SignatureHelpProvider** | **High** | **High** | **High** | Parameter hints for BSON constructors, e.g. `ObjectId(│hex│)` | -| **CodeActionProvider** | **High** | **High** | Medium | Quick-fix for near-miss warnings → auto-replace typo | -| **InlayHintsProvider** | **High** | Medium | Low | Inline type annotations, e.g. `{ age: ▸int 25 }` | -| **DocumentFormattingEditProvider** | Medium | **High** | **High** | Auto-format/prettify; low value for single-line filters | -| **FoldingRangeProvider** | Low | **High** | **High** | Fold pipeline stages, nested objects | -| **DocumentSymbolProvider** | Low | **High** | **High** | Outline / breadcrumbs — pipeline stages as symbols | -| **CodeLensProvider** | Medium | Medium | **High** | "Run" / "Run Stage" above code blocks | -| **LinkProvider** | Medium | Medium | Low | Clickable operator names → docs (currently shown in hover only) | -| **RenameProvider** | Low | Medium | **High** | Rename field references across pipeline or script | -| **DocumentRangeFormattingEditProvider** | Low | Medium | Medium | Format selection only | -| **OnTypeFormattingEditProvider** | Medium | Medium | Medium | Auto-indent on `{`, `}`, `,` | -| **DocumentSemanticTokensProvider** | Medium | Medium | Medium | Richer coloring: operators vs fields vs constructors | -| **InlineCompletionProvider** | Low | Medium | Medium | Ghost-text suggestions (Copilot-style); needs AI backend | -| **DocumentHighlightProvider** | Low | Low | Medium | Highlight all occurrences of a symbol | -| **DefinitionProvider** | Low | Low | Medium | Go to definition (only meaningful with `let`/`const`) | -| **ReferenceProvider** | Low | Low | Medium | Find all references | -| **LinkedEditingRangeProvider** | Low | Low | Low | Simultaneous edit of matching tags; not applicable | -| **DeclarationProvider** | Low | Low | Low | Mostly redundant with DefinitionProvider | -| **ColorProvider** | Low | Low | Low | Color picker — not applicable | - -### Recommended Next Providers - -#### 1. SignatureHelpProvider - -**Usefulness:** High across all editor types. - -Shows parameter hints when typing inside BSON constructor or function calls — e.g., `ObjectId(|hex string|)`, `NumberDecimal(|value|)`, `ISODate(|ISO 8601 string|)`. - -The metadata is already available: `OperatorEntry.snippet` defines the parameter structure with tab stops (`${1:hex}`). The provider parses the snippet definition to extract parameter names and types, then shows them as the user types between parentheses. - -**Effort:** Low (~0.5 day). Trigger characters: `(`, `,`. Parse the matching `OperatorEntry.snippet` for the current function name. - -#### 2. CodeActionProvider - -**Usefulness:** High for query editors and aggregation pipelines. - -Provides quick-fix actions for the near-miss warnings already produced by the `acorn` validator. When the validator emits "Did you mean 'Date'?" for `Daate.now()`, the CodeActionProvider offers a one-click fix that replaces `Daate` with `Date`. - -This pairs directly with the existing `Diagnostic` infrastructure — each warning diagnostic becomes a `CodeAction` with a `WorkspaceEdit` that performs the replacement. - -**Effort:** Low (~0.5 day). The validator already computes the exact offset range and the suggested replacement. The CodeActionProvider maps diagnostics to edits. - -#### 3. FoldingRangeProvider - -**Usefulness:** High for aggregation pipelines and scrapbook, low for single-line query editors. - -Enables code folding for nested objects, arrays, and pipeline stages. In a multi-stage aggregation pipeline, each stage can be collapsed independently. In scrapbook scripts, function bodies and complex expressions can be folded. - -**Effort:** Low (~0.5 day). Can be implemented with simple brace/bracket matching or by reusing the `acorn` AST to identify foldable regions. - ---- - -## Completion Provider Enhancements - -### Dot-triggered method completions for JS globals - -When the user types `Date.` or `Math.`, trigger method-specific completions dynamically instead of showing the full completion list. This requires detecting the word before the `.` trigger character and returning method completions for that specific object. - -**Approach:** In the completion provider, when charBefore is `.` and the word before the dot is a known JS global (`Date`, `Math`), return whitelisted methods from shell-bson-parser's `ALLOWED_CLASS_EXPRESSIONS`. - -**Effort:** Medium (~1 day). Requires changes to cursor context detection and a new method resolution path in the completion provider. - -### Projection/sort value suggestions - -Project editors need `1` / `0` / `true` / `false` as value-position suggestions (include/exclude fields). Sort editors need `1` / `-1` (ascending/descending). Currently no type suggestions are shown at value position in these editors because the BSON field type is not relevant for projection semantics. - -**Approach:** Detect `EditorType.Project` or `EditorType.Sort` in `createValuePositionCompletions` and return editor-specific value suggestions instead of BSON-type-based ones. - -**Effort:** Low (~0.5 day). - -### Method-level validation for JS globals - -The validator currently checks object-level identifiers (`Date` → known, `Daate` → warning) but does not validate method names (`Date.nodw()` → no diagnostic). Adding method-level validation would require maintaining a whitelist of methods per global class, matching shell-bson-parser's `ALLOWED_CLASS_EXPRESSIONS`. - -**Effort:** Low (~0.5 day). The whitelist already exists in shell-bson-parser's scope.js. - -### Field name validation against schema - -The validator intentionally does not flag unknown field names (`{ nonExistentField: 1 }` produces no diagnostic). With the completion store holding known fields per session, field names could be validated against the schema with severity `'info'` (hint) — "Field 'nonExistentField' not found in the sampled schema." - -**Effort:** Medium (~1 day). Requires wiring the completion store into the validator, which currently has no Monaco or session dependencies. - -### Deep nesting context detection (3+ levels) - -The cursor context heuristic scans backward through 1-2 levels of nesting. At 3+ levels (e.g., `{ $and: [{ age: { $gt: { $numberLong: | } } }] }`), it may fall back to `unknown`. An AST-based approach (dummy completion insertion) could improve accuracy for deeply nested positions. - -**Effort:** High (~2 days). The dummy completion strategy has fundamental ambiguity issues (see 4.5 plan "Why Not Use a Dummy Completion Strategy"). From 3c023297f8b9c9aa183e4c22c2bbfaebd37da5f4 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Mar 2026 13:29:52 +0000 Subject: [PATCH 087/128] docs: add git safety rules to copilot instructions Never use git add -f to override .gitignore. Files in docs/plan/ and docs/analysis/ are local planning documents excluded from the repo. --- .github/copilot-instructions.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 6a7852567..a5b2b97b7 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -32,6 +32,12 @@ Before finishing work on a PR, agents **must** run the following steps in order: > ⚠️ **An agent must not finish or terminate until all three steps above have been run and pass successfully.** Skipping these steps leads to CI failures. +## Git Safety + +- **Never use `git add -f`** to force-add files. If `git add` refuses a file, it is likely in `.gitignore` for a reason (e.g., `docs/plan/`, `docs/analysis/`, build outputs). Do NOT override this with `-f`. +- When `git add` warns that a path is ignored, **stop and inform the user** instead of force-adding. +- Files in `docs/plan/` and `docs/analysis/` are **local planning documents** that must not be committed to the repository. + ## Project Structure | Folder | Purpose | From 85c490fc7d96080fe0626492d429bfa1bda44822 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Tue, 17 Mar 2026 14:59:44 +0000 Subject: [PATCH 088/128] fix: lint error and minor cleanup - Remove unnecessary escape in template literal (no-useless-escape) - Formatter-applied changes to imports and whitespace --- src/webviews/documentdbQuery/completions/index.ts | 7 ++++--- src/webviews/documentdbQuery/completions/jsGlobals.ts | 6 ++++-- .../documentdbQuery/completions/mapCompletionItems.ts | 2 +- .../documentdbQuery/completions/typeSuggestions.ts | 3 +-- .../documentdbQuery/documentdbQueryValidator.test.ts | 4 +++- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/webviews/documentdbQuery/completions/index.ts b/src/webviews/documentdbQuery/completions/index.ts index 05a9a4737..c9fa6db8c 100644 --- a/src/webviews/documentdbQuery/completions/index.ts +++ b/src/webviews/documentdbQuery/completions/index.ts @@ -16,8 +16,10 @@ export { INFO_INDICATOR, LABEL_PLACEHOLDER } from './completionKnowledge'; export { + KEY_POSITION_OPERATORS, createCompletionItems, - getMetaTagsForEditorType, KEY_POSITION_OPERATORS, type CreateCompletionItemsParams + getMetaTagsForEditorType, + type CreateCompletionItemsParams, } from './createCompletionItems'; export { createJsGlobalCompletionItems } from './jsGlobals'; export { @@ -25,8 +27,7 @@ export { getCompletionKindForMeta, getOperatorSortPrefix, mapFieldToCompletionItem, - mapOperatorToCompletionItem + mapOperatorToCompletionItem, } from './mapCompletionItems'; export { escapeSnippetDollars, stripOuterBraces } from './snippetUtils'; export { createTypeSuggestions } from './typeSuggestions'; - diff --git a/src/webviews/documentdbQuery/completions/jsGlobals.ts b/src/webviews/documentdbQuery/completions/jsGlobals.ts index 93302ff00..483485f54 100644 --- a/src/webviews/documentdbQuery/completions/jsGlobals.ts +++ b/src/webviews/documentdbQuery/completions/jsGlobals.ts @@ -72,13 +72,15 @@ const JS_GLOBALS: readonly JsGlobalDef[] = [ label: 'Date.now()', snippet: 'Date.now()', description: 'JS global', - documentation: 'Returns milliseconds since Unix epoch (Jan 1, 1970).\n\nUseful for relative date queries:\n```\n{ $gt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) }\n```', + documentation: + 'Returns milliseconds since Unix epoch (Jan 1, 1970).\n\nUseful for relative date queries:\n```\n{ $gt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) }\n```', }, { label: 'RegExp', snippet: 'RegExp("${1:pattern}")', description: 'JS global', - documentation: 'JavaScript RegExp constructor.\n\nExample: `RegExp("^test")`\n\nPrefer regex literals: `/^test/`', + documentation: + 'JavaScript RegExp constructor.\n\nExample: `RegExp("^test")`\n\nPrefer regex literals: `/^test/`', }, // -- Math methods -- diff --git a/src/webviews/documentdbQuery/completions/mapCompletionItems.ts b/src/webviews/documentdbQuery/completions/mapCompletionItems.ts index 43305c836..940e7eab8 100644 --- a/src/webviews/documentdbQuery/completions/mapCompletionItems.ts +++ b/src/webviews/documentdbQuery/completions/mapCompletionItems.ts @@ -141,7 +141,7 @@ export function mapFieldToCompletionItem( description: `${field.displayType}${sparseIndicator}`, }, kind: monaco.languages.CompletionItemKind.Field, - insertText: `${field.insertText}: \$1`, + insertText: `${field.insertText}: $1`, insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet, sortText: `0_${field.fieldName}`, range, diff --git a/src/webviews/documentdbQuery/completions/typeSuggestions.ts b/src/webviews/documentdbQuery/completions/typeSuggestions.ts index 575e0f45b..7a9e62d37 100644 --- a/src/webviews/documentdbQuery/completions/typeSuggestions.ts +++ b/src/webviews/documentdbQuery/completions/typeSuggestions.ts @@ -88,8 +88,7 @@ const TYPE_SUGGESTIONS: Record = { insertText: '{ $regex: /${1:\\.com$}/ }', isSnippet: true, description: `ends with .com - pattern match`, - documentation: - 'Example pattern match for: ends with `.com`:\n```\n{ $regex: /\\.com$/ }\n```', + documentation: 'Example pattern match for: ends with `.com`:\n```\n{ $regex: /\\.com$/ }\n```', }, { label: '""', diff --git a/src/webviews/documentdbQuery/documentdbQueryValidator.test.ts b/src/webviews/documentdbQuery/documentdbQueryValidator.test.ts index 969c80af0..40f807e10 100644 --- a/src/webviews/documentdbQuery/documentdbQueryValidator.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryValidator.test.ts @@ -144,7 +144,9 @@ describe('documentdbQueryValidator', () => { }); test('new Daddddte() produces error for unknown constructor', () => { - const diagnostics = validateExpression('{ date: { $gt: new Daddddte(Date.now() - 14 * 24 * 60 * 60 * 1000) } }'); + const diagnostics = validateExpression( + '{ date: { $gt: new Daddddte(Date.now() - 14 * 24 * 60 * 60 * 1000) } }', + ); const errors = diagnostics.filter((d) => d.severity === 'error'); expect(errors).toHaveLength(1); expect(errors[0].message).toContain("Unknown constructor 'Daddddte'"); From 49f2711555c682d97858f90eea02e821143b56ad Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Wed, 18 Mar 2026 09:12:45 +0000 Subject: [PATCH 089/128] docs: add known edge case comment for string-literal scanning in cursorContext --- src/webviews/documentdbQuery/cursorContext.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/webviews/documentdbQuery/cursorContext.ts b/src/webviews/documentdbQuery/cursorContext.ts index d6c06f2c5..606db0f39 100644 --- a/src/webviews/documentdbQuery/cursorContext.ts +++ b/src/webviews/documentdbQuery/cursorContext.ts @@ -88,6 +88,14 @@ interface ScanResult { index: number; } +// Known edge case: the backward scanner does not track whether characters +// are inside quoted strings. A structural character that appears within a +// string literal is still treated as structural. For example, in +// { msg: "{", | } +// the `{` inside the string `"{"` would be found before the real opening +// brace, causing a misclassification. This is acceptable for a completion +// heuristic where rare edge cases degrade gracefully rather than break. + /** * Scans backward from the cursor, skipping whitespace and identifier characters * (letters, digits, `_`, `$`, `.`, quotes), to find the nearest structural character. From afbaacb077b2e5a704205d06d3a0a4ce3141de93 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Wed, 18 Mar 2026 09:17:16 +0000 Subject: [PATCH 090/128] fix: normalize BSON type 'int' to 'int32' across tests and constants Tests were using 'int' but the schema analyzer produces 'int32' (BSONTypes.Int32). Also fixed applicableBsonTypes in documentdb-constants bitwise operators to use 'int32' to match, which was a real production mismatch. --- .../src/queryOperators.ts | 8 ++-- .../documentdbQuery/completionStore.test.ts | 2 +- .../completions/typeSuggestions.ts | 2 +- .../documentdbQuery/cursorContext.test.ts | 12 +++--- .../documentdbQueryCompletionProvider.test.ts | 39 +++++++++---------- 5 files changed, 30 insertions(+), 33 deletions(-) diff --git a/packages/documentdb-constants/src/queryOperators.ts b/packages/documentdb-constants/src/queryOperators.ts index a673e0fb2..4afc3bdd6 100644 --- a/packages/documentdb-constants/src/queryOperators.ts +++ b/packages/documentdb-constants/src/queryOperators.ts @@ -341,7 +341,7 @@ const bitwiseQueryOperators: readonly OperatorEntry[] = [ 'The $bitsAllClear operator is used to match documents where all the bit positions specified in a bitmask are clear.', snippet: '{ $bitsAllClear: ${1:bitmask} }', link: getDocLink('$bitsAllClear', META_QUERY_BITWISE), - applicableBsonTypes: ['int', 'long'], + applicableBsonTypes: ['int32', 'long'], }, { value: '$bitsAllSet', @@ -349,7 +349,7 @@ const bitwiseQueryOperators: readonly OperatorEntry[] = [ description: 'The bitsAllSet command is used to match documents where all the specified bit positions are set.', snippet: '{ $bitsAllSet: ${1:bitmask} }', link: getDocLink('$bitsAllSet', META_QUERY_BITWISE), - applicableBsonTypes: ['int', 'long'], + applicableBsonTypes: ['int32', 'long'], }, { value: '$bitsAnyClear', @@ -358,7 +358,7 @@ const bitwiseQueryOperators: readonly OperatorEntry[] = [ 'The $bitsAnyClear operator matches documents where any of the specified bit positions in a bitmask are clear.', snippet: '{ $bitsAnyClear: ${1:bitmask} }', link: getDocLink('$bitsAnyClear', META_QUERY_BITWISE), - applicableBsonTypes: ['int', 'long'], + applicableBsonTypes: ['int32', 'long'], }, { value: '$bitsAnySet', @@ -367,7 +367,7 @@ const bitwiseQueryOperators: readonly OperatorEntry[] = [ 'The $bitsAnySet operator returns documents where any of the specified bit positions are set to 1.', snippet: '{ $bitsAnySet: ${1:bitmask} }', link: getDocLink('$bitsAnySet', META_QUERY_BITWISE), - applicableBsonTypes: ['int', 'long'], + applicableBsonTypes: ['int32', 'long'], }, ]; diff --git a/src/webviews/documentdbQuery/completionStore.test.ts b/src/webviews/documentdbQuery/completionStore.test.ts index b674116ac..fde71ed1b 100644 --- a/src/webviews/documentdbQuery/completionStore.test.ts +++ b/src/webviews/documentdbQuery/completionStore.test.ts @@ -109,7 +109,7 @@ describe('completionStore', () => { { fieldName: 'b', displayType: 'Number', - bsonType: 'int', + bsonType: 'int32', isSparse: true, insertText: 'b', referenceText: '$b', diff --git a/src/webviews/documentdbQuery/completions/typeSuggestions.ts b/src/webviews/documentdbQuery/completions/typeSuggestions.ts index 7a9e62d37..391e3094f 100644 --- a/src/webviews/documentdbQuery/completions/typeSuggestions.ts +++ b/src/webviews/documentdbQuery/completions/typeSuggestions.ts @@ -205,7 +205,7 @@ function todayISO(): string { * * Returns an empty array when the BSON type is unknown or has no specific suggestions. * - * @param fieldBsonType - BSON type string from the schema (e.g., 'int', 'string', 'bool') + * @param fieldBsonType - BSON type string from the schema (e.g., 'int32', 'string', 'boolean') * @param range - the insertion range * @param monaco - the Monaco API */ diff --git a/src/webviews/documentdbQuery/cursorContext.test.ts b/src/webviews/documentdbQuery/cursorContext.test.ts index 03f0d0ca7..4ee6f57fe 100644 --- a/src/webviews/documentdbQuery/cursorContext.test.ts +++ b/src/webviews/documentdbQuery/cursorContext.test.ts @@ -65,9 +65,9 @@ describe('detectCursorContext', () => { }); it('includes bsonType when fieldLookup provides it', () => { - const lookup: FieldTypeLookup = (name) => (name === 'age' ? 'int' : undefined); + const lookup: FieldTypeLookup = (name) => (name === 'age' ? 'int32' : undefined); const result = detect('{ age: | }', lookup); - expect(result).toEqual({ position: 'value', fieldName: 'age', fieldBsonType: 'int' }); + expect(result).toEqual({ position: 'value', fieldName: 'age', fieldBsonType: 'int32' }); }); it('omits bsonType when fieldLookup returns undefined', () => { @@ -84,9 +84,9 @@ describe('detectCursorContext', () => { }); it('detects operator position with bsonType', () => { - const lookup: FieldTypeLookup = (name) => (name === 'age' ? 'int' : undefined); + const lookup: FieldTypeLookup = (name) => (name === 'age' ? 'int32' : undefined); const result = detect('{ age: { | } }', lookup); - expect(result).toEqual({ position: 'operator', fieldName: 'age', fieldBsonType: 'int' }); + expect(result).toEqual({ position: 'operator', fieldName: 'age', fieldBsonType: 'int32' }); }); it('detects operator position after comma in nested object', () => { @@ -229,9 +229,9 @@ describe('detectCursorContext', () => { }); it('handles fieldLookup with incomplete input', () => { - const lookup: FieldTypeLookup = (name) => (name === 'age' ? 'int' : undefined); + const lookup: FieldTypeLookup = (name) => (name === 'age' ? 'int32' : undefined); const result = detect('{ age: { $|', lookup); - expect(result).toEqual({ position: 'operator', fieldName: 'age', fieldBsonType: 'int' }); + expect(result).toEqual({ position: 'operator', fieldName: 'age', fieldBsonType: 'int32' }); }); it('{ $or: [ { name: "x" }, {| — second element in $or array', () => { diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index 93c323d73..ece576684 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -384,7 +384,7 @@ describe('documentdbQueryCompletionProvider', () => { const field = { fieldName: 'age', displayType: 'Number', - bsonType: 'int', + bsonType: 'int32', isSparse: false, insertText: 'age', referenceText: '$age', @@ -453,7 +453,7 @@ describe('documentdbQueryCompletionProvider', () => { { fieldName: 'age', displayType: 'Number', - bsonType: 'int', + bsonType: 'int32', isSparse: false, insertText: 'age', referenceText: '$age', @@ -583,7 +583,7 @@ describe('documentdbQueryCompletionProvider', () => { description: 'Regex match', applicableBsonTypes: ['string'], }; - expect(getOperatorSortPrefix(entry, ['int'])).toBe('2_'); + expect(getOperatorSortPrefix(entry, ['int32'])).toBe('2_'); }); test('handles polymorphic fields (multiple bsonTypes)', () => { @@ -593,8 +593,8 @@ describe('documentdbQueryCompletionProvider', () => { description: 'Regex match', applicableBsonTypes: ['string'], }; - // Field is sometimes string, sometimes int — $regex should match - expect(getOperatorSortPrefix(regexEntry, ['int', 'string'])).toBe('0_'); + // Field is sometimes string, sometimes int32 — $regex should match + expect(getOperatorSortPrefix(regexEntry, ['int32', 'string'])).toBe('0_'); }); test('returns "2_" when operator types and field types have no intersection', () => { @@ -604,7 +604,7 @@ describe('documentdbQueryCompletionProvider', () => { description: 'Array size', applicableBsonTypes: ['array'], }; - expect(getOperatorSortPrefix(sizeEntry, ['string', 'int'])).toBe('2_'); + expect(getOperatorSortPrefix(sizeEntry, ['string', 'int32'])).toBe('2_'); }); }); @@ -637,7 +637,7 @@ describe('documentdbQueryCompletionProvider', () => { meta: 'query:comparison', description: 'Equals', }; - const item = mapOperatorToCompletionItem(entry, testRange, mockMonaco, ['int']); + const item = mapOperatorToCompletionItem(entry, testRange, mockMonaco, ['int32']); expect(item.sortText).toBe('1a_$eq'); }); @@ -659,7 +659,7 @@ describe('documentdbQueryCompletionProvider', () => { description: 'Regex match', applicableBsonTypes: ['string'], }; - const item = mapOperatorToCompletionItem(entry, testRange, mockMonaco, ['int']); + const item = mapOperatorToCompletionItem(entry, testRange, mockMonaco, ['int32']); expect(item.sortText).toBe('2_$regex'); }); }); @@ -711,7 +711,7 @@ describe('documentdbQueryCompletionProvider', () => { expect(eqItem?.sortText).toBe('1a_$eq'); }); - test('with fieldBsonTypes=["int"] at operator position, $regex gets "2_" (demoted, still present)', () => { + test('with fieldBsonTypes=["int32"] at operator position, $regex gets "2_" (demoted, still present)', () => { const context: CursorContext = { position: 'operator', fieldName: 'x' }; const items = createCompletionItems({ editorType: EditorType.Filter, @@ -719,7 +719,7 @@ describe('documentdbQueryCompletionProvider', () => { range: testRange, isDollarPrefix: false, monaco: mockMonaco, - fieldBsonTypes: ['int'], + fieldBsonTypes: ['int32'], cursorContext: context, }); @@ -751,7 +751,7 @@ describe('documentdbQueryCompletionProvider', () => { range: testRange, isDollarPrefix: false, monaco: mockMonaco, - fieldBsonTypes: ['int'], + fieldBsonTypes: ['int32'], cursorContext: { position: 'operator', fieldName: 'x' }, }); @@ -765,7 +765,7 @@ describe('documentdbQueryCompletionProvider', () => { { fieldName: 'age', displayType: 'Number', - bsonType: 'int', + bsonType: 'int32', isSparse: false, insertText: 'age', referenceText: '$age', @@ -779,7 +779,7 @@ describe('documentdbQueryCompletionProvider', () => { range: testRange, isDollarPrefix: false, monaco: mockMonaco, - fieldBsonTypes: ['int'], + fieldBsonTypes: ['int32'], cursorContext: { position: 'key', depth: 1 }, }); @@ -948,7 +948,7 @@ describe('documentdbQueryCompletionProvider', () => { { fieldName: 'age', displayType: 'Number', - bsonType: 'int', + bsonType: 'int32', isSparse: false, insertText: 'age', referenceText: '$age', @@ -1178,13 +1178,10 @@ describe('documentdbQueryCompletionProvider', () => { }); test('applies type-aware sorting when fieldBsonType is available', () => { - // Uses 'int' (documentdb-constants naming) rather than 'int32' (BSONTypes) - // because applicableBsonTypes in operators uses the constants naming. - // TODO: normalize type names between schema-analyzer and documentdb-constants const typedContext: CursorContext = { position: 'operator', fieldName: 'age', - fieldBsonType: 'int', + fieldBsonType: 'int32', }; const items = createCompletionItems({ @@ -1196,11 +1193,11 @@ describe('documentdbQueryCompletionProvider', () => { cursorContext: typedContext, }); - // $regex has applicableBsonTypes=['string'], doesn't match 'int' → demoted + // $regex has applicableBsonTypes=['string'], doesn't match 'int32' → demoted const regexItem = items.find((i) => getLabelText(i.label) === '$regex'); expect(regexItem?.sortText).toBe('2_$regex'); - // $bitsAllSet has applicableBsonTypes containing 'int' → promoted + // $bitsAllSet has applicableBsonTypes containing 'int32' → promoted const bitsItem = items.find((i) => getLabelText(i.label) === '$bitsAllSet'); expect(bitsItem?.sortText).toBe('0_$bitsAllSet'); @@ -1240,7 +1237,7 @@ describe('documentdbQueryCompletionProvider', () => { { fieldName: 'age', displayType: 'Number', - bsonType: 'int', + bsonType: 'int32', isSparse: false, insertText: 'age', referenceText: '$age', From f72ba46088801baee7433a58bb24213c0e5015e8 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Wed, 18 Mar 2026 09:20:10 +0000 Subject: [PATCH 091/128] feat: show all completions when cursor context is unknown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When cursorContext is undefined or 'unknown', show the full set of completions (fields, all operators, BSON constructors, JS globals) instead of only key-position items. This is a better UX fallback — when context can't be determined, the user is better served by seeing everything available. --- .../completions/createCompletionItems.ts | 47 ++++++++++++++++--- .../documentdbQueryCompletionProvider.test.ts | 33 +++++++------ 2 files changed, 56 insertions(+), 24 deletions(-) diff --git a/src/webviews/documentdbQuery/completions/createCompletionItems.ts b/src/webviews/documentdbQuery/completions/createCompletionItems.ts index 94dd9bb41..18a8e5ca5 100644 --- a/src/webviews/documentdbQuery/completions/createCompletionItems.ts +++ b/src/webviews/documentdbQuery/completions/createCompletionItems.ts @@ -48,7 +48,8 @@ export interface CreateCompletionItemsParams { /** * Optional cursor context from the heuristic cursor position detector. * When provided, completions are filtered based on the semantic position - * of the cursor. When undefined, falls back to showing all completions. + * of the cursor. When undefined, falls back to showing all completions + * (fields, operators, BSON constructors, and JS globals). */ cursorContext?: CursorContext; } @@ -84,16 +85,16 @@ export function getMetaTagsForEditorType(editorType: EditorType | undefined): re * - **value**: type suggestions + operators (with braces) + BSON constructors * - **operator**: operators (without braces) with type-aware sorting * - **array-element**: same as key position - * - **unknown**: all completions (backward compatible fallback) + * - **unknown / undefined**: all completions — fields, all operators, BSON + * constructors, and JS globals (backward-compatible fallback) */ export function createCompletionItems(params: CreateCompletionItemsParams): monacoEditor.languages.CompletionItem[] { const { editorType, sessionId, range, monaco, fieldBsonTypes, cursorContext } = params; if (!cursorContext || cursorContext.position === 'unknown') { - // When context is unknown (e.g., empty input, no braces), show the same - // completions as key position: field names first, then key-position operators. - // This is the common scenario when users clear the input box and start fresh. - return createKeyPositionCompletions(editorType, sessionId, range, monaco); + // When context is unknown (e.g., empty input, no braces), show all + // completions so the user can discover what's available. + return createAllCompletions(editorType, sessionId, range, monaco); } switch (cursorContext.position) { @@ -112,12 +113,44 @@ export function createCompletionItems(params: CreateCompletionItemsParams): mona } default: - return createKeyPositionCompletions(editorType, sessionId, range, monaco); + return createAllCompletions(editorType, sessionId, range, monaco); } } // ---------- Context-specific completion builders ---------- +/** + * All completions — used when cursor context is unknown or undefined. + * Shows fields, all operators, BSON constructors, and JS globals. + */ +function createAllCompletions( + editorType: EditorType | undefined, + sessionId: string | undefined, + range: monacoEditor.IRange, + monaco: typeof monacoEditor, +): monacoEditor.languages.CompletionItem[] { + const metaTags = getMetaTagsForEditorType(editorType); + const allEntries = getFilteredCompletions({ meta: [...metaTags] }); + + const fieldItems = getFieldCompletionItems(sessionId, range, monaco); + + const operatorItems = allEntries + .filter((e) => e.meta !== 'bson' && e.meta !== 'variable') + .map((entry) => mapOperatorToCompletionItem(entry, range, monaco)); + + const bsonItems = allEntries + .filter((e) => e.meta === 'bson') + .map((entry) => { + const item = mapOperatorToCompletionItem(entry, range, monaco); + item.sortText = `3_${entry.value}`; + return item; + }); + + const jsGlobals = createJsGlobalCompletionItems(range, monaco); + + return [...fieldItems, ...operatorItems, ...bsonItems, ...jsGlobals]; +} + function createKeyPositionCompletions( editorType: EditorType | undefined, sessionId: string | undefined, diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index ece576684..8acecd66a 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -498,13 +498,9 @@ describe('documentdbQueryCompletionProvider', () => { const fieldItem = items.find((i) => getLabelText(i.label) === 'name'); expect(fieldItem?.sortText).toBe('0_name'); - - // Key-position operators get "1_" prefix (below fields) - const andItem = items.find((i) => getLabelText(i.label) === '$and'); - expect(andItem?.sortText).toBe('1_$and'); }); - test('empty store returns only key-position operator completions', () => { + test('empty store returns all operator completions', () => { const items = createCompletionItems({ editorType: EditorType.Filter, sessionId: 'nonexistent-session', @@ -513,14 +509,14 @@ describe('documentdbQueryCompletionProvider', () => { monaco: mockMonaco, }); - // Without cursorContext, falls back to key-position completions + // Without cursorContext, falls back to all completions const labels = items.map((i) => getLabelText(i.label)); expect(labels).toContain('$and'); expect(labels).toContain('$or'); - expect(labels).not.toContain('$gt'); + expect(labels).toContain('$gt'); }); - test('undefined sessionId returns only key-position operator completions', () => { + test('undefined sessionId returns all operator completions', () => { const items = createCompletionItems({ editorType: EditorType.Filter, sessionId: undefined, @@ -529,11 +525,11 @@ describe('documentdbQueryCompletionProvider', () => { monaco: mockMonaco, }); - // Without cursorContext, falls back to key-position completions + // Without cursorContext, falls back to all completions const labels = items.map((i) => getLabelText(i.label)); expect(labels).toContain('$and'); expect(labels).toContain('$or'); - expect(labels).not.toContain('$gt'); + expect(labels).toContain('$gt'); }); }); @@ -1271,7 +1267,7 @@ describe('documentdbQueryCompletionProvider', () => { describe('unknown position', () => { const unknownContext: CursorContext = { position: 'unknown' }; - test('falls back to key-position completions', () => { + test('falls back to all completions', () => { const itemsWithContext = createCompletionItems({ editorType: EditorType.Filter, sessionId: undefined, @@ -1289,17 +1285,20 @@ describe('documentdbQueryCompletionProvider', () => { monaco: mockMonaco, }); - // Both should produce the same key-position completions + // Both should produce the same all-completions list expect(itemsWithContext).toHaveLength(itemsWithoutContext.length); const labels = itemsWithContext.map((i) => getLabelText(i.label)); + // All completions include key-position operators expect(labels).toContain('$and'); expect(labels).toContain('$or'); - expect(labels).not.toContain('$gt'); + // Also include value-position operators and BSON constructors + expect(labels).toContain('$gt'); + expect(labels).toContain('ObjectId'); }); }); describe('no cursorContext (undefined)', () => { - test('falls back to key-position completions (fields + key operators)', () => { + test('falls back to all completions (fields + operators + BSON + JS globals)', () => { const items = createCompletionItems({ editorType: EditorType.Filter, sessionId: undefined, @@ -1309,12 +1308,12 @@ describe('documentdbQueryCompletionProvider', () => { cursorContext: undefined, }); - // Without cursorContext, shows key-position completions (fields + key operators) + // Without cursorContext, shows all completions const labels = items.map((i) => getLabelText(i.label)); expect(labels).toContain('$and'); expect(labels).toContain('$or'); - expect(labels).not.toContain('$gt'); - expect(labels).not.toContain('ObjectId'); + expect(labels).toContain('$gt'); + expect(labels).toContain('ObjectId'); }); }); }); From 16de10eb41fec794c6158265971b2d430520b266 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Wed, 18 Mar 2026 09:20:56 +0000 Subject: [PATCH 092/128] cleanup: remove development console.debug logs from completion provider These debug logs were used during development and logged full editor text and completion items to the webview console on every keystroke. Removed to avoid unnecessary noise and potential data exposure. --- .../documentdbQuery/registerLanguage.ts | 27 ------------------- 1 file changed, 27 deletions(-) diff --git a/src/webviews/documentdbQuery/registerLanguage.ts b/src/webviews/documentdbQuery/registerLanguage.ts index faeba3f66..7624ff4b7 100644 --- a/src/webviews/documentdbQuery/registerLanguage.ts +++ b/src/webviews/documentdbQuery/registerLanguage.ts @@ -112,20 +112,6 @@ async function doRegisterLanguage(monaco: typeof monacoEditor): Promise { const cursorContext = detectCursorContext(text, cursorOffset, fieldLookup); - // Trace-level logging for debugging context-sensitive completions - console.debug('[documentdb-query] provideCompletionItems', { - text, - cursorOffset, - position: { line: position.lineNumber, col: position.column }, - charBefore, - isDollarPrefix: charBefore === '$', - wordInfo: { word: wordInfo.word, startColumn: wordInfo.startColumn, endColumn: wordInfo.endColumn }, - range, - cursorContext, - editorType: parsed?.editorType, - sessionId, - }); - // Build completion items based on context const items = createCompletionItems({ editorType: parsed?.editorType, @@ -136,19 +122,6 @@ async function doRegisterLanguage(monaco: typeof monacoEditor): Promise { cursorContext, }); - console.debug('[documentdb-query] completionItems', { - count: items.length, - labels: items.map((i) => i.label), - contextPosition: cursorContext.position, - // Log first 3 items with their insertText for snippet debugging - sampleItems: items.slice(0, 3).map((i) => ({ - label: i.label, - insertText: i.insertText, - insertTextRules: i.insertTextRules, - range: i.range, - })), - }); - return { suggestions: items }; }, }); From d84f4465350c0cc3cc4c427c2067633a3c7d19a2 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Wed, 18 Mar 2026 10:04:19 +0000 Subject: [PATCH 093/128] docs: update completion flow to clarify handling of unknown context and include JS globals --- src/webviews/documentdbQuery/completions/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/webviews/documentdbQuery/completions/README.md b/src/webviews/documentdbQuery/completions/README.md index 85b738be9..0e7277ec8 100644 --- a/src/webviews/documentdbQuery/completions/README.md +++ b/src/webviews/documentdbQuery/completions/README.md @@ -23,9 +23,10 @@ registerLanguage.ts 1. Monaco calls `provideCompletionItems()` (registered in `registerLanguage.ts`) 2. `detectCursorContext()` scans backward from the cursor to determine the semantic position 3. `createCompletionItems()` routes to the appropriate builder: - - **key / array-element / unknown** → field names + key-position operators - - **value** → type suggestions + operators (with braces) + BSON constructors + - **key / array-element** → field names + key-position operators + - **value** → type suggestions + operators (with braces) + BSON constructors + JS globals - **operator** → operators only (braces stripped, type-aware sorting) + - **unknown / undefined** → all completions (fields, all operators, BSON constructors, JS globals) ## Sorting From 31726718330c87c23fddf9242116b00cce649aaf Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Wed, 18 Mar 2026 10:59:22 +0000 Subject: [PATCH 094/128] fix: set isTrusted on completion documentation for clickable links Documentation links like [DocumentDB Docs](https://...) were not rendered as clickable hyperlinks in Monaco's completion detail panel. Monaco requires { value: string, isTrusted: true } on MarkdownStrings to enable link rendering. Set isTrusted: true on operator documentation MarkdownStrings in mapOperatorToCompletionItem. This is safe because the documentation content comes entirely from documentdb-constants (operator descriptions we control), not from user-generated content. --- src/webviews/documentdbQuery/completions/mapCompletionItems.ts | 1 + .../documentdbQuery/documentdbQueryCompletionProvider.test.ts | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/webviews/documentdbQuery/completions/mapCompletionItems.ts b/src/webviews/documentdbQuery/completions/mapCompletionItems.ts index 940e7eab8..c00baee13 100644 --- a/src/webviews/documentdbQuery/completions/mapCompletionItems.ts +++ b/src/webviews/documentdbQuery/completions/mapCompletionItems.ts @@ -116,6 +116,7 @@ export function mapOperatorToCompletionItem( insertTextRules: hasSnippet ? monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet : undefined, documentation: { value: documentationValue, + isTrusted: true, }, sortText: sortPrefix ? `${sortPrefix}${entry.value}` : undefined, range, diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index 8acecd66a..5763e0183 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -163,6 +163,7 @@ describe('documentdbQueryCompletionProvider', () => { expect(item.insertTextRules).toBeUndefined(); expect(item.documentation).toEqual({ value: 'Matches values equal to a specified value.', + isTrusted: true, }); expect(item.range).toBe(testRange); }); @@ -199,6 +200,7 @@ describe('documentdbQueryCompletionProvider', () => { expect(item.insertTextRules).toBe(mockInsertTextRule.InsertAsSnippet); expect(item.documentation).toEqual({ value: 'Creates a new ObjectId value.\n\n[DocumentDB Docs](https://docs.example.com/objectid)', + isTrusted: true, }); }); From 4855f48458b55eee463dd44143ee0a8bee027ff9 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Wed, 18 Mar 2026 11:00:41 +0000 Subject: [PATCH 095/128] fix: preserve field completion data across query changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, ClusterSession reset the SchemaAnalyzer when the user changed their query. This meant queries returning 0 results left the autocompletion field list empty. Now the SchemaAnalyzer accumulates field knowledge monotonically across queries within the same session — new fields are added, type statistics enriched. Trade-off: type statistics represent aggregated observations across all queries, not a single query snapshot. This is acceptable since the UI shows approximate type info (e.g., 'mostly String') rather than absolute percentages. Added a future work discussion in docs/plan/future-work.md about potential strategies for separating cumulative vs. per-query statistics if needed. --- src/documentdb/ClusterSession.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/documentdb/ClusterSession.ts b/src/documentdb/ClusterSession.ts index 432d53581..da3b5107c 100644 --- a/src/documentdb/ClusterSession.ts +++ b/src/documentdb/ClusterSession.ts @@ -167,9 +167,17 @@ export class ClusterSession { } } - // The user's query has changed, invalidate all caches - this._schemaAnalyzer.reset(); - ext.outputChannel.trace('[SchemaAnalyzer] Reset — query changed'); + // The user's query has changed, invalidate all caches. + // + // NOTE: We intentionally do NOT reset the SchemaAnalyzer here. + // When a new query returns 0 results, preserving field knowledge from + // previous queries is more valuable for autocompletion than having an + // empty field list. The SchemaAnalyzer accumulates field data + // monotonically — new fields are added, existing field type statistics + // are enriched with each query. This means type statistics represent + // aggregated observations across queries, not a single query snapshot. + // Consumers should treat type frequency data as approximate/relative + // (e.g., "mostly String") rather than absolute percentages. this._highestPageAccumulated = 0; this._currentPageSize = null; this._currentRawDocuments = []; From 1cd9f66bb5e89b854846232f265f185d31a0dd64 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Wed, 18 Mar 2026 11:02:12 +0000 Subject: [PATCH 096/128] fix: move $not from key-position to field-level operator category $not is a field-level operator (e.g., { price: { $not: { $gt: 1.99 } } }), not a root-level logical combinator like $and/$or/$nor. It was incorrectly included in KEY_POSITION_OPERATORS, causing it to appear at query root (where it's invalid) and be hidden at operator position (where users need it). Changes: - Remove '$not' from KEY_POSITION_OPERATORS in completionKnowledge.ts - Update JSDoc to document why $not is excluded - Update tests: expect $not at operator position, not at key position --- .../documentdbQuery/completions/completionKnowledge.ts | 5 ++++- .../documentdbQueryCompletionProvider.test.ts | 7 +++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/webviews/documentdbQuery/completions/completionKnowledge.ts b/src/webviews/documentdbQuery/completions/completionKnowledge.ts index 0f56e4fa4..148539e60 100644 --- a/src/webviews/documentdbQuery/completions/completionKnowledge.ts +++ b/src/webviews/documentdbQuery/completions/completionKnowledge.ts @@ -49,6 +49,10 @@ * { age: { $and: … } } * ``` * + * **`$not` is intentionally excluded** — despite being a logical operator, + * `$not` is a field-level operator that wraps a single field's expression: + * `{ price: { $not: { $gt: 1.99 } } }`. It does NOT work at query root. + * * The completion provider uses this set to: * - **Include** these operators at key position and array-element position * - **Exclude** them from operator position (inside `{ field: { … } }`) @@ -60,7 +64,6 @@ export const KEY_POSITION_OPERATORS = new Set([ '$and', '$or', '$nor', - '$not', '$comment', '$expr', '$jsonSchema', diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index 5763e0183..7e982ee82 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -900,9 +900,10 @@ describe('documentdbQueryCompletionProvider', () => { expect(labels).toContain('$and'); expect(labels).toContain('$or'); expect(labels).toContain('$nor'); - expect(labels).toContain('$not'); expect(labels).toContain('$comment'); expect(labels).toContain('$expr'); + // $not is a field-level operator, NOT a key-position operator + expect(labels).not.toContain('$not'); }); test('does NOT show value-level operators ($gt, $lt, $regex, $eq)', () => { @@ -1098,7 +1099,7 @@ describe('documentdbQueryCompletionProvider', () => { describe('operator position', () => { const operatorContext: CursorContext = { position: 'operator', fieldName: 'age' }; - test('shows comparison operators ($gt, $lt, $eq, $in)', () => { + test('shows comparison operators ($gt, $lt, $eq, $in) and $not', () => { const items = createCompletionItems({ editorType: EditorType.Filter, sessionId: undefined, @@ -1115,6 +1116,8 @@ describe('documentdbQueryCompletionProvider', () => { expect(labels).toContain('$in'); expect(labels).toContain('$exists'); expect(labels).toContain('$regex'); + // $not is a field-level operator, valid at operator position + expect(labels).toContain('$not'); }); test('does NOT show key-position operators ($and, $or)', () => { From 26de68f5037724f6a8ede87a9947be195d412e4f Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Wed, 18 Mar 2026 11:03:35 +0000 Subject: [PATCH 097/128] feat: add project (1/0) and sort (1/-1) value completions At value position in the project editor, show 1 (include) and 0 (exclude) instead of filter-specific completions (operators, BSON constructors, etc.). At value position in the sort editor, show 1 (ascending) and -1 (descending). These are the most common values for projection and sort fields. Projection operators like $slice and $elemMatch remain available via operator-position completions for advanced use cases. --- .../completions/createCompletionItems.ts | 77 +++++++++- .../documentdbQueryCompletionProvider.test.ts | 139 ++++++++++++++++++ 2 files changed, 212 insertions(+), 4 deletions(-) diff --git a/src/webviews/documentdbQuery/completions/createCompletionItems.ts b/src/webviews/documentdbQuery/completions/createCompletionItems.ts index 18a8e5ca5..8a40dbf38 100644 --- a/src/webviews/documentdbQuery/completions/createCompletionItems.ts +++ b/src/webviews/documentdbQuery/completions/createCompletionItems.ts @@ -175,10 +175,13 @@ function createKeyPositionCompletions( /** * Value position completions: - * 1. Type-aware suggestions (sort `00_`) — e.g., `true`/`false` for booleans - * 2. Query operators with brace-wrapping snippets (sort `0_`–`2_`) - * 3. BSON constructors (sort `3_`) - * 4. JS globals: Date, Math, RegExp, etc. (sort `4_`) + * - **Project editor**: `1` (include) and `0` (exclude) — the most common projection values + * - **Sort editor**: `1` (ascending) and `-1` (descending) + * - **Filter editor** (default): + * 1. Type-aware suggestions (sort `00_`) — e.g., `true`/`false` for booleans + * 2. Query operators with brace-wrapping snippets (sort `0_`–`2_`) + * 3. BSON constructors (sort `3_`) + * 4. JS globals: Date, Math, RegExp, etc. (sort `4_`) */ function createValuePositionCompletions( editorType: EditorType | undefined, @@ -186,6 +189,16 @@ function createValuePositionCompletions( monaco: typeof monacoEditor, fieldBsonType: string | undefined, ): monacoEditor.languages.CompletionItem[] { + // Project editor: only show include/exclude values + if (editorType === EditorType.Project) { + return createProjectValueCompletions(range, monaco); + } + + // Sort editor: only show ascending/descending values + if (editorType === EditorType.Sort) { + return createSortValueCompletions(range, monaco); + } + const metaTags = getMetaTagsForEditorType(editorType); const allEntries = getFilteredCompletions({ meta: [...metaTags] }); @@ -222,6 +235,62 @@ function createValuePositionCompletions( return [...typeSuggestions, ...operatorItems, ...bsonItems, ...jsGlobals]; } +/** + * Value completions for the **project** editor: `1` (include) and `0` (exclude). + * + * Projection operators like `$slice` and `$elemMatch` are already available + * via operator-position completions; these simple numeric values cover the + * most common use case. + */ +function createProjectValueCompletions( + range: monacoEditor.IRange, + monaco: typeof monacoEditor, +): monacoEditor.languages.CompletionItem[] { + return [ + { + label: { label: '1', description: 'include field' }, + kind: monaco.languages.CompletionItemKind.Value, + insertText: '1', + sortText: '00_1', + preselect: true, + range, + }, + { + label: { label: '0', description: 'exclude field' }, + kind: monaco.languages.CompletionItemKind.Value, + insertText: '0', + sortText: '00_0', + range, + }, + ]; +} + +/** + * Value completions for the **sort** editor: `1` (ascending) and `-1` (descending). + */ +function createSortValueCompletions( + range: monacoEditor.IRange, + monaco: typeof monacoEditor, +): monacoEditor.languages.CompletionItem[] { + return [ + { + label: { label: '1', description: 'ascending' }, + kind: monaco.languages.CompletionItemKind.Value, + insertText: '1', + sortText: '00_1', + preselect: true, + range, + }, + { + label: { label: '-1', description: 'descending' }, + kind: monaco.languages.CompletionItemKind.Value, + insertText: '-1', + sortText: '00_-1', + range, + }, + ]; +} + function createOperatorPositionCompletions( editorType: EditorType | undefined, range: monacoEditor.IRange, diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index 7e982ee82..5c3d07231 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -1485,4 +1485,143 @@ describe('documentdbQueryCompletionProvider', () => { expect(items.filter((i) => i.sortText?.startsWith('00_'))).toHaveLength(0); }); }); + + // --------------------------------------------------------------- + // Project and Sort value completions + // --------------------------------------------------------------- + describe('project editor value completions', () => { + const mockMonaco = createMockMonaco(); + + test('shows 1 (include) and 0 (exclude) at value position', () => { + const context: CursorContext = { position: 'value', fieldName: 'name' }; + const items = createCompletionItems({ + editorType: EditorType.Project, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: context, + }); + + expect(items).toHaveLength(2); + const labels = items.map((i) => getLabelText(i.label)); + expect(labels).toContain('1'); + expect(labels).toContain('0'); + }); + + test('1 (include) has description "include field"', () => { + const context: CursorContext = { position: 'value', fieldName: 'name' }; + const items = createCompletionItems({ + editorType: EditorType.Project, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: context, + }); + + const includeItem = items.find((i) => getLabelText(i.label) === '1'); + expect((includeItem?.label as { description: string }).description).toBe('include field'); + }); + + test('does NOT show operators, BSON constructors, or JS globals', () => { + const context: CursorContext = { position: 'value', fieldName: 'name' }; + const items = createCompletionItems({ + editorType: EditorType.Project, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: context, + }); + + const labels = items.map((i) => getLabelText(i.label)); + expect(labels).not.toContain('$gt'); + expect(labels).not.toContain('ObjectId'); + expect(labels).not.toContain('Date'); + }); + + test('1 is preselected', () => { + const context: CursorContext = { position: 'value', fieldName: 'name' }; + const items = createCompletionItems({ + editorType: EditorType.Project, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: context, + }); + + const includeItem = items.find((i) => getLabelText(i.label) === '1'); + expect(includeItem?.preselect).toBe(true); + }); + }); + + describe('sort editor value completions', () => { + const mockMonaco = createMockMonaco(); + + test('shows 1 (ascending) and -1 (descending) at value position', () => { + const context: CursorContext = { position: 'value', fieldName: 'age' }; + const items = createCompletionItems({ + editorType: EditorType.Sort, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: context, + }); + + expect(items).toHaveLength(2); + const labels = items.map((i) => getLabelText(i.label)); + expect(labels).toContain('1'); + expect(labels).toContain('-1'); + }); + + test('-1 has description "descending"', () => { + const context: CursorContext = { position: 'value', fieldName: 'age' }; + const items = createCompletionItems({ + editorType: EditorType.Sort, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: context, + }); + + const descItem = items.find((i) => getLabelText(i.label) === '-1'); + expect((descItem?.label as { description: string }).description).toBe('descending'); + }); + + test('does NOT show operators, BSON constructors, or JS globals', () => { + const context: CursorContext = { position: 'value', fieldName: 'age' }; + const items = createCompletionItems({ + editorType: EditorType.Sort, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: context, + }); + + const labels = items.map((i) => getLabelText(i.label)); + expect(labels).not.toContain('$gt'); + expect(labels).not.toContain('ObjectId'); + expect(labels).not.toContain('Date'); + }); + + test('1 is preselected', () => { + const context: CursorContext = { position: 'value', fieldName: 'age' }; + const items = createCompletionItems({ + editorType: EditorType.Sort, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: context, + }); + + const ascItem = items.find((i) => getLabelText(i.label) === '1'); + expect(ascItem?.preselect).toBe(true); + }); + }); }); From 31dba3d29fbd913f2c6d43d34a24da180929e187 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Wed, 18 Mar 2026 11:06:56 +0000 Subject: [PATCH 098/128] fix: wrap completions with braces when editor has no outer brackets When the user clears the editor content (removing the initial '{ }'), field completions now insert '{ fieldName: $1 }' instead of 'fieldName: $1' to produce valid query syntax. Operator snippets already include their own braces and are not double-wrapped. A 'needsWrapping' flag is computed in registerLanguage.ts by checking whether the editor text contains a '{' character. When true, field completions in the 'all completions' fallback path get wrapped with outer braces. --- .../completions/createCompletionItems.ts | 23 +++++- .../documentdbQueryCompletionProvider.test.ts | 75 +++++++++++++++++++ .../documentdbQuery/registerLanguage.ts | 6 ++ 3 files changed, 101 insertions(+), 3 deletions(-) diff --git a/src/webviews/documentdbQuery/completions/createCompletionItems.ts b/src/webviews/documentdbQuery/completions/createCompletionItems.ts index 8a40dbf38..a9fba4e44 100644 --- a/src/webviews/documentdbQuery/completions/createCompletionItems.ts +++ b/src/webviews/documentdbQuery/completions/createCompletionItems.ts @@ -45,6 +45,12 @@ export interface CreateCompletionItemsParams { * When provided, operators are sorted by type relevance. */ fieldBsonTypes?: readonly string[]; + /** + * When true, completion snippets should include outer `{ }` wrapping. + * Set when the editor content has no braces (user cleared the editor), + * so that inserted completions produce valid query syntax. + */ + needsWrapping?: boolean; /** * Optional cursor context from the heuristic cursor position detector. * When provided, completions are filtered based on the semantic position @@ -89,12 +95,12 @@ export function getMetaTagsForEditorType(editorType: EditorType | undefined): re * constructors, and JS globals (backward-compatible fallback) */ export function createCompletionItems(params: CreateCompletionItemsParams): monacoEditor.languages.CompletionItem[] { - const { editorType, sessionId, range, monaco, fieldBsonTypes, cursorContext } = params; + const { editorType, sessionId, range, monaco, fieldBsonTypes, cursorContext, needsWrapping } = params; if (!cursorContext || cursorContext.position === 'unknown') { // When context is unknown (e.g., empty input, no braces), show all // completions so the user can discover what's available. - return createAllCompletions(editorType, sessionId, range, monaco); + return createAllCompletions(editorType, sessionId, range, monaco, needsWrapping); } switch (cursorContext.position) { @@ -122,17 +128,28 @@ export function createCompletionItems(params: CreateCompletionItemsParams): mona /** * All completions — used when cursor context is unknown or undefined. * Shows fields, all operators, BSON constructors, and JS globals. + * + * When `needsWrapping` is true, field insertText is wrapped with `{ ... }` + * to produce valid syntax in an empty editor. */ function createAllCompletions( editorType: EditorType | undefined, sessionId: string | undefined, range: monacoEditor.IRange, monaco: typeof monacoEditor, + needsWrapping?: boolean, ): monacoEditor.languages.CompletionItem[] { const metaTags = getMetaTagsForEditorType(editorType); const allEntries = getFilteredCompletions({ meta: [...metaTags] }); - const fieldItems = getFieldCompletionItems(sessionId, range, monaco); + let fieldItems = getFieldCompletionItems(sessionId, range, monaco); + if (needsWrapping) { + // Wrap field insertText with { ... } for empty-editor context + fieldItems = fieldItems.map((item) => ({ + ...item, + insertText: `{ ${item.insertText as string} }`, + })); + } const operatorItems = allEntries .filter((e) => e.meta !== 'bson' && e.meta !== 'variable') diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index 5c3d07231..fe61caffe 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -1321,6 +1321,81 @@ describe('documentdbQueryCompletionProvider', () => { expect(labels).toContain('ObjectId'); }); }); + + describe('needsWrapping (empty editor, no braces)', () => { + test('field insertText is wrapped with { } when needsWrapping is true', () => { + setCompletionContext('test-session', { + fields: [ + { + fieldName: 'name', + displayType: 'String', + bsonType: 'string', + isSparse: false, + insertText: 'name', + referenceText: '$name', + }, + ], + }); + + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: 'test-session', + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: { position: 'unknown' }, + needsWrapping: true, + }); + + const fieldItem = items.find((i) => getLabelText(i.label) === 'name'); + expect(fieldItem?.insertText).toBe('{ name: $1 }'); + }); + + test('field insertText is NOT wrapped when needsWrapping is false', () => { + setCompletionContext('test-session', { + fields: [ + { + fieldName: 'name', + displayType: 'String', + bsonType: 'string', + isSparse: false, + insertText: 'name', + referenceText: '$name', + }, + ], + }); + + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: 'test-session', + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: { position: 'unknown' }, + needsWrapping: false, + }); + + const fieldItem = items.find((i) => getLabelText(i.label) === 'name'); + expect(fieldItem?.insertText).toBe('name: $1'); + }); + + test('operators keep full brace-wrapping snippets when needsWrapping is true', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: { position: 'unknown' }, + needsWrapping: true, + }); + + // Operator snippets include { } already — they should NOT be stripped + const andItem = items.find((i) => getLabelText(i.label) === '$and'); + expect(andItem?.insertText).toContain('{'); + expect(andItem?.insertText).toContain('}'); + }); + }); }); // --------------------------------------------------------------- diff --git a/src/webviews/documentdbQuery/registerLanguage.ts b/src/webviews/documentdbQuery/registerLanguage.ts index 7624ff4b7..8cf67983b 100644 --- a/src/webviews/documentdbQuery/registerLanguage.ts +++ b/src/webviews/documentdbQuery/registerLanguage.ts @@ -112,6 +112,11 @@ async function doRegisterLanguage(monaco: typeof monacoEditor): Promise { const cursorContext = detectCursorContext(text, cursorOffset, fieldLookup); + // Detect whether the editor content has braces. When the user clears + // the editor (deleting initial `{ }`), completions need to include + // wrapping braces so inserted snippets produce valid query syntax. + const needsWrapping = !text.includes('{'); + // Build completion items based on context const items = createCompletionItems({ editorType: parsed?.editorType, @@ -120,6 +125,7 @@ async function doRegisterLanguage(monaco: typeof monacoEditor): Promise { isDollarPrefix: charBefore === '$', monaco, cursorContext, + needsWrapping, }); return { suggestions: items }; From 394425e7c3c9669317e4a7c1967477b79c7f6f54 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Wed, 18 Mar 2026 11:08:11 +0000 Subject: [PATCH 099/128] feat: add auto-trigger characters for colon, comma, and bracket Added ':', ',', and '[' to the completion provider's triggerCharacters list. These positions are already handled by the cursor context parser (value after ':', new key after ',', array element after '[') but previously required manual Ctrl+Space invocation. Added string-literal detection (isCursorInsideString) to suppress completions when trigger characters appear inside string values. Uses a forward scan counting unescaped quotes to determine if the cursor is inside a string. When inside a string, returns empty suggestions to prevent the popup. --- .../isCursorInsideString.test.ts | 87 +++++++++++++++++++ .../documentdbQuery/isCursorInsideString.ts | 47 ++++++++++ .../documentdbQuery/registerLanguage.ts | 11 ++- 3 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 src/webviews/documentdbQuery/isCursorInsideString.test.ts create mode 100644 src/webviews/documentdbQuery/isCursorInsideString.ts diff --git a/src/webviews/documentdbQuery/isCursorInsideString.test.ts b/src/webviews/documentdbQuery/isCursorInsideString.test.ts new file mode 100644 index 000000000..1c5468aff --- /dev/null +++ b/src/webviews/documentdbQuery/isCursorInsideString.test.ts @@ -0,0 +1,87 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { isCursorInsideString } from './isCursorInsideString'; + +describe('isCursorInsideString', () => { + test('returns false for empty text', () => { + expect(isCursorInsideString('', 0)).toBe(false); + }); + + test('returns false when cursor is outside any string', () => { + const text = '{ name: "Alice", age: 30 }'; + // cursor after the comma, outside the string + const cursorOffset = text.indexOf(',') + 1; + expect(isCursorInsideString(text, cursorOffset)).toBe(false); + }); + + test('returns true when cursor is inside a double-quoted string', () => { + const text = '{ name: "Ali'; + expect(isCursorInsideString(text, text.length)).toBe(true); + }); + + test('returns true when cursor is inside a single-quoted string', () => { + const text = "{ name: 'Ali"; + expect(isCursorInsideString(text, text.length)).toBe(true); + }); + + test('returns false when cursor is after a closed string', () => { + const text = '{ name: "Alice" }'; + // cursor at the space after closing quote + const cursorOffset = text.indexOf('"', 9) + 1; + expect(isCursorInsideString(text, cursorOffset)).toBe(false); + }); + + test('handles escaped quotes inside strings', () => { + const text = '{ name: "has\\"quote'; + // cursor is still inside the string (the \" is escaped) + expect(isCursorInsideString(text, text.length)).toBe(true); + }); + + test('returns false after escaped quote followed by closing quote', () => { + const text = '{ name: "has\\"quote" }'; + // cursor after the closing quote + const closingQuoteIdx = text.lastIndexOf('"'); + expect(isCursorInsideString(text, closingQuoteIdx + 1)).toBe(false); + }); + + // Edge cases from the plan + test('{ name: "Alice", | } — cursor outside string after comma', () => { + const text = '{ name: "Alice", '; + expect(isCursorInsideString(text, text.length)).toBe(false); + }); + + test('{ name: "has:colon" } — cursor inside string at colon', () => { + const text = '{ name: "has:'; + expect(isCursorInsideString(text, text.length)).toBe(true); + }); + + test('{ name: "has:colon", | } — cursor outside string after comma', () => { + const text = '{ name: "has:colon", '; + expect(isCursorInsideString(text, text.length)).toBe(false); + }); + + test('{ tags: ["a", | ] } — cursor outside string in array', () => { + const text = '{ tags: ["a", '; + expect(isCursorInsideString(text, text.length)).toBe(false); + }); + + test('{ msg: "has[bracket" } — cursor inside string at bracket', () => { + const text = '{ msg: "has['; + expect(isCursorInsideString(text, text.length)).toBe(true); + }); + + test('{ $and: [ | ] } — cursor outside string in array', () => { + const text = '{ $and: [ '; + expect(isCursorInsideString(text, text.length)).toBe(false); + }); + + test('handles mixed quote types correctly', () => { + const text = '{ name: "it\'s" }'; + // The single quote inside double quotes doesn't close anything + const cursorAfterClosingDouble = text.indexOf('"', 9) + 1; + expect(isCursorInsideString(text, cursorAfterClosingDouble)).toBe(false); + }); +}); diff --git a/src/webviews/documentdbQuery/isCursorInsideString.ts b/src/webviews/documentdbQuery/isCursorInsideString.ts new file mode 100644 index 000000000..7c605d1fe --- /dev/null +++ b/src/webviews/documentdbQuery/isCursorInsideString.ts @@ -0,0 +1,47 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Determines whether the cursor is inside a string literal. + * + * Scans the text from the beginning up to the cursor offset, tracking whether + * we are inside a single-quoted or double-quoted string. Escaped quotes + * (preceded by `\`) do not toggle the state. + * + * This is a lightweight heuristic for suppressing auto-trigger completions + * when the trigger character (`:`, `,`, `[`) appears inside a string value + * rather than as structural syntax. + * + * @param text - the full text of the editor + * @param cursorOffset - the 0-based character offset of the cursor + * @returns true if the cursor is inside a string literal + */ +export function isCursorInsideString(text: string, cursorOffset: number): boolean { + let inString: "'" | '"' | false = false; + + for (let i = 0; i < cursorOffset && i < text.length; i++) { + const ch = text[i]; + + if (inString) { + // Check for escape character + if (ch === '\\') { + // Skip the next character (escaped) + i++; + continue; + } + // Check for closing quote + if (ch === inString) { + inString = false; + } + } else { + // Check for opening quote + if (ch === '"' || ch === "'") { + inString = ch; + } + } + } + + return inString !== false; +} diff --git a/src/webviews/documentdbQuery/registerLanguage.ts b/src/webviews/documentdbQuery/registerLanguage.ts index 8cf67983b..806c3c3e9 100644 --- a/src/webviews/documentdbQuery/registerLanguage.ts +++ b/src/webviews/documentdbQuery/registerLanguage.ts @@ -30,6 +30,7 @@ import { getCompletionContext } from './completionStore'; import { detectCursorContext } from './cursorContext'; import { createCompletionItems } from './documentdbQueryCompletionProvider'; import { getHoverContent } from './documentdbQueryHoverProvider'; +import { isCursorInsideString } from './isCursorInsideString'; import { LANGUAGE_ID, parseEditorUri } from './languageConfig'; /** Coalesces concurrent registrations into a single promise. */ @@ -67,7 +68,7 @@ async function doRegisterLanguage(monaco: typeof monacoEditor): Promise { // Step 4: Register the completion provider monaco.languages.registerCompletionItemProvider(LANGUAGE_ID, { - triggerCharacters: ['$', '"', "'", '{', '.'], + triggerCharacters: ['$', '"', "'", '{', '.', ':', ',', '['], provideCompletionItems: ( model: monacoEditor.editor.ITextModel, position: monacoEditor.Position, @@ -101,6 +102,14 @@ async function doRegisterLanguage(monaco: typeof monacoEditor): Promise { // Detect cursor context for context-sensitive completions const text = model.getValue(); const cursorOffset = model.getOffsetAt(position); + + // Suppress completions when the cursor is inside a string literal. + // This prevents trigger characters like ':', ',', '[' from firing + // inside strings like { name: "has:colon" } or { msg: "has[bracket" }. + if (isCursorInsideString(text, cursorOffset)) { + return { suggestions: [] }; + } + const sessionId = parsed?.sessionId; // Build field lookup from completion store to enrich context with BSON types From b46254a229d3806c74483e595710ee74b026ee4d Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Wed, 18 Mar 2026 11:10:11 +0000 Subject: [PATCH 100/128] feat: add field type hover provider Extended the HoverProvider to show type information when hovering over field names in the query editor. When a field is recognized from the completion store (populated by SchemaAnalyzer), the hover shows: - Field name (bold) - BSON type (e.g., Number, String, Date) - Sparse indicator when the field is not present in all documents Operators/BSON constructors take priority over field names to avoid ambiguity. Statistics use relative language ('sparse') rather than absolute numbers since the SchemaAnalyzer accumulates data across queries. Also set isTrusted: true on operator hover content to make doc links clickable (consistent with the completion documentation fix). --- .../documentdbQueryHoverProvider.test.ts | 87 ++++++++++++++++++- .../documentdbQueryHoverProvider.ts | 47 +++++++++- .../documentdbQuery/registerLanguage.ts | 12 ++- 3 files changed, 140 insertions(+), 6 deletions(-) diff --git a/src/webviews/documentdbQuery/documentdbQueryHoverProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryHoverProvider.test.ts index ca52d52e7..a157c06e2 100644 --- a/src/webviews/documentdbQuery/documentdbQueryHoverProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryHoverProvider.test.ts @@ -3,7 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { getHoverContent } from './documentdbQueryHoverProvider'; +import { type FieldCompletionData } from '../../utils/json/data-api/autocomplete/toFieldCompletionItems'; +import { getHoverContent, type FieldDataLookup } from './documentdbQueryHoverProvider'; + +/** Creates a mock field lookup function from an array of fields. */ +function createFieldLookup(fields: FieldCompletionData[]): FieldDataLookup { + return (word: string) => fields.find((f) => f.fieldName === word); +} describe('documentdbQueryHoverProvider', () => { describe('getHoverContent', () => { @@ -70,4 +76,83 @@ describe('documentdbQueryHoverProvider', () => { expect(content).toContain('**UUID**'); }); }); + + describe('field hover', () => { + const fields: FieldCompletionData[] = [ + { + fieldName: 'age', + displayType: 'Number', + bsonType: 'int32', + isSparse: false, + insertText: 'age', + referenceText: '$age', + }, + { + fieldName: 'nickname', + displayType: 'String', + bsonType: 'string', + isSparse: true, + insertText: 'nickname', + referenceText: '$nickname', + }, + ]; + + test('returns hover for a known field name', () => { + const hover = getHoverContent('age', createFieldLookup(fields)); + expect(hover).not.toBeNull(); + + const content = (hover!.contents[0] as { value: string }).value; + expect(content).toContain('**age**'); + expect(content).toContain('Number'); + }); + + test('shows sparse indicator for sparse fields', () => { + const hover = getHoverContent('nickname', createFieldLookup(fields)); + expect(hover).not.toBeNull(); + + const content = (hover!.contents[0] as { value: string }).value; + expect(content).toContain('**nickname**'); + expect(content).toContain('String'); + expect(content).toContain('sparse'); + }); + + test('does NOT show sparse indicator for non-sparse fields', () => { + const hover = getHoverContent('age', createFieldLookup(fields)); + expect(hover).not.toBeNull(); + + const content = (hover!.contents[0] as { value: string }).value; + expect(content).not.toContain('sparse'); + }); + + test('returns null for unknown field when no operator match', () => { + const hover = getHoverContent('unknownField', createFieldLookup(fields)); + expect(hover).toBeNull(); + }); + + test('operators take priority over field names', () => { + // If a field happens to be named "gt", the operator $gt should match first + const fieldsWithOperatorName: FieldCompletionData[] = [ + { + fieldName: 'gt', + displayType: 'String', + bsonType: 'string', + isSparse: false, + insertText: 'gt', + referenceText: '$gt', + }, + ]; + + const hover = getHoverContent('gt', createFieldLookup(fieldsWithOperatorName)); + expect(hover).not.toBeNull(); + + const content = (hover!.contents[0] as { value: string }).value; + // Should show operator hover, not field hover + expect(content).toContain('**$gt**'); + }); + + test('returns null for field when no fieldLookup provided', () => { + const hover = getHoverContent('age'); + expect(hover).toBeNull(); + }); + }); }); diff --git a/src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts b/src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts index d07c32951..ac08bb52b 100644 --- a/src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts +++ b/src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts @@ -6,13 +6,20 @@ /** * Hover provider logic for the `documentdb-query` language. * - * Provides inline documentation when hovering over operators and - * BSON constructors. Uses `documentdb-constants` for the operator registry. + * Provides inline documentation when hovering over operators, + * BSON constructors, and field names. Uses `documentdb-constants` for + * the operator registry and the completion store for field type info. */ import { getAllCompletions } from '@vscode-documentdb/documentdb-constants'; // eslint-disable-next-line import/no-internal-modules import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; +import { type FieldCompletionData } from '../../utils/json/data-api/autocomplete/toFieldCompletionItems'; + +/** + * A callback that resolves a word to field data from the completion store. + */ +export type FieldDataLookup = (word: string) => FieldCompletionData | undefined; /** * Returns hover content for a word under the cursor. @@ -20,11 +27,15 @@ import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; * Tries multiple candidates to handle cases where: * - The cursor is on `gt` after `$` (need to try `$gt`) * - The cursor is on `ObjectId` (try as-is) + * - The cursor is on a field name like `age` (check field data) + * + * Operators/BSON constructors take priority over field names. * * @param word - The word at the cursor position + * @param fieldLookup - optional callback to resolve field names to field data * @returns A Monaco Hover or null if no match */ -export function getHoverContent(word: string): monacoEditor.languages.Hover | null { +export function getHoverContent(word: string, fieldLookup?: FieldDataLookup): monacoEditor.languages.Hover | null { // Try with '$' prefix first (for operators where cursor lands after $) // Then try the word as-is (for BSON constructors like ObjectId) const candidates = word.startsWith('$') ? [word] : [`$${word}`, word]; @@ -42,9 +53,37 @@ export function getHoverContent(word: string): monacoEditor.languages.Hover | nu lines.push('', `[DocumentDB Docs](${match.link})`); } return { - contents: [{ value: lines.join('\n') }], + contents: [{ value: lines.join('\n'), isTrusted: true }], }; } } + + // If no operator match, try field name lookup + if (fieldLookup) { + const fieldData = fieldLookup(word); + if (fieldData) { + return buildFieldHover(fieldData); + } + } + return null; } + +/** + * Builds a hover tooltip for a field name, showing its type info. + * + * Uses relative language for statistics (e.g., "sparse" rather than + * absolute percentages) since the SchemaAnalyzer accumulates data + * across queries and the numbers are approximate. + */ +function buildFieldHover(field: FieldCompletionData): monacoEditor.languages.Hover { + const lines: string[] = [`**${field.fieldName}**`]; + + // Type info + const sparseNote = field.isSparse ? ' *(sparse — not present in all documents)*' : ''; + lines.push('', `Type: \`${field.displayType}\`${sparseNote}`); + + return { + contents: [{ value: lines.join('\n') }], + }; +} diff --git a/src/webviews/documentdbQuery/registerLanguage.ts b/src/webviews/documentdbQuery/registerLanguage.ts index 806c3c3e9..1d9c7feff 100644 --- a/src/webviews/documentdbQuery/registerLanguage.ts +++ b/src/webviews/documentdbQuery/registerLanguage.ts @@ -152,7 +152,17 @@ async function doRegisterLanguage(monaco: typeof monacoEditor): Promise { return null; } - const hover = getHoverContent(wordAtPosition.word); + // Build field lookup from completion store for field hover info + const uriString = model.uri.toString(); + const parsedUri = parseEditorUri(uriString); + const hoverFieldLookup = parsedUri?.sessionId + ? (word: string) => { + const ctx = getCompletionContext(parsedUri.sessionId); + return ctx?.fields.find((f) => f.fieldName === word); + } + : undefined; + + const hover = getHoverContent(wordAtPosition.word, hoverFieldLookup); if (!hover) { return null; } From b4fd7a97c5bc5d7d353b8b618a7393e186967a35 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Wed, 18 Mar 2026 12:55:25 +0000 Subject: [PATCH 101/128] =?UTF-8?q?fix:=20hover=20provider=20improvements?= =?UTF-8?q?=20=E2=80=94=20quoted=20keys,=20isTrusted,=20inferred=20types?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three hover provider fixes: 1. Quoted string keys: Hover now works for quoted field names like {"address.street": 1}. Monaco's getWordAtPosition treats quotes/dots as word boundaries, so a new extractQuotedKey helper manually extracts the full quoted key from the line content. 2. isTrusted on field hovers: Field hover content now has isTrusted: true, making any future links in field hovers clickable. (Operator hovers already had this from a previous commit.) 3. Redesigned field hover format: - Field name bold, with 'sparse: not present in all documents' in subscript on the same line (no em-dashes) - 'Inferred Types' bold section header - Comma-separated type list (using displayTypes from all observed BSON types for polymorphic fields) Also threaded bsonTypes/displayTypes through FieldCompletionData from FieldEntry for polymorphic field support. --- .../autocomplete/toFieldCompletionItems.ts | 6 + .../documentdbQueryHoverProvider.test.ts | 51 +++++++- .../documentdbQueryHoverProvider.ts | 28 ++-- .../documentdbQuery/extractQuotedKey.test.ts | 79 ++++++++++++ .../documentdbQuery/registerLanguage.ts | 122 +++++++++++++++++- 5 files changed, 266 insertions(+), 20 deletions(-) create mode 100644 src/webviews/documentdbQuery/extractQuotedKey.test.ts diff --git a/src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts b/src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts index 63e85bd92..60e299590 100644 --- a/src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts +++ b/src/utils/json/data-api/autocomplete/toFieldCompletionItems.ts @@ -23,6 +23,10 @@ export interface FieldCompletionData { displayType: string; /** Raw BSON type from FieldEntry */ bsonType: string; + /** All observed BSON types for polymorphic fields (e.g., ["string", "int32"]) */ + bsonTypes?: string[]; + /** Human-readable display strings for all observed types (e.g., ["String", "Int32"]) */ + displayTypes?: string[]; /** Whether the field was not present in every inspected document (statistical observation, not a constraint) */ isSparse: boolean; /** Text to insert when the user selects this completion — quoted/escaped if the field name contains special chars */ @@ -72,6 +76,8 @@ export function toFieldCompletionItems(fields: FieldEntry[]): FieldCompletionDat fieldName: entry.path, displayType, bsonType: entry.bsonType, + bsonTypes: entry.bsonTypes, + displayTypes: entry.bsonTypes?.map((t) => BSONTypes.toDisplayString(t as BSONTypes)), isSparse: entry.isSparse ?? false, insertText, referenceText: `$${entry.path}`, diff --git a/src/webviews/documentdbQuery/documentdbQueryHoverProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryHoverProvider.test.ts index a157c06e2..0807cceaf 100644 --- a/src/webviews/documentdbQuery/documentdbQueryHoverProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryHoverProvider.test.ts @@ -28,7 +28,6 @@ describe('documentdbQueryHoverProvider', () => { const content = (hover!.contents[0] as { value: string }).value; expect(content).toContain('**$eq**'); - // It should have a description line expect(content.split('\n').length).toBeGreaterThan(1); }); @@ -51,7 +50,6 @@ describe('documentdbQueryHoverProvider', () => { }); test('word without $ prefix matches operator when prefixed', () => { - // When cursor is on "gt" (after $ was already output), try $gt const hover = getHoverContent('gt'); expect(hover).not.toBeNull(); @@ -64,10 +62,17 @@ describe('documentdbQueryHoverProvider', () => { expect(hover).not.toBeNull(); const content = (hover!.contents[0] as { value: string }).value; - // $gt is a well-known operator that should have a doc link expect(content).toContain('[DocumentDB Docs]'); }); + test('operator hover has isTrusted set for clickable links', () => { + const hover = getHoverContent('$gt'); + expect(hover).not.toBeNull(); + + const hoverContent = hover!.contents[0] as { isTrusted?: boolean }; + expect(hoverContent.isTrusted).toBe(true); + }); + test('returns hover for UUID constructor', () => { const hover = getHoverContent('UUID'); expect(hover).not.toBeNull(); @@ -95,6 +100,16 @@ describe('documentdbQueryHoverProvider', () => { insertText: 'nickname', referenceText: '$nickname', }, + { + fieldName: 'rating', + displayType: 'Double', + bsonType: 'double', + bsonTypes: ['double', 'int32'], + displayTypes: ['Double', 'Int32'], + isSparse: true, + insertText: 'rating', + referenceText: '$rating', + }, ]; test('returns hover for a known field name', () => { @@ -103,17 +118,35 @@ describe('documentdbQueryHoverProvider', () => { const content = (hover!.contents[0] as { value: string }).value; expect(content).toContain('**age**'); + }); + + test('shows "Inferred Types" section with type list', () => { + const hover = getHoverContent('age', createFieldLookup(fields)); + expect(hover).not.toBeNull(); + + const content = (hover!.contents[0] as { value: string }).value; + expect(content).toContain('**Inferred Types**'); expect(content).toContain('Number'); }); + test('shows multiple types for polymorphic fields', () => { + const hover = getHoverContent('rating', createFieldLookup(fields)); + expect(hover).not.toBeNull(); + + const content = (hover!.contents[0] as { value: string }).value; + expect(content).toContain('**Inferred Types**'); + expect(content).toContain('Double'); + expect(content).toContain('Int32'); + }); + test('shows sparse indicator for sparse fields', () => { const hover = getHoverContent('nickname', createFieldLookup(fields)); expect(hover).not.toBeNull(); const content = (hover!.contents[0] as { value: string }).value; expect(content).toContain('**nickname**'); - expect(content).toContain('String'); expect(content).toContain('sparse'); + expect(content).toContain('not present in all documents'); }); test('does NOT show sparse indicator for non-sparse fields', () => { @@ -124,13 +157,20 @@ describe('documentdbQueryHoverProvider', () => { expect(content).not.toContain('sparse'); }); + test('field hover has isTrusted set', () => { + const hover = getHoverContent('age', createFieldLookup(fields)); + expect(hover).not.toBeNull(); + + const hoverContent = hover!.contents[0] as { isTrusted?: boolean }; + expect(hoverContent.isTrusted).toBe(true); + }); + test('returns null for unknown field when no operator match', () => { const hover = getHoverContent('unknownField', createFieldLookup(fields)); expect(hover).toBeNull(); }); test('operators take priority over field names', () => { - // If a field happens to be named "gt", the operator $gt should match first const fieldsWithOperatorName: FieldCompletionData[] = [ { fieldName: 'gt', @@ -146,7 +186,6 @@ describe('documentdbQueryHoverProvider', () => { expect(hover).not.toBeNull(); const content = (hover!.contents[0] as { value: string }).value; - // Should show operator hover, not field hover expect(content).toContain('**$gt**'); }); diff --git a/src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts b/src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts index ac08bb52b..8f325f1d3 100644 --- a/src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts +++ b/src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts @@ -70,20 +70,30 @@ export function getHoverContent(word: string, fieldLookup?: FieldDataLookup): mo } /** - * Builds a hover tooltip for a field name, showing its type info. + * Builds a hover tooltip for a field name. * - * Uses relative language for statistics (e.g., "sparse" rather than - * absolute percentages) since the SchemaAnalyzer accumulates data - * across queries and the numbers are approximate. + * Format: + * ``` + * **fieldName** sparse: not present in all documents + * + * **Inferred Types** + * String, Int32 + * ``` */ function buildFieldHover(field: FieldCompletionData): monacoEditor.languages.Hover { - const lines: string[] = [`**${field.fieldName}**`]; + // First line: field name, optionally with sparse note + let header = `**${field.fieldName}**`; + if (field.isSparse) { + header += '   sparse: not present in all documents'; + } + + const lines: string[] = [header]; - // Type info - const sparseNote = field.isSparse ? ' *(sparse — not present in all documents)*' : ''; - lines.push('', `Type: \`${field.displayType}\`${sparseNote}`); + // Inferred types section + const typeList = field.displayTypes && field.displayTypes.length > 0 ? field.displayTypes : [field.displayType]; + lines.push('', '**Inferred Types**', typeList.join(', ')); return { - contents: [{ value: lines.join('\n') }], + contents: [{ value: lines.join('\n'), isTrusted: true, supportHtml: true }], }; } diff --git a/src/webviews/documentdbQuery/extractQuotedKey.test.ts b/src/webviews/documentdbQuery/extractQuotedKey.test.ts new file mode 100644 index 000000000..20239d5b9 --- /dev/null +++ b/src/webviews/documentdbQuery/extractQuotedKey.test.ts @@ -0,0 +1,79 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { extractQuotedKey } from './registerLanguage'; + +describe('extractQuotedKey', () => { + test('extracts double-quoted key when cursor is inside', () => { + const line = '{ "address.street": "value" }'; + // 01234567890123456789 + const col = 5; // on 'a' of address + const result = extractQuotedKey(line, col); + expect(result).not.toBeNull(); + expect(result!.key).toBe('address.street'); + }); + + test('extracts single-quoted key when cursor is inside', () => { + const line = "{ 'address.street': 'value' }"; + const col = 5; + const result = extractQuotedKey(line, col); + expect(result).not.toBeNull(); + expect(result!.key).toBe('address.street'); + }); + + test('returns null when cursor is not inside quotes', () => { + const line = '{ name: "value" }'; + const col = 3; // on 'a' of name (unquoted) + const result = extractQuotedKey(line, col); + expect(result).toBeNull(); + }); + + test('returns null when cursor is on a structural character', () => { + const line = '{ "key": "value" }'; + const col = 0; // on '{' + const result = extractQuotedKey(line, col); + expect(result).toBeNull(); + }); + + test('returns correct start/end for range highlighting', () => { + const line = '{ "address.street": 1 }'; + // 0123456789012345678 + const col = 10; // somewhere inside the quoted string + const result = extractQuotedKey(line, col); + expect(result).not.toBeNull(); + expect(result!.start).toBe(2); // position of opening " + expect(result!.end).toBe(18); // position after closing " + expect(result!.key).toBe('address.street'); + }); + + test('handles escaped quotes inside key', () => { + const line = '{ "key\\"name": 1 }'; + const col = 5; + const result = extractQuotedKey(line, col); + expect(result).not.toBeNull(); + expect(result!.key).toBe('key\\"name'); + }); + + test('cursor on opening quote still works', () => { + const line = '{ "address.street": 1 }'; + const col = 2; // on the opening " + const result = extractQuotedKey(line, col); + expect(result).not.toBeNull(); + expect(result!.key).toBe('address.street'); + }); + + test('cursor on closing quote still works', () => { + const line = '{ "address.street": 1 }'; + const col = 17; // on the closing " + const result = extractQuotedKey(line, col); + expect(result).not.toBeNull(); + expect(result!.key).toBe('address.street'); + }); + + test('returns null for empty line', () => { + const result = extractQuotedKey('', 0); + expect(result).toBeNull(); + }); +}); diff --git a/src/webviews/documentdbQuery/registerLanguage.ts b/src/webviews/documentdbQuery/registerLanguage.ts index 1d9c7feff..7ec65febb 100644 --- a/src/webviews/documentdbQuery/registerLanguage.ts +++ b/src/webviews/documentdbQuery/registerLanguage.ts @@ -147,11 +147,6 @@ async function doRegisterLanguage(monaco: typeof monacoEditor): Promise { model: monacoEditor.editor.ITextModel, position: monacoEditor.Position, ): monacoEditor.languages.Hover | null => { - const wordAtPosition = model.getWordAtPosition(position); - if (!wordAtPosition) { - return null; - } - // Build field lookup from completion store for field hover info const uriString = model.uri.toString(); const parsedUri = parseEditorUri(uriString); @@ -162,6 +157,35 @@ async function doRegisterLanguage(monaco: typeof monacoEditor): Promise { } : undefined; + // Try to extract a quoted string key (e.g., "address.street") + // Monaco's getWordAtPosition treats quotes and dots as word boundaries, + // so for { "address.street": 1 } hovering on "address" would only match + // "address", not the full field name "address.street". + const lineContent = model.getLineContent(position.lineNumber); + const col0 = position.column - 1; // 0-based + + const quotedResult = extractQuotedKey(lineContent, col0); + if (quotedResult) { + const hover = getHoverContent(quotedResult.key, hoverFieldLookup); + if (hover) { + return { + ...hover, + range: { + startLineNumber: position.lineNumber, + endLineNumber: position.lineNumber, + startColumn: quotedResult.start + 1, // 1-based + endColumn: quotedResult.end + 1, // 1-based + }, + }; + } + } + + // Fall back to standard word-based hover + const wordAtPosition = model.getWordAtPosition(position); + if (!wordAtPosition) { + return null; + } + const hover = getHoverContent(wordAtPosition.word, hoverFieldLookup); if (!hover) { return null; @@ -188,3 +212,91 @@ async function doRegisterLanguage(monaco: typeof monacoEditor): Promise { export function _resetRegistration(): void { registrationPromise = undefined; } + +/** + * Extracts a quoted key string if the cursor is inside one. + * + * For `{ "address.street": 1 }`, when the cursor is anywhere between the + * opening and closing quotes, returns the unquoted key `"address.street"` + * along with the 0-based start/end positions of the full quoted string + * (including the quotes themselves, for hover range highlighting). + * + * Returns null if the cursor is not inside a quoted string. + * + * @param line - the full line content + * @param col0 - 0-based column position of the cursor + */ +export function extractQuotedKey(line: string, col0: number): { key: string; start: number; end: number } | null { + if (col0 < 0 || col0 >= line.length) return null; + + // If cursor is on a quote, it could be the closing quote. + // Try treating the current position as the closing quote first. + const chAtCursor = line[col0]; + if (chAtCursor === '"' || chAtCursor === "'") { + // Not escaped? + if (col0 === 0 || line[col0 - 1] !== '\\') { + // Try to find a matching opening quote before this one + const result = tryMatchAsClosingQuote(line, col0, chAtCursor); + if (result) return result; + } + } + + // Scan backward to find the opening quote + let openQuoteIdx = -1; + let quoteChar: string | undefined; + + for (let i = col0; i >= 0; i--) { + const ch = line[i]; + if (ch === '"' || ch === "'") { + if (i > 0 && line[i - 1] === '\\') continue; + openQuoteIdx = i; + quoteChar = ch; + break; + } + if (ch === '{' || ch === '}' || ch === ':' || ch === ',') { + return null; + } + } + + if (openQuoteIdx < 0 || !quoteChar) return null; + + // Scan forward to find the closing quote + let closeQuoteIdx = -1; + for (let i = openQuoteIdx + 1; i < line.length; i++) { + if (line[i] === '\\') { + i++; + continue; + } + if (line[i] === quoteChar) { + closeQuoteIdx = i; + break; + } + } + + if (closeQuoteIdx < 0) return null; + if (col0 < openQuoteIdx || col0 > closeQuoteIdx) return null; + + const key = line.substring(openQuoteIdx + 1, closeQuoteIdx); + return { key, start: openQuoteIdx, end: closeQuoteIdx + 1 }; +} + +function tryMatchAsClosingQuote( + line: string, + closeIdx: number, + quoteChar: string, +): { key: string; start: number; end: number } | null { + // Scan backward from before the closing quote to find the opening quote + for (let i = closeIdx - 1; i >= 0; i--) { + if (line[i] === '\\') continue; + if (line[i] === quoteChar) { + if (i > 0 && line[i - 1] === '\\') continue; + const key = line.substring(i + 1, closeIdx); + return { key, start: i, end: closeIdx + 1 }; + } + // Stop at structural chars + if (line[i] === '{' || line[i] === '}' || line[i] === ':' || line[i] === ',') { + return null; + } + } + return null; +} From c6f69019875d46470bc202daf73725bf877830e2 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Wed, 18 Mar 2026 12:56:18 +0000 Subject: [PATCH 102/128] test: add operator category coverage tests by position MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added tests verifying that operator categories appear at the correct completion positions: - Key position: only logical combinators ($and, $or, $nor) and meta operators ($comment, $expr, etc.) — no field-level operators - Value position: all field-level categories — comparison ($gt, $eq), evaluation ($regex), element ($exists, $type), array ($all, $elemMatch, $size), and field-level $not - Operator position: same as value position This confirms $all is correctly excluded from key position (it's a field-level array operator: { tags: { $all: [...] } }), not a root-level query combinator. --- .../documentdbQueryCompletionProvider.test.ts | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index fe61caffe..00f8b509b 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -1396,6 +1396,84 @@ describe('documentdbQueryCompletionProvider', () => { expect(andItem?.insertText).toContain('}'); }); }); + + // --------------------------------------------------------------- + // Category coverage: verify operator categories at each position + // --------------------------------------------------------------- + describe('operator category coverage by position', () => { + test('key position: only key-position operators, no field-level operators', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: { position: 'key', depth: 1 }, + }); + + const labels = items.map((i) => getLabelText(i.label)); + // Key-position: logical combinators and meta operators + expect(labels).toContain('$and'); // query:logical + expect(labels).toContain('$or'); // query:logical + expect(labels).toContain('$nor'); // query:logical + expect(labels).toContain('$comment'); // query:comment + expect(labels).toContain('$expr'); // query:expr + // Field-level operators must NOT appear at key position + expect(labels).not.toContain('$all'); // query:array — field-level + expect(labels).not.toContain('$elemMatch'); // query:array — field-level + expect(labels).not.toContain('$size'); // query:array — field-level + expect(labels).not.toContain('$gt'); // query:comparison + expect(labels).not.toContain('$regex'); // query:evaluation + expect(labels).not.toContain('$exists'); // query:element + expect(labels).not.toContain('$not'); // query:logical — field-level + }); + + test('value position: includes operators from all field-level categories', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: { position: 'value', fieldName: 'x' }, + }); + + const labels = items.map((i) => getLabelText(i.label)); + // Should include field-level operators from every category + expect(labels).toContain('$gt'); // query:comparison + expect(labels).toContain('$eq'); // query:comparison + expect(labels).toContain('$in'); // query:comparison + expect(labels).toContain('$regex'); // query:evaluation + expect(labels).toContain('$exists'); // query:element + expect(labels).toContain('$type'); // query:element + expect(labels).toContain('$all'); // query:array + expect(labels).toContain('$elemMatch'); // query:array + expect(labels).toContain('$size'); // query:array + expect(labels).toContain('$not'); // query:logical (field-level) + // Key-position operators should NOT be at value position + expect(labels).not.toContain('$and'); + expect(labels).not.toContain('$or'); + }); + + test('operator position: same field-level categories as value position', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: { position: 'operator', fieldName: 'x' }, + }); + + const labels = items.map((i) => getLabelText(i.label)); + expect(labels).toContain('$gt'); // query:comparison + expect(labels).toContain('$regex'); // query:evaluation + expect(labels).toContain('$exists'); // query:element + expect(labels).toContain('$all'); // query:array + expect(labels).toContain('$not'); // query:logical (field-level) + expect(labels).not.toContain('$and'); // key-position only + }); + }); }); // --------------------------------------------------------------- From 2a7f1df7433f36ab8f60e599034ba6d28a2f60a4 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Wed, 18 Mar 2026 13:14:25 +0000 Subject: [PATCH 103/128] feat: smart-trigger completions after ': ' and ', ' patterns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a field completion inserts 'rating: ', the completion popup did not reappear for the value position. Now, typing a space after ':' or ',' triggers the suggestion popup after 50ms. This provides a smooth autocomplete flow: select field → space → see value suggestions. Implemented via onDidChangeModelContent listener that detects single-space insertions preceded by ':' or ',' and programmatically calls editor.action.triggerSuggest. Wired into all three editors (filter, project, sort) with proper cleanup. --- .../components/queryEditor/QueryEditor.tsx | 60 +++++ .../documentdbQueryCompletionProvider.test.ts | 248 ++++++++++++++++++ 2 files changed, 308 insertions(+) diff --git a/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx b/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx index 709c883e2..c15d3bc31 100644 --- a/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx +++ b/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx @@ -131,10 +131,56 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element }; }; + /** + * Sets up pattern-based auto-trigger of completions. + * When the user types a space after `: ` or `, `, completions are + * triggered automatically after a short delay. This bridges the gap + * where selecting a field completion (e.g., `rating`) inserts `rating: ` + * but the completion popup doesn't reappear for the value. + * + * Returns a cleanup function. + */ + const setupSmartTrigger = (editor: monacoEditor.editor.IStandaloneCodeEditor): (() => void) => { + let triggerTimeout: ReturnType; + const disposable = editor.onDidChangeModelContent((e) => { + clearTimeout(triggerTimeout); + + // Only fire for single-character insertions (typing) + const change = e.changes[0]; + if (!change || change.text !== ' ') return; + + // Check the two characters ending at the cursor: "X " where X is : or , + const model = editor.getModel(); + if (!model) return; + + const offset = model.getOffsetAt( + // The position after the inserted space + model.getPositionAt(change.rangeOffset + 1), + ); + + // We need at least 2 chars: the trigger char + space + if (offset < 2) return; + + const textBefore = model.getValue().substring(offset - 2, offset); + if (textBefore === ': ' || textBefore === ', ') { + triggerTimeout = setTimeout(() => { + editor.trigger('smart-trigger', 'editor.action.triggerSuggest', {}); + }, 50); + } + }); + return () => { + clearTimeout(triggerTimeout); + disposable.dispose(); + }; + }; + // Track validation cleanup functions const filterValidationCleanupRef = useRef<(() => void) | null>(null); const projectValidationCleanupRef = useRef<(() => void) | null>(null); const sortValidationCleanupRef = useRef<(() => void) | null>(null); + const filterSmartTriggerCleanupRef = useRef<(() => void) | null>(null); + const projectSmartTriggerCleanupRef = useRef<(() => void) | null>(null); + const sortSmartTriggerCleanupRef = useRef<(() => void) | null>(null); const handleEditorDidMount = (editor: monacoEditor.editor.IStandaloneCodeEditor, monaco: typeof monacoEditor) => { // Store the filter editor reference @@ -149,6 +195,9 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element // Set up debounced validation filterValidationCleanupRef.current = setupValidation(editor, monaco, model); + // Set up smart-trigger for completions after ": " and ", " + filterSmartTriggerCleanupRef.current = setupSmartTrigger(editor); + const getCurrentQueryFunction = () => ({ filter: filterValue, project: projectValue, @@ -202,6 +251,11 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element projectValidationCleanupRef.current?.(); sortValidationCleanupRef.current?.(); + // Clean up smart-trigger listeners + filterSmartTriggerCleanupRef.current?.(); + projectSmartTriggerCleanupRef.current?.(); + sortSmartTriggerCleanupRef.current?.(); + // Dispose Monaco models filterEditorRef.current?.getModel()?.dispose(); projectEditorRef.current?.getModel()?.dispose(); @@ -552,6 +606,9 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element // Set up validation projectValidationCleanupRef.current = setupValidation(editor, monaco, model); + // Set up smart-trigger + projectSmartTriggerCleanupRef.current = setupSmartTrigger(editor); + editor.onDidChangeModelContent(() => { setProjectValue(editor.getValue()); }); @@ -592,6 +649,9 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element // Set up validation sortValidationCleanupRef.current = setupValidation(editor, monaco, model); + // Set up smart-trigger + sortSmartTriggerCleanupRef.current = setupSmartTrigger(editor); + editor.onDidChangeModelContent(() => { setSortValue(editor.getValue()); }); diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index 00f8b509b..040eaa504 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -1777,4 +1777,252 @@ describe('documentdbQueryCompletionProvider', () => { expect(ascItem?.preselect).toBe(true); }); }); + + // --------------------------------------------------------------- + // Category-based completion coverage by cursor position + // --------------------------------------------------------------- + describe('completion categories by cursor position', () => { + const mockMonaco = createMockMonaco(); + + /** + * Helper: extracts the description (category label) from a CompletionItem. + * For operator items this is getCategoryLabel(meta), e.g., "comparison", "array". + * For JS globals it is "JS global". + * For fields it is the type, e.g., "Number". + */ + function getDescription( + label: string | monacoEditor.languages.CompletionItemLabel, + ): string | undefined { + return typeof label === 'string' ? undefined : label.description; + } + + /** Returns Set of distinct category descriptions from a completion list. */ + function getCategories(items: monacoEditor.languages.CompletionItem[]): Set { + const categories = new Set(); + for (const item of items) { + const desc = getDescription(item.label); + if (desc) categories.add(desc); + } + return categories; + } + + describe('key position ({ })', () => { + const keyContext: CursorContext = { position: 'key', depth: 1 }; + + test('includes "logical" category operators', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: keyContext, + }); + + const categories = getCategories(items); + expect(categories.has('logical')).toBe(true); + }); + + test('does NOT include field-level categories (comparison, array, evaluation, element)', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: keyContext, + }); + + const categories = getCategories(items); + expect(categories.has('comparison')).toBe(false); + expect(categories.has('array')).toBe(false); + expect(categories.has('evaluation')).toBe(false); + expect(categories.has('element')).toBe(false); + }); + + test('does NOT include "bson" or "JS global"', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: keyContext, + }); + + const categories = getCategories(items); + expect(categories.has('bson')).toBe(false); + expect(categories.has('JS global')).toBe(false); + }); + }); + + describe('value position ({ field: })', () => { + const valueContext: CursorContext = { position: 'value', fieldName: 'x' }; + + test('includes field-level categories: comparison, array, evaluation, element', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: valueContext, + }); + + const categories = getCategories(items); + expect(categories.has('comparison')).toBe(true); + expect(categories.has('array')).toBe(true); + expect(categories.has('evaluation')).toBe(true); + expect(categories.has('element')).toBe(true); + }); + + test('includes "bson" and "JS global"', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: valueContext, + }); + + const categories = getCategories(items); + expect(categories.has('bson')).toBe(true); + expect(categories.has('JS global')).toBe(true); + }); + + test('does NOT include key-position-only operators', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: valueContext, + }); + + const labels = items.map((i) => getLabelText(i.label)); + expect(labels).not.toContain('$and'); + expect(labels).not.toContain('$or'); + expect(labels).not.toContain('$nor'); + }); + }); + + describe('operator position ({ field: { } })', () => { + const operatorContext: CursorContext = { position: 'operator', fieldName: 'x' }; + + test('includes field-level categories: comparison, array, evaluation, element', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: operatorContext, + }); + + const categories = getCategories(items); + expect(categories.has('comparison')).toBe(true); + expect(categories.has('array')).toBe(true); + expect(categories.has('evaluation')).toBe(true); + expect(categories.has('element')).toBe(true); + }); + + test('does NOT include "bson", "JS global", or key-position operators', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: operatorContext, + }); + + const categories = getCategories(items); + expect(categories.has('bson')).toBe(false); + expect(categories.has('JS global')).toBe(false); + + const labels = items.map((i) => getLabelText(i.label)); + expect(labels).not.toContain('$and'); + expect(labels).not.toContain('$or'); + }); + }); + + describe('unknown position (empty editor / no context)', () => { + const unknownContext: CursorContext = { position: 'unknown' }; + + test('includes key-position "logical" category', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: unknownContext, + }); + + const categories = getCategories(items); + expect(categories.has('logical')).toBe(true); + }); + + test('does NOT include field-level categories (comparison, array, evaluation, element)', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: unknownContext, + }); + + const categories = getCategories(items); + expect(categories.has('comparison')).toBe(false); + expect(categories.has('array')).toBe(false); + expect(categories.has('evaluation')).toBe(false); + expect(categories.has('element')).toBe(false); + }); + + test('does NOT include "bson" or "JS global"', () => { + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: unknownContext, + }); + + const categories = getCategories(items); + expect(categories.has('bson')).toBe(false); + expect(categories.has('JS global')).toBe(false); + }); + + test('includes field names if store has data', () => { + setCompletionContext('test-session', { + fields: [ + { + fieldName: 'name', + displayType: 'String', + bsonType: 'string', + isSparse: false, + insertText: 'name', + referenceText: '$name', + }, + ], + }); + + const items = createCompletionItems({ + editorType: EditorType.Filter, + sessionId: 'test-session', + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: unknownContext, + }); + + const labels = items.map((i) => getLabelText(i.label)); + expect(labels).toContain('name'); + }); + }); + }); }); From 8bfe0fbd0a454bf7c8851ea672682b2d2e64ebfb Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Wed, 18 Mar 2026 13:17:38 +0000 Subject: [PATCH 104/128] fix: make hover tooltip documentation links clickable in webview Monaco renders hover markdown links as tags, but the webview CSP blocks direct navigation to external URLs. Added a delegated click handler on the query editor container that intercepts clicks with http/https hrefs and routes them through the existing trpcClient.common.openUrl mutation, which calls vscode.env.openExternal on the extension host side. --- .../components/queryEditor/QueryEditor.tsx | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx b/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx index c15d3bc31..5da1d2672 100644 --- a/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx +++ b/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx @@ -238,6 +238,31 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element automaticLayout: false, }; + // Intercept link clicks in Monaco hover tooltips. + // Monaco renders hover markdown links as tags, but the webview CSP + // blocks direct navigation. Capture clicks and route through tRPC. + const editorContainerRef = useRef(null); + useEffect(() => { + const container = editorContainerRef.current; + if (!container) return; + + const handleLinkClick = (e: MouseEvent): void => { + const target = e.target as HTMLElement; + const anchor = target.closest('a'); + if (!anchor) return; + + const href = anchor.getAttribute('href'); + if (href && (href.startsWith('https://') || href.startsWith('http://'))) { + e.preventDefault(); + e.stopPropagation(); + void trpcClient.common.openUrl.mutate({ url: href }); + } + }; + + container.addEventListener('click', handleLinkClick, true); + return () => container.removeEventListener('click', handleLinkClick, true); + }, [trpcClient]); + // Cleanup any pending operations when component unmounts useEffect(() => { return () => { @@ -421,7 +446,7 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element }; return ( -
+
{/* Optional AI prompt row */}
From 053b184a879c1475775a89ec96bb188e3f56b572 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Wed, 18 Mar 2026 13:20:36 +0000 Subject: [PATCH 105/128] style: apply prettier formatting to completion tests --- .../documentdbQuery/documentdbQueryCompletionProvider.test.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index 040eaa504..43f111f87 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -1790,9 +1790,7 @@ describe('documentdbQueryCompletionProvider', () => { * For JS globals it is "JS global". * For fields it is the type, e.g., "Number". */ - function getDescription( - label: string | monacoEditor.languages.CompletionItemLabel, - ): string | undefined { + function getDescription(label: string | monacoEditor.languages.CompletionItemLabel): string | undefined { return typeof label === 'string' ? undefined : label.description; } From 769b045bde1ac425ae2df64272e3ce35c468d3fa Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Wed, 18 Mar 2026 14:55:23 +0000 Subject: [PATCH 106/128] =?UTF-8?q?feat:=20split=20EMPTY=20from=20UNKNOWN?= =?UTF-8?q?=20context=20=E2=80=94=20TDD=20behavior=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit EMPTY editor (no braces) now shows key-position completions (fields + root operators) with { } wrapping, instead of showing all operators. UNKNOWN context remains as the full discovery fallback. Changes: - createCompletionItems: route needsWrapping+unknown to new createEmptyEditorCompletions (key-position items with wrapping) - createAllCompletions: now pure UNKNOWN fallback (no needsWrapping param) - New tdd/ folder with behavior spec (readme.completionBehavior.md) and 26 category-based TDD tests verifying the completion matrix - Updated existing category tests: KEY position allows 'evaluation' (because $expr/$text are key-position operators), UNKNOWN now shows everything - Updated completions/README.md: added Empty position, fixed flow docs The TDD tests check categories (from description label) and sortText prefixes, not specific operator names, for resilience to documentdb-constants changes. --- .../documentdbQuery/completions/README.md | 13 +- .../completions/createCompletionItems.ts | 64 ++- .../documentdbQueryCompletionProvider.test.ts | 46 +- src/webviews/documentdbQuery/tdd/README.md | 33 ++ .../tdd/completionBehavior.test.ts | 526 ++++++++++++++++++ .../tdd/readme.completionBehavior.md | 135 +++++ 6 files changed, 762 insertions(+), 55 deletions(-) create mode 100644 src/webviews/documentdbQuery/tdd/README.md create mode 100644 src/webviews/documentdbQuery/tdd/completionBehavior.test.ts create mode 100644 src/webviews/documentdbQuery/tdd/readme.completionBehavior.md diff --git a/src/webviews/documentdbQuery/completions/README.md b/src/webviews/documentdbQuery/completions/README.md index 0e7277ec8..bb060d369 100644 --- a/src/webviews/documentdbQuery/completions/README.md +++ b/src/webviews/documentdbQuery/completions/README.md @@ -26,12 +26,22 @@ registerLanguage.ts - **key / array-element** → field names + key-position operators - **value** → type suggestions + operators (with braces) + BSON constructors + JS globals - **operator** → operators only (braces stripped, type-aware sorting) - - **unknown / undefined** → all completions (fields, all operators, BSON constructors, JS globals) + - **empty** (unknown + needsWrapping) → key-position completions with `{ }` wrapping + - **unknown** (ambiguous, no wrapping) → all completions (fields, all operators, BSON constructors, JS globals) ## Sorting Completion items use `sortText` prefixes so Monaco displays them in the intended order. Lower prefixes appear higher in the list. +### Empty position (no braces) + +Same as key position. All insertions wrapped with `{ }`. + +| Prefix | Content | Example | +|--------|---------|---------| +| `0_fieldName` | Schema field names (wrapped) | `{ age: $1 }`, `{ name: $1 }` | +| `1_$and` | Key-position operators (with braces) | `{ $and: [...] }` | + ### Value position | Prefix | Content | Example | @@ -93,6 +103,7 @@ Curated domain rules that go beyond the auto-generated operator registry in `doc Operator snippets in `documentdb-constants` include outer braces: `{ $gt: ${1:value} }`. +- **Empty position**: operators keep full braces (user has no braces); fields wrapped with `{ ... }` - **Value position**: inserted as-is (user is replacing the entire value) - **Operator position**: outer `{ }` stripped via `stripOuterBraces()` (user is already inside braces) - **Key position**: outer `{ }` stripped (user is already inside the query object) diff --git a/src/webviews/documentdbQuery/completions/createCompletionItems.ts b/src/webviews/documentdbQuery/completions/createCompletionItems.ts index a9fba4e44..1c0bd9948 100644 --- a/src/webviews/documentdbQuery/completions/createCompletionItems.ts +++ b/src/webviews/documentdbQuery/completions/createCompletionItems.ts @@ -91,16 +91,21 @@ export function getMetaTagsForEditorType(editorType: EditorType | undefined): re * - **value**: type suggestions + operators (with braces) + BSON constructors * - **operator**: operators (without braces) with type-aware sorting * - **array-element**: same as key position - * - **unknown / undefined**: all completions — fields, all operators, BSON - * constructors, and JS globals (backward-compatible fallback) + * - **empty** (unknown + needsWrapping): key-position completions with `{ }` wrapping + * - **unknown** (ambiguous): all completions — full discovery fallback */ export function createCompletionItems(params: CreateCompletionItemsParams): monacoEditor.languages.CompletionItem[] { const { editorType, sessionId, range, monaco, fieldBsonTypes, cursorContext, needsWrapping } = params; if (!cursorContext || cursorContext.position === 'unknown') { - // When context is unknown (e.g., empty input, no braces), show all - // completions so the user can discover what's available. - return createAllCompletions(editorType, sessionId, range, monaco, needsWrapping); + if (needsWrapping) { + // EMPTY editor — no braces present. Show key-position completions + // (fields + root operators) with { } wrapping so inserted items + // produce valid syntax. + return createEmptyEditorCompletions(editorType, sessionId, range, monaco); + } + // Genuinely UNKNOWN — show all completions as a discovery fallback. + return createAllCompletions(editorType, sessionId, range, monaco); } switch (cursorContext.position) { @@ -126,30 +131,53 @@ export function createCompletionItems(params: CreateCompletionItemsParams): mona // ---------- Context-specific completion builders ---------- /** - * All completions — used when cursor context is unknown or undefined. - * Shows fields, all operators, BSON constructors, and JS globals. + * Empty editor completions — shows key-position items with `{ }` wrapping. * - * When `needsWrapping` is true, field insertText is wrapped with `{ ... }` - * to produce valid syntax in an empty editor. + * Used when the editor has no braces (user cleared content). Behaves like + * key position but wraps all inserted completions with outer `{ }` so they + * produce valid query syntax. + */ +function createEmptyEditorCompletions( + editorType: EditorType | undefined, + sessionId: string | undefined, + range: monacoEditor.IRange, + monaco: typeof monacoEditor, +): monacoEditor.languages.CompletionItem[] { + const metaTags = getMetaTagsForEditorType(editorType); + const allEntries = getFilteredCompletions({ meta: [...metaTags] }); + + // Key-position operators — keep outer braces (don't strip) + const keyEntries = allEntries.filter((e) => KEY_POSITION_OPERATORS.has(e.value)); + const operatorItems = keyEntries.map((entry) => { + const item = mapOperatorToCompletionItem(entry, range, monaco); + item.sortText = `1_${entry.value}`; + return item; + }); + + // Fields — wrap insertText with `{ ... }` for valid syntax + const fieldItems = getFieldCompletionItems(sessionId, range, monaco).map((item) => ({ + ...item, + insertText: `{ ${item.insertText as string} }`, + })); + + return [...fieldItems, ...operatorItems]; +} + +/** + * All completions — used when cursor context is genuinely ambiguous (UNKNOWN). + * Shows fields, all operators, BSON constructors, and JS globals. + * Full discovery fallback for positions the parser can't classify. */ function createAllCompletions( editorType: EditorType | undefined, sessionId: string | undefined, range: monacoEditor.IRange, monaco: typeof monacoEditor, - needsWrapping?: boolean, ): monacoEditor.languages.CompletionItem[] { const metaTags = getMetaTagsForEditorType(editorType); const allEntries = getFilteredCompletions({ meta: [...metaTags] }); - let fieldItems = getFieldCompletionItems(sessionId, range, monaco); - if (needsWrapping) { - // Wrap field insertText with { ... } for empty-editor context - fieldItems = fieldItems.map((item) => ({ - ...item, - insertText: `{ ${item.insertText as string} }`, - })); - } + const fieldItems = getFieldCompletionItems(sessionId, range, monaco); const operatorItems = allEntries .filter((e) => e.meta !== 'bson' && e.meta !== 'variable') diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index 43f111f87..9b08b1add 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -1821,7 +1821,7 @@ describe('documentdbQueryCompletionProvider', () => { expect(categories.has('logical')).toBe(true); }); - test('does NOT include field-level categories (comparison, array, evaluation, element)', () => { + test('does NOT include purely field-level categories (comparison, array, element)', () => { const items = createCompletionItems({ editorType: EditorType.Filter, sessionId: undefined, @@ -1832,10 +1832,11 @@ describe('documentdbQueryCompletionProvider', () => { }); const categories = getCategories(items); + // These categories have NO operators in KEY_POSITION_OPERATORS expect(categories.has('comparison')).toBe(false); expect(categories.has('array')).toBe(false); - expect(categories.has('evaluation')).toBe(false); expect(categories.has('element')).toBe(false); + // Note: 'evaluation' IS present because $expr, $jsonSchema, $text are key-position }); test('does NOT include "bson" or "JS global"', () => { @@ -1946,10 +1947,10 @@ describe('documentdbQueryCompletionProvider', () => { }); }); - describe('unknown position (empty editor / no context)', () => { + describe('unknown position (genuinely ambiguous — shows everything)', () => { const unknownContext: CursorContext = { position: 'unknown' }; - test('includes key-position "logical" category', () => { + test('includes all categories (full discovery fallback)', () => { const items = createCompletionItems({ editorType: EditorType.Filter, sessionId: undefined, @@ -1960,39 +1961,12 @@ describe('documentdbQueryCompletionProvider', () => { }); const categories = getCategories(items); + // UNKNOWN shows everything as discovery expect(categories.has('logical')).toBe(true); - }); - - test('does NOT include field-level categories (comparison, array, evaluation, element)', () => { - const items = createCompletionItems({ - editorType: EditorType.Filter, - sessionId: undefined, - range: testRange, - isDollarPrefix: false, - monaco: mockMonaco, - cursorContext: unknownContext, - }); - - const categories = getCategories(items); - expect(categories.has('comparison')).toBe(false); - expect(categories.has('array')).toBe(false); - expect(categories.has('evaluation')).toBe(false); - expect(categories.has('element')).toBe(false); - }); - - test('does NOT include "bson" or "JS global"', () => { - const items = createCompletionItems({ - editorType: EditorType.Filter, - sessionId: undefined, - range: testRange, - isDollarPrefix: false, - monaco: mockMonaco, - cursorContext: unknownContext, - }); - - const categories = getCategories(items); - expect(categories.has('bson')).toBe(false); - expect(categories.has('JS global')).toBe(false); + expect(categories.has('comparison')).toBe(true); + expect(categories.has('array')).toBe(true); + expect(categories.has('bson')).toBe(true); + expect(categories.has('JS global')).toBe(true); }); test('includes field names if store has data', () => { diff --git a/src/webviews/documentdbQuery/tdd/README.md b/src/webviews/documentdbQuery/tdd/README.md new file mode 100644 index 000000000..27cbe2a63 --- /dev/null +++ b/src/webviews/documentdbQuery/tdd/README.md @@ -0,0 +1,33 @@ +# TDD Behavior Tests + +This folder contains **behavior-driven TDD tests** for the `documentdb-query` +autocompletion system. These tests define the expected behavior contract — they +were written BEFORE the implementation and drive the design. + +## Important: TDD Contract + +> **⚠️ LLM/Agent Instruction:** +> These tests represent intentional behavior specifications. If a test in this +> folder fails after a code change, **do NOT automatically fix the test**. +> Instead, alert the user that a TDD behavior contract has been violated. +> The failure likely means the implementation change broke an expected behavior. +> The user must decide whether to update the test (changing the contract) or +> fix the implementation. + +## Test Files + +| File | What it tests | +|------|---------------| +| `completionBehavior.test.ts` | Which completion categories appear at each cursor position, sorting order, and snippet wrapping | + +## Specification + +See [readme.completionBehavior.md](readme.completionBehavior.md) for the full +behavior specification with ASCII art examples. + +## Why a separate folder? + +These tests verify cross-cutting **behavior** (the completion matrix), not a +single class or module. They sit at the `documentdbQuery/tdd/` level because +they test the combined output of `cursorContext`, `createCompletionItems`, +`mapCompletionItems`, and `completionKnowledge` working together. diff --git a/src/webviews/documentdbQuery/tdd/completionBehavior.test.ts b/src/webviews/documentdbQuery/tdd/completionBehavior.test.ts new file mode 100644 index 000000000..e63274e37 --- /dev/null +++ b/src/webviews/documentdbQuery/tdd/completionBehavior.test.ts @@ -0,0 +1,526 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * TDD Behavior Tests — Completion Categories by Cursor Position + * + * These tests define the expected behavior CONTRACT for the autocompletion + * system. They were written BEFORE the implementation (TDD red→green cycle) + * and verify WHAT completions appear at each cursor position, not HOW they + * are produced internally. + * + * ⚠️ LLM/Agent Instruction: + * If these tests fail after a code change, do NOT automatically fix the tests. + * Alert the user that a TDD behavior contract has been violated. The failure + * means the implementation broke expected behavior. The user must decide + * whether to update the spec or fix the implementation. + * + * Tests are category-based (not specific-operator-based) to be resilient to + * changes in documentdb-constants. Categories come from the `description` + * field in CompletionItemLabel (e.g., "comparison", "logical", "bson"). + * + * See: readme.completionBehavior.md for the full specification. + */ + +// eslint-disable-next-line import/no-internal-modules +import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; +import { clearAllCompletionContexts, setCompletionContext } from '../completionStore'; +import { type CursorContext } from '../cursorContext'; +import { createCompletionItems } from '../documentdbQueryCompletionProvider'; +import { EditorType } from '../languageConfig'; + +// ---------- Test infrastructure ---------- + +const mockCompletionItemKind: typeof monacoEditor.languages.CompletionItemKind = { + Method: 0, + Function: 1, + Constructor: 2, + Field: 3, + Variable: 4, + Class: 5, + Struct: 6, + Interface: 7, + Module: 8, + Property: 9, + Event: 10, + Operator: 11, + Unit: 12, + Value: 13, + Constant: 14, + Enum: 15, + EnumMember: 16, + Keyword: 17, + Text: 18, + Color: 19, + File: 20, + Reference: 21, + Customcolor: 22, + Folder: 23, + TypeParameter: 24, + User: 25, + Issue: 26, + Snippet: 27, +}; + +const mockInsertTextRule = { + InsertAsSnippet: 4, + KeepWhitespace: 1, + None: 0, +} as typeof monacoEditor.languages.CompletionItemInsertTextRule; + +function createMockMonaco(): typeof monacoEditor { + return { + languages: { + CompletionItemKind: mockCompletionItemKind, + CompletionItemInsertTextRule: mockInsertTextRule, + }, + } as unknown as typeof monacoEditor; +} + +const testRange: monacoEditor.IRange = { + startLineNumber: 1, + endLineNumber: 1, + startColumn: 1, + endColumn: 1, +}; + +// ---------- Helpers ---------- + +/** Extracts the description (category) from a CompletionItem label. */ +function getDescription(label: string | monacoEditor.languages.CompletionItemLabel): string | undefined { + return typeof label === 'string' ? undefined : label.description; +} + +/** Returns the set of distinct categories present in a completion list. */ +function getCategories(items: monacoEditor.languages.CompletionItem[]): Set { + const categories = new Set(); + for (const item of items) { + const desc = getDescription(item.label); + if (desc) categories.add(desc); + } + return categories; +} + +/** Returns the label text from a CompletionItem. */ +function getLabelText(label: string | monacoEditor.languages.CompletionItemLabel): string { + return typeof label === 'string' ? label : label.label; +} + +/** + * Returns all distinct sortText prefixes (the part before the underscore) + * found in a completion list. + */ +function getSortPrefixes(items: monacoEditor.languages.CompletionItem[]): Set { + const prefixes = new Set(); + for (const item of items) { + if (item.sortText) { + const underscoreIdx = item.sortText.indexOf('_'); + if (underscoreIdx > 0) { + prefixes.add(item.sortText.substring(0, underscoreIdx + 1)); + } + } + } + return prefixes; +} + +// ---------- Field data for tests ---------- + +const testFields = [ + { + fieldName: 'name', + displayType: 'String', + bsonType: 'string', + isSparse: false, + insertText: 'name', + referenceText: '$name', + }, + { + fieldName: 'age', + displayType: 'Number', + bsonType: 'int32', + isSparse: false, + insertText: 'age', + referenceText: '$age', + }, +]; + +// ---------- Key-position operator categories ---------- +// These are the categories that should appear at KEY / EMPTY positions. +// We test by category name, not specific operators, for resilience. +// (Used in assertions, not as a lookup — individual tests check specific categories.) + +// Field-level categories that should NOT appear at key/empty positions. +// These categories have NO operators in KEY_POSITION_OPERATORS. +// Note: 'logical' and 'evaluation' are shared — they have both key-position +// operators ($and/$or for logical, $expr/$text for evaluation) and field-level +// operators ($not for logical, $regex/$mod for evaluation). +const FIELD_LEVEL_ONLY_CATEGORIES = ['comparison', 'array', 'element', 'bitwise', 'geospatial']; + +// ===================================================================== +// Tests +// ===================================================================== + +describe('Completion Behavior (TDD)', () => { + const mockMonaco = createMockMonaco(); + + afterEach(() => { + clearAllCompletionContexts(); + }); + + // ----------------------------------------------------------------- + // EMPTY position — no braces in editor + // ----------------------------------------------------------------- + describe('EMPTY position (no braces, needsWrapping=true)', () => { + /** + * ┌──────────────────────────┐ + * │ | │ ← cursor, no braces + * └──────────────────────────┘ + * + * Expected: fields + key operators, all wrapped with { } + * NOT expected: comparison, array, evaluation, element, bson, JS global + */ + + function getEmptyCompletions(sessionId?: string): monacoEditor.languages.CompletionItem[] { + return createCompletionItems({ + editorType: EditorType.Filter, + sessionId, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: { position: 'unknown' }, + needsWrapping: true, + }); + } + + test('includes field names when store has data', () => { + setCompletionContext('s1', { fields: testFields }); + const items = getEmptyCompletions('s1'); + const labels = items.map((i) => getLabelText(i.label)); + expect(labels).toContain('name'); + expect(labels).toContain('age'); + }); + + test('field insertText is wrapped with { }', () => { + setCompletionContext('s1', { fields: testFields }); + const items = getEmptyCompletions('s1'); + const nameItem = items.find((i) => getLabelText(i.label) === 'name'); + expect(nameItem?.insertText).toMatch(/^\{.*\}$/); + }); + + test('includes key-position operator categories (logical)', () => { + const items = getEmptyCompletions(); + const categories = getCategories(items); + expect(categories.has('logical')).toBe(true); + }); + + test('does NOT include field-level categories', () => { + const items = getEmptyCompletions(); + const categories = getCategories(items); + for (const cat of FIELD_LEVEL_ONLY_CATEGORIES) { + expect(categories.has(cat)).toBe(false); + } + }); + + test('does NOT include "bson"', () => { + const items = getEmptyCompletions(); + const categories = getCategories(items); + expect(categories.has('bson')).toBe(false); + }); + + test('does NOT include "JS global"', () => { + const items = getEmptyCompletions(); + const categories = getCategories(items); + expect(categories.has('JS global')).toBe(false); + }); + + test('fields sort before operators (0_ < 1_)', () => { + setCompletionContext('s1', { fields: testFields }); + const items = getEmptyCompletions('s1'); + const fieldItem = items.find((i) => getLabelText(i.label) === 'name'); + const operatorItems = items.filter((i) => getDescription(i.label) === 'logical'); + expect(fieldItem?.sortText).toMatch(/^0_/); + expect(operatorItems.length).toBeGreaterThan(0); + expect(operatorItems[0]?.sortText).toMatch(/^1_/); + }); + }); + + // ----------------------------------------------------------------- + // KEY position — inside { } + // ----------------------------------------------------------------- + describe('KEY position ({ | })', () => { + /** + * ┌──────────────────────────┐ + * │ { | } │ ← cursor inside braces + * └──────────────────────────┘ + * + * Expected: fields + key operators + * NOT expected: comparison, array, evaluation, element, bson, JS global + */ + + const keyContext: CursorContext = { position: 'key', depth: 1 }; + + function getKeyCompletions(sessionId?: string): monacoEditor.languages.CompletionItem[] { + return createCompletionItems({ + editorType: EditorType.Filter, + sessionId, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: keyContext, + }); + } + + test('includes key-position operator categories', () => { + const categories = getCategories(getKeyCompletions()); + expect(categories.has('logical')).toBe(true); + }); + + test('does NOT include field-level categories', () => { + const categories = getCategories(getKeyCompletions()); + for (const cat of FIELD_LEVEL_ONLY_CATEGORIES) { + expect(categories.has(cat)).toBe(false); + } + }); + + test('does NOT include "bson" or "JS global"', () => { + const categories = getCategories(getKeyCompletions()); + expect(categories.has('bson')).toBe(false); + expect(categories.has('JS global')).toBe(false); + }); + + test('field sortText starts with 0_, operator sortText starts with 1_', () => { + setCompletionContext('s1', { fields: testFields }); + const items = getKeyCompletions('s1'); + + // Every field item should have sortText starting with 0_ + const fieldItems = items.filter((i) => getLabelText(i.label) === 'name' || getLabelText(i.label) === 'age'); + for (const item of fieldItems) { + expect(item.sortText).toMatch(/^0_/); + } + + // Every operator item should have sortText starting with 1_ + const operatorItems = items.filter((i) => { + const desc = getDescription(i.label); + return desc === 'logical' || desc === 'evaluation' || desc === 'misc'; + }); + for (const item of operatorItems) { + expect(item.sortText).toMatch(/^1_/); + } + }); + }); + + // ----------------------------------------------------------------- + // VALUE position — { field: | } + // ----------------------------------------------------------------- + describe('VALUE position ({ field: | })', () => { + /** + * ┌──────────────────────────┐ + * │ { age: | } │ ← cursor at value position + * └──────────────────────────┘ + * + * Expected: type suggestions + field-level operators + bson + JS globals + * NOT expected: key-position operators ($and, $or at root) + */ + + const valueContext: CursorContext = { position: 'value', fieldName: 'age' }; + + function getValueCompletions(): monacoEditor.languages.CompletionItem[] { + return createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: valueContext, + }); + } + + test('includes field-level categories', () => { + const categories = getCategories(getValueCompletions()); + for (const cat of FIELD_LEVEL_ONLY_CATEGORIES) { + expect(categories.has(cat)).toBe(true); + } + }); + + test('includes "bson" and "JS global"', () => { + const categories = getCategories(getValueCompletions()); + expect(categories.has('bson')).toBe(true); + expect(categories.has('JS global')).toBe(true); + }); + + test('does NOT include key-position operators by label', () => { + const labels = getValueCompletions().map((i) => getLabelText(i.label)); + // Check just a couple representative key operators + expect(labels).not.toContain('$and'); + expect(labels).not.toContain('$or'); + }); + + test('sort order: operators (0_) before bson (3_) before JS globals (4_)', () => { + const prefixes = getSortPrefixes(getValueCompletions()); + expect(prefixes.has('0_')).toBe(true); + expect(prefixes.has('3_')).toBe(true); + expect(prefixes.has('4_')).toBe(true); + }); + + test('project editor shows only 1/0 at value position', () => { + const items = createCompletionItems({ + editorType: EditorType.Project, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: valueContext, + }); + expect(items).toHaveLength(2); + const labels = items.map((i) => getLabelText(i.label)); + expect(labels).toContain('1'); + expect(labels).toContain('0'); + }); + + test('sort editor shows only 1/-1 at value position', () => { + const items = createCompletionItems({ + editorType: EditorType.Sort, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: valueContext, + }); + expect(items).toHaveLength(2); + const labels = items.map((i) => getLabelText(i.label)); + expect(labels).toContain('1'); + expect(labels).toContain('-1'); + }); + }); + + // ----------------------------------------------------------------- + // OPERATOR position — { field: { | } } + // ----------------------------------------------------------------- + describe('OPERATOR position ({ field: { | } })', () => { + /** + * ┌──────────────────────────┐ + * │ { age: { | } } │ ← cursor inside operator object + * └──────────────────────────┘ + * + * Expected: field-level operators (braces stripped) + * NOT expected: bson, JS global, key-position operators + */ + + const operatorContext: CursorContext = { position: 'operator', fieldName: 'age' }; + + function getOperatorCompletions(): monacoEditor.languages.CompletionItem[] { + return createCompletionItems({ + editorType: EditorType.Filter, + sessionId: undefined, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: operatorContext, + }); + } + + test('includes field-level categories', () => { + const categories = getCategories(getOperatorCompletions()); + for (const cat of FIELD_LEVEL_ONLY_CATEGORIES) { + expect(categories.has(cat)).toBe(true); + } + }); + + test('does NOT include "bson" or "JS global"', () => { + const categories = getCategories(getOperatorCompletions()); + expect(categories.has('bson')).toBe(false); + expect(categories.has('JS global')).toBe(false); + }); + + test('does NOT include key-position operators', () => { + const labels = getOperatorCompletions().map((i) => getLabelText(i.label)); + expect(labels).not.toContain('$and'); + expect(labels).not.toContain('$or'); + }); + }); + + // ----------------------------------------------------------------- + // ARRAY-ELEMENT position — { $and: [|] } + // ----------------------------------------------------------------- + describe('ARRAY-ELEMENT position ({ $and: [|] })', () => { + /** + * Same behavior as KEY position + */ + + const arrayContext: CursorContext = { position: 'array-element', parentOperator: '$and' }; + + function getArrayElementCompletions(sessionId?: string): monacoEditor.languages.CompletionItem[] { + return createCompletionItems({ + editorType: EditorType.Filter, + sessionId, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: arrayContext, + }); + } + + test('behaves like KEY: includes logical, excludes field-level categories', () => { + const categories = getCategories(getArrayElementCompletions()); + expect(categories.has('logical')).toBe(true); + for (const cat of FIELD_LEVEL_ONLY_CATEGORIES) { + expect(categories.has(cat)).toBe(false); + } + }); + + test('includes fields when store has data', () => { + setCompletionContext('s1', { fields: testFields }); + const labels = getArrayElementCompletions('s1').map((i) => getLabelText(i.label)); + expect(labels).toContain('name'); + }); + }); + + // ----------------------------------------------------------------- + // UNKNOWN position — genuinely ambiguous (show everything) + // ----------------------------------------------------------------- + describe('UNKNOWN position (ambiguous, needsWrapping=false)', () => { + /** + * Genuinely unknown cursor position. Show everything as discovery. + * This is the fallback when the parser can't determine position AND + * the editor is not empty (has some content with braces but ambiguous). + */ + + function getUnknownCompletions(sessionId?: string): monacoEditor.languages.CompletionItem[] { + return createCompletionItems({ + editorType: EditorType.Filter, + sessionId, + range: testRange, + isDollarPrefix: false, + monaco: mockMonaco, + cursorContext: { position: 'unknown' }, + needsWrapping: false, + }); + } + + test('includes key-position categories', () => { + const categories = getCategories(getUnknownCompletions()); + expect(categories.has('logical')).toBe(true); + }); + + test('includes field-level categories (full discovery)', () => { + const categories = getCategories(getUnknownCompletions()); + for (const cat of FIELD_LEVEL_ONLY_CATEGORIES) { + expect(categories.has(cat)).toBe(true); + } + }); + + test('includes "bson" and "JS global"', () => { + const categories = getCategories(getUnknownCompletions()); + expect(categories.has('bson')).toBe(true); + expect(categories.has('JS global')).toBe(true); + }); + + test('includes fields when store has data', () => { + setCompletionContext('s1', { fields: testFields }); + const labels = getUnknownCompletions('s1').map((i) => getLabelText(i.label)); + expect(labels).toContain('name'); + }); + }); +}); diff --git a/src/webviews/documentdbQuery/tdd/readme.completionBehavior.md b/src/webviews/documentdbQuery/tdd/readme.completionBehavior.md new file mode 100644 index 000000000..575f4f9f8 --- /dev/null +++ b/src/webviews/documentdbQuery/tdd/readme.completionBehavior.md @@ -0,0 +1,135 @@ +# Completion Behavior Specification + +> **⚠️ LLM/Agent Instruction:** +> This specification defines the expected completion behavior contract. +> If tests based on this spec fail after a code change, **do NOT automatically +> fix the tests**. Alert the user that a TDD behavior contract has been violated. +> The user must decide whether the behavior change is intentional. + +## Cursor Positions & Expected Completions + +The completion system shows different items depending on the cursor's semantic +position within a query expression. This spec defines what categories appear, +their sort order, and how snippets are wrapped at each position. + +### Categories + +Completions are grouped by category (shown as the `description` field in the +completion item label). The categories come from the operator's `meta` tag: + +| Category | Source | Example operators | +|----------|--------|-------------------| +| `logical` | `query:logical` | `$and`, `$or`, `$nor` | +| `comparison` | `query:comparison` | `$eq`, `$gt`, `$in` | +| `array` | `query:array` | `$all`, `$elemMatch`, `$size` | +| `evaluation` | `query:evaluation` | `$regex`, `$mod` | +| `element` | `query:element` | `$exists`, `$type` | +| `bson` | `bson` | `ObjectId`, `UUID`, `ISODate` | +| `JS global` | (hardcoded) | `Date`, `Math`, `RegExp` | +| (field type) | field data | `String`, `Number`, etc. | + +### Position: EMPTY (no braces in editor) + +``` +┌──────────────────────────┐ +│ | │ ← cursor, editor has no braces +└──────────────────────────┘ +``` + +**Shows:** Fields + key-position operators only (same items as KEY) +**Wrapping:** All insertions wrapped with `{ ... }` +**Sort:** `0_` fields, `1_` key operators + +``` +Expected completions: + name String ← field, inserts: { name: $1 } + age Number ← field, inserts: { age: $1 } + $and logical ← key operator, inserts: { $and: [...] } + $or logical ← key operator + $nor logical ← key operator + +NOT shown: + $gt comparison ← field-level, invalid at root + $all array ← field-level, invalid at root + ObjectId bson ← not valid at root key position + Date JS global ← not valid at root key position +``` + +### Position: KEY (`{ | }`) + +``` +┌──────────────────────────┐ +│ { | } │ ← cursor inside braces +└──────────────────────────┘ +``` + +**Shows:** Fields + key-position operators +**Wrapping:** None (already inside braces) +**Sort:** `0_` fields, `1_` key operators +**Snippets:** Outer `{ }` stripped from operator snippets + +``` +NOT shown: comparison, array, evaluation, element, bson, JS global +``` + +### Position: VALUE (`{ field: | }`) + +``` +┌──────────────────────────┐ +│ { age: | } │ ← cursor at value position +└──────────────────────────┘ +``` + +**Shows:** Type suggestions + field-level operators + BSON constructors + JS globals +**Sort:** `00_` type suggestions, `0_`–`2_` operators, `3_` BSON, `4_` JS globals +**Special:** Project editor → `1`/`0` only. Sort editor → `1`/`-1` only. + +``` +Shown categories: comparison, array, evaluation, element, logical ($not), bson, JS global +NOT shown: key-position operators ($and, $or, $nor at root) +``` + +### Position: OPERATOR (`{ field: { | } }`) + +``` +┌──────────────────────────┐ +│ { age: { | } } │ ← cursor inside operator object +└──────────────────────────┘ +``` + +**Shows:** Field-level operators only (braces stripped) +**Sort:** `0_` type-relevant, `1a_` comparison, `1b_` other universal, `2_` non-matching +**Snippets:** Outer `{ }` stripped + +``` +Shown categories: comparison, array, evaluation, element, logical ($not) +NOT shown: bson, JS global, key-position operators +``` + +### Position: ARRAY-ELEMENT (`{ $and: [|] }`) + +**Shows:** Same as KEY position +**Sort:** Same as KEY position + +### Position: UNKNOWN (genuinely ambiguous) + +**Shows:** ALL completions (fields + all operators + BSON + JS globals) +**Purpose:** Discovery fallback for positions the parser can't classify + +``` +Shown: everything — logical, comparison, array, evaluation, element, bson, JS global +``` + +## Sort Order Contract + +Each position has a defined sort prefix hierarchy. Items with lower prefixes +appear higher in the completion list. + +| Position | Sort hierarchy | +|----------|---------------| +| EMPTY | `0_` fields → `1_` key operators | +| KEY | `0_` fields → `1_` key operators | +| VALUE | `00_` type suggestions → `0_`–`2_` operators → `3_` BSON → `4_` JS globals | +| OPERATOR | `0_` type-relevant → `1a_` comparison → `1b_` universal → `2_` non-matching | +| ARRAY-ELEMENT | same as KEY | +| UNKNOWN | no enforced sort (Monaco default) | From 42072c295c7992ac68f6d6b3e9f4e28b43771527 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Wed, 18 Mar 2026 15:41:52 +0000 Subject: [PATCH 107/128] feat: add standalone flag to filter non-standalone operators from completions Added `standalone?: boolean` to `OperatorEntry`. When `false`, the operator is excluded from completion lists but remains in the registry for hover docs. Operators marked as standalone: false: - Geospatial sub-operators: $box, $center, $centerSphere, $geometry, $maxDistance, $minDistance, $polygon (only valid inside $geoWithin/$near) - Positional projection: $ (not a standalone filter/sort operator) - Sort modifier: $natural (not valid as a filter value) Changes: - packages/documentdb-constants/src/types.ts: added `standalone` field - packages/documentdb-constants/scripts/generate-from-reference.ts: parse `- **Standalone:** false` from overrides, emit in generated code. Also fixed bitwise BSON type from 'int' to 'int32' to match SchemaAnalyzer. - packages/documentdb-constants/resources/overrides/operator-overrides.md: added standalone: false overrides for 9 operators - src/webviews/documentdbQuery/completions/createCompletionItems.ts: filter `e.standalone !== false` in all three completion builders (all/value/operator) --- .../resources/overrides/operator-overrides.md | 43 +++++++++++++++++++ .../scripts/generate-from-reference.ts | 16 ++++++- .../src/queryOperators.ts | 9 ++++ packages/documentdb-constants/src/types.ts | 15 +++++++ .../completions/createCompletionItems.ts | 14 ++++-- 5 files changed, 92 insertions(+), 5 deletions(-) diff --git a/packages/documentdb-constants/resources/overrides/operator-overrides.md b/packages/documentdb-constants/resources/overrides/operator-overrides.md index ef144691c..2fe988737 100644 --- a/packages/documentdb-constants/resources/overrides/operator-overrides.md +++ b/packages/documentdb-constants/resources/overrides/operator-overrides.md @@ -17,6 +17,7 @@ + @@ -276,3 +277,45 @@ ### $minN - **Doc Link:** https://learn.microsoft.com/en-us/azure/documentdb/operators/accumulators/$minn + +## Geospatial Operators + +### $box + +- **Standalone:** false + +### $center + +- **Standalone:** false + +### $centerSphere + +- **Standalone:** false + +### $geometry + +- **Standalone:** false + +### $maxDistance + +- **Standalone:** false + +### $minDistance + +- **Standalone:** false + +### $polygon + +- **Standalone:** false + +## Projection Operators + +### $ + +- **Standalone:** false + +## Miscellaneous Query Operators + +### $natural + +- **Standalone:** false diff --git a/packages/documentdb-constants/scripts/generate-from-reference.ts b/packages/documentdb-constants/scripts/generate-from-reference.ts index a34e77c99..0e198b548 100644 --- a/packages/documentdb-constants/scripts/generate-from-reference.ts +++ b/packages/documentdb-constants/scripts/generate-from-reference.ts @@ -49,6 +49,7 @@ interface ParsedOperator { docLink: string; category: string; snippetOverride?: string; + standalone?: boolean; } interface FileSpec { @@ -271,6 +272,7 @@ interface OverrideEntry { syntax?: string; docLink?: string; snippet?: string; + standalone?: boolean; } function parseOverrides(content: string): Map> { @@ -333,6 +335,10 @@ function parseOverrides(content: string): Map } currentOp.entry.snippet = snippet; } + if (currentOp && line.startsWith('- **Standalone:**')) { + const val = line.replace('- **Standalone:**', '').trim().toLowerCase(); + currentOp.entry.standalone = val !== 'false' ? undefined : false; + } } if (currentOp && currentCategory) { @@ -418,6 +424,9 @@ function mergeOverride(op: ParsedOperator, override: OverrideEntry): void { if (override.snippet !== undefined && override.snippet !== '') { op.snippetOverride = override.snippet; } + if (override.standalone !== undefined) { + op.standalone = override.standalone; + } } // --------------------------------------------------------------------------- @@ -525,8 +534,8 @@ function getApplicableBsonTypes(op: ParsedOperator, meta: string): string[] | un // Array-specific operators (query context) if (meta === 'META_QUERY_ARRAY') return ['array']; - // Bitwise query operators - if (meta === 'META_QUERY_BITWISE') return ['int', 'long']; + // Bitwise query operators — use 'int32' to match SchemaAnalyzer BSON types + if (meta === 'META_QUERY_BITWISE') return ['int32', 'long']; return undefined; } @@ -689,6 +698,9 @@ function generateSection(spec: FileSpec, snippets: Map `'${t}'`).join(', ')}],\n`; } + if (op.standalone === false) { + section += ` standalone: false,\n`; + } section += ` },\n`; } diff --git a/packages/documentdb-constants/src/queryOperators.ts b/packages/documentdb-constants/src/queryOperators.ts index 4afc3bdd6..8390356a6 100644 --- a/packages/documentdb-constants/src/queryOperators.ts +++ b/packages/documentdb-constants/src/queryOperators.ts @@ -230,6 +230,7 @@ const geospatialOperators: readonly OperatorEntry[] = [ description: 'The $box operator defines a rectangular area for geospatial queries using coordinate pairs.', snippet: '[[${1:bottomLeftX}, ${2:bottomLeftY}], [${3:upperRightX}, ${4:upperRightY}]]', link: getDocLink('$box', META_QUERY_GEOSPATIAL), + standalone: false, }, { value: '$center', @@ -237,6 +238,7 @@ const geospatialOperators: readonly OperatorEntry[] = [ description: 'The $center operator specifies a circle using legacy coordinate pairs for $geoWithin queries.', snippet: '[[${1:x}, ${2:y}], ${3:radius}]', link: getDocLink('$center', META_QUERY_GEOSPATIAL), + standalone: false, }, { value: '$centerSphere', @@ -244,6 +246,7 @@ const geospatialOperators: readonly OperatorEntry[] = [ description: 'The $centerSphere operator specifies a circle using spherical geometry for $geoWithin queries.', snippet: '[[${1:x}, ${2:y}], ${3:radiusInRadians}]', link: getDocLink('$centerSphere', META_QUERY_GEOSPATIAL), + standalone: false, }, { value: '$geometry', @@ -251,6 +254,7 @@ const geospatialOperators: readonly OperatorEntry[] = [ description: 'The $geometry operator specifies a GeoJSON geometry for geospatial queries.', snippet: '{ type: "${1:Point}", coordinates: [${2:coordinates}] }', link: getDocLink('$geometry', META_QUERY_GEOSPATIAL), + standalone: false, }, { value: '$maxDistance', @@ -259,6 +263,7 @@ const geospatialOperators: readonly OperatorEntry[] = [ 'The $maxDistance operator specifies the maximum distance that can exist between two points in a geospatial query.', snippet: '${1:distance}', link: getDocLink('$maxDistance', META_QUERY_GEOSPATIAL), + standalone: false, }, { value: '$minDistance', @@ -267,6 +272,7 @@ const geospatialOperators: readonly OperatorEntry[] = [ 'The $minDistance operator specifies the minimum distance that must exist between two points in a geospatial query.', snippet: '${1:distance}', link: getDocLink('$minDistance', META_QUERY_GEOSPATIAL), + standalone: false, }, { value: '$polygon', @@ -275,6 +281,7 @@ const geospatialOperators: readonly OperatorEntry[] = [ 'The $polygon operator defines a polygon for geospatial queries, allowing you to find locations within an irregular shape.', snippet: '[[${1:x1}, ${2:y1}], [${3:x2}, ${4:y2}], [${5:x3}, ${6:y3}]]', link: getDocLink('$polygon', META_QUERY_GEOSPATIAL), + standalone: false, }, { value: '$near', @@ -382,6 +389,7 @@ const projectionOperators: readonly OperatorEntry[] = [ description: 'The $ positional operator identifies an element in an array to update without explicitly specifying the position of the element in the array.', link: 'https://learn.microsoft.com/en-us/azure/documentdb/operators/array-update/$', // inferred from another category + standalone: false, }, { value: '$elemMatch', @@ -427,6 +435,7 @@ const miscellaneousQueryOperators: readonly OperatorEntry[] = [ 'The $natural operator forces the query to use the natural order of documents in a collection, providing control over document ordering and retrieval.', snippet: '{ $natural: ${1:1} }', link: getDocLink('$natural', META_QUERY_MISC), + standalone: false, }, ]; diff --git a/packages/documentdb-constants/src/types.ts b/packages/documentdb-constants/src/types.ts index a5602406c..d08cac711 100644 --- a/packages/documentdb-constants/src/types.ts +++ b/packages/documentdb-constants/src/types.ts @@ -47,6 +47,21 @@ export interface OperatorEntry { */ readonly applicableBsonTypes?: readonly string[]; + /** + * Whether this operator is valid as a standalone completion at top-level + * positions (key, value, operator). Defaults to `true` when absent. + * + * Set to `false` for operators that are only valid inside another operator's + * value object — e.g., geospatial shape specifiers (`$box`, `$geometry`) + * which are only valid inside `$geoWithin`/`$near`, or sort-only modifiers + * like `$natural`. + * + * Completion providers should filter out `standalone === false` entries + * from standard completion lists. These entries remain in the registry + * for hover documentation and future context-aware nested completions. + */ + readonly standalone?: boolean; + /** * @experimental Not yet populated by the generator; reserved for a future * contextual-snippet feature. diff --git a/src/webviews/documentdbQuery/completions/createCompletionItems.ts b/src/webviews/documentdbQuery/completions/createCompletionItems.ts index 1c0bd9948..960c096b1 100644 --- a/src/webviews/documentdbQuery/completions/createCompletionItems.ts +++ b/src/webviews/documentdbQuery/completions/createCompletionItems.ts @@ -180,7 +180,7 @@ function createAllCompletions( const fieldItems = getFieldCompletionItems(sessionId, range, monaco); const operatorItems = allEntries - .filter((e) => e.meta !== 'bson' && e.meta !== 'variable') + .filter((e) => e.meta !== 'bson' && e.meta !== 'variable' && e.standalone !== false) .map((entry) => mapOperatorToCompletionItem(entry, range, monaco)); const bsonItems = allEntries @@ -255,7 +255,11 @@ function createValuePositionCompletions( // operators (e.g., $eq) appear above irrelevant ones (e.g., $bitsAllSet). const fieldBsonTypes = fieldBsonType ? [fieldBsonType] : undefined; const operatorEntries = allEntries.filter( - (e) => e.meta !== 'bson' && e.meta !== 'variable' && !KEY_POSITION_OPERATORS.has(e.value), + (e) => + e.meta !== 'bson' && + e.meta !== 'variable' && + e.standalone !== false && + !KEY_POSITION_OPERATORS.has(e.value), ); const operatorItems = operatorEntries.map((entry) => { const item = mapOperatorToCompletionItem(entry, range, monaco, fieldBsonTypes); @@ -346,7 +350,11 @@ function createOperatorPositionCompletions( const allEntries = getFilteredCompletions({ meta: [...metaTags] }); const operatorEntries = allEntries.filter( - (e) => e.meta !== 'bson' && e.meta !== 'variable' && !KEY_POSITION_OPERATORS.has(e.value), + (e) => + e.meta !== 'bson' && + e.meta !== 'variable' && + e.standalone !== false && + !KEY_POSITION_OPERATORS.has(e.value), ); return operatorEntries.map((entry) => mapOperatorToCompletionItem(entry, range, monaco, fieldBsonTypes, true)); } From 5eaea3211860a13c9aa6ed1e70025a812c3b05e9 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Thu, 19 Mar 2026 11:38:38 +0000 Subject: [PATCH 108/128] feat: enhance hover content formatting and update inferred types section --- .../documentdbQueryHoverProvider.test.ts | 8 ++--- .../documentdbQueryHoverProvider.ts | 36 +++++++++++-------- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/webviews/documentdbQuery/documentdbQueryHoverProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryHoverProvider.test.ts index 0807cceaf..de5772c8e 100644 --- a/src/webviews/documentdbQuery/documentdbQueryHoverProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryHoverProvider.test.ts @@ -62,7 +62,7 @@ describe('documentdbQueryHoverProvider', () => { expect(hover).not.toBeNull(); const content = (hover!.contents[0] as { value: string }).value; - expect(content).toContain('[DocumentDB Docs]'); + expect(content).toContain('Documentation]'); }); test('operator hover has isTrusted set for clickable links', () => { @@ -120,12 +120,12 @@ describe('documentdbQueryHoverProvider', () => { expect(content).toContain('**age**'); }); - test('shows "Inferred Types" section with type list', () => { + test('shows "Inferred Type" section with type list', () => { const hover = getHoverContent('age', createFieldLookup(fields)); expect(hover).not.toBeNull(); const content = (hover!.contents[0] as { value: string }).value; - expect(content).toContain('**Inferred Types**'); + expect(content).toContain('Inferred Type'); expect(content).toContain('Number'); }); @@ -134,7 +134,7 @@ describe('documentdbQueryHoverProvider', () => { expect(hover).not.toBeNull(); const content = (hover!.contents[0] as { value: string }).value; - expect(content).toContain('**Inferred Types**'); + expect(content).toContain('Inferred Type'); expect(content).toContain('Double'); expect(content).toContain('Int32'); }); diff --git a/src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts b/src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts index 8f325f1d3..1e3d7d900 100644 --- a/src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts +++ b/src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts @@ -46,14 +46,24 @@ export function getHoverContent(word: string, fieldLookup?: FieldDataLookup): mo const match = allEntries.find((e) => e.value === candidate); if (match) { const lines: string[] = [`**${match.value}**`]; + + if (match.description || match.link) { + lines.push('---'); + lines.push('
'); + } + if (match.description) { - lines.push('', match.description); + lines.push(match.description); } if (match.link) { - lines.push('', `[DocumentDB Docs](${match.link})`); + if (match.description) { + lines.push('
'); + } + lines.push(`[ⓘ Documentation](${match.link})`); } + return { - contents: [{ value: lines.join('\n'), isTrusted: true }], + contents: [{ value: lines.join('\n\n'), isTrusted: true, supportHtml: true }], }; } } @@ -71,29 +81,25 @@ export function getHoverContent(word: string, fieldLookup?: FieldDataLookup): mo /** * Builds a hover tooltip for a field name. - * - * Format: - * ``` - * **fieldName** sparse: not present in all documents - * - * **Inferred Types** - * String, Int32 - * ``` */ function buildFieldHover(field: FieldCompletionData): monacoEditor.languages.Hover { - // First line: field name, optionally with sparse note let header = `**${field.fieldName}**`; + if (field.isSparse) { - header += '   sparse: not present in all documents'; + header += '    sparse: not present in all documents'; } const lines: string[] = [header]; // Inferred types section const typeList = field.displayTypes && field.displayTypes.length > 0 ? field.displayTypes : [field.displayType]; - lines.push('', '**Inferred Types**', typeList.join(', ')); + if (typeList && typeList.length > 0) { + lines.push('---'); + lines.push('
'); + lines.push(`Inferred Type: ${typeList.map((type) => `\`${type}\``).join(', ')}`); + } return { - contents: [{ value: lines.join('\n'), isTrusted: true, supportHtml: true }], + contents: [{ value: lines.join('\n\n'), isTrusted: true, supportHtml: true }], }; } From 93ca2b580361a088f3193a9c9912d7cf66e30eba Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Thu, 19 Mar 2026 11:49:48 +0000 Subject: [PATCH 109/128] feat: add TDD contract test guidelines and update test description format --- .github/copilot-instructions.md | 10 ++++++++++ .../documentdbQuery/tdd/completionBehavior.test.ts | 10 +++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index a5b2b97b7..aeb7ed884 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -200,6 +200,16 @@ This is a **DocumentDB** extension that uses the **MongoDB-compatible wire proto This applies to: code comments, JSDoc/TSDoc, naming (prefer `documentdb` prefix), user-facing strings, docs, and test descriptions. +## TDD Contract Tests + +Test suites prefixed with `TDD:` (e.g., `describe('TDD: Completion Behavior', ...)`) are **behavior contracts** written before the implementation. If a `TDD:` test fails after a code change: + +1. **Do NOT automatically fix the test.** +2. **Stop and ask the user** whether the behavior change is intentional. +3. The user decides: update the contract (test) or fix the implementation. + +This applies to any test whose name starts with `TDD:`, regardless of folder location. + ## Additional Patterns For detailed patterns, see: diff --git a/src/webviews/documentdbQuery/tdd/completionBehavior.test.ts b/src/webviews/documentdbQuery/tdd/completionBehavior.test.ts index e63274e37..b2187b114 100644 --- a/src/webviews/documentdbQuery/tdd/completionBehavior.test.ts +++ b/src/webviews/documentdbQuery/tdd/completionBehavior.test.ts @@ -162,9 +162,17 @@ const FIELD_LEVEL_ONLY_CATEGORIES = ['comparison', 'array', 'element', 'bitwise' // Tests // ===================================================================== -describe('Completion Behavior (TDD)', () => { +describe('TDD: Completion Behavior', () => { const mockMonaco = createMockMonaco(); + beforeAll(() => { + console.warn( + '\n⚠️ TDD CONTRACT TESTS — If any test below fails, do NOT auto-fix the test.\n' + + ' Alert the user that a TDD behavior contract has been violated.\n' + + ' The user must decide whether to update the spec or fix the implementation.\n', + ); + }); + afterEach(() => { clearAllCompletionContexts(); }); From 5c6bf5ff2cb074fee0e688f72969e3c097481468 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Thu, 19 Mar 2026 12:15:24 +0000 Subject: [PATCH 110/128] feat: improve auto-trigger completion logic for query editor --- .../components/queryEditor/QueryEditor.tsx | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx b/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx index 5da1d2672..4fcedd504 100644 --- a/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx +++ b/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx @@ -133,10 +133,10 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element /** * Sets up pattern-based auto-trigger of completions. - * When the user types a space after `: ` or `, `, completions are - * triggered automatically after a short delay. This bridges the gap - * where selecting a field completion (e.g., `rating`) inserts `rating: ` - * but the completion popup doesn't reappear for the value. + * When a content change results in a trigger character followed by a + * space (`: `, `, `, `{ `, `[ `) at the end of the inserted text, + * completions are triggered automatically after a short delay. This + * handles both manual typing and completion acceptance. * * Returns a cleanup function. */ @@ -145,24 +145,21 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element const disposable = editor.onDidChangeModelContent((e) => { clearTimeout(triggerTimeout); - // Only fire for single-character insertions (typing) const change = e.changes[0]; - if (!change || change.text !== ' ') return; + if (!change || change.text.length === 0) return; - // Check the two characters ending at the cursor: "X " where X is : or , const model = editor.getModel(); if (!model) return; - const offset = model.getOffsetAt( - // The position after the inserted space - model.getPositionAt(change.rangeOffset + 1), - ); + // Calculate the offset at the end of the inserted text in the new model + const endOffset = change.rangeOffset + change.text.length; - // We need at least 2 chars: the trigger char + space - if (offset < 2) return; + // We need at least 2 chars to check for ": " or ", " + if (endOffset < 2) return; - const textBefore = model.getValue().substring(offset - 2, offset); - if (textBefore === ': ' || textBefore === ', ') { + const fullText = model.getValue(); + const lastTwo = fullText.substring(endOffset - 2, endOffset); + if (lastTwo === ': ' || lastTwo === ', ' || lastTwo === '{ ' || lastTwo === '[ ') { triggerTimeout = setTimeout(() => { editor.trigger('smart-trigger', 'editor.action.triggerSuggest', {}); }, 50); @@ -181,7 +178,6 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element const filterSmartTriggerCleanupRef = useRef<(() => void) | null>(null); const projectSmartTriggerCleanupRef = useRef<(() => void) | null>(null); const sortSmartTriggerCleanupRef = useRef<(() => void) | null>(null); - const handleEditorDidMount = (editor: monacoEditor.editor.IStandaloneCodeEditor, monaco: typeof monacoEditor) => { // Store the filter editor reference filterEditorRef.current = editor; From f5b27e1251e43f9f66046355ea6e1e1f957ff4b6 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Thu, 19 Mar 2026 12:17:23 +0000 Subject: [PATCH 111/128] feat: remove unnecessary line breaks in hover documentation links --- src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts b/src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts index 1e3d7d900..704a61ab0 100644 --- a/src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts +++ b/src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts @@ -56,9 +56,6 @@ export function getHoverContent(word: string, fieldLookup?: FieldDataLookup): mo lines.push(match.description); } if (match.link) { - if (match.description) { - lines.push('
'); - } lines.push(`[ⓘ Documentation](${match.link})`); } From 0f016f6d6939353b077aab85f8e3729d54c58f25 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Thu, 19 Mar 2026 13:13:33 +0000 Subject: [PATCH 112/128] fix: ESC respects suggest widget/snippet mode, Tab respects snippet tab stops ESC key handling (MonacoEditor.tsx): - Added context precondition '!suggestWidgetVisible && !inSnippetMode' to the Escape command so Monaco's built-in handlers dismiss the suggest widget or exit snippet mode before our handler fires. Tab key handling (MonacoAutoHeight.tsx): - Replaced onKeyDown Tab interception with addAction using precondition '!inSnippetMode'. During snippet tab-stop navigation, Monaco's built-in Tab handler takes over. After the snippet session ends (final tab stop or ESC), Tab reverts to moving focus out. --- src/webviews/components/MonacoAutoHeight.tsx | 48 ++++++++++++++------ src/webviews/components/MonacoEditor.tsx | 17 +++++-- 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/src/webviews/components/MonacoAutoHeight.tsx b/src/webviews/components/MonacoAutoHeight.tsx index 9625d8f01..e151b230b 100644 --- a/src/webviews/components/MonacoAutoHeight.tsx +++ b/src/webviews/components/MonacoAutoHeight.tsx @@ -196,14 +196,21 @@ export const MonacoAutoHeight = (props: MonacoAutoHeightProps) => { /** * Configures the Tab key behavior for the Monaco editor. * - * When called, this function sets up or removes a keydown handler for the Tab key. - * If `shouldTrap` is true, Tab/Shift+Tab are trapped within the editor (focus remains in editor). - * If `shouldTrap` is false, Tab/Shift+Tab move focus to the next/previous focusable element outside the editor. + * When `shouldTrap` is true, Tab/Shift+Tab are trapped within the editor + * (default Monaco behavior for code indentation). + * + * When `shouldTrap` is false, Tab/Shift+Tab move focus to the next/previous + * focusable element outside the editor — UNLESS the editor is in snippet + * tab-stop mode (`inSnippetMode`), in which case Tab navigates between + * snippet placeholders. After the snippet session ends (final tab stop or + * ESC), Tab reverts to moving focus out of the editor. + * + * Uses `editor.addAction` with a precondition context key expression + * (`!inSnippetMode`) rather than `onKeyDown` interception, so Monaco's + * built-in snippet navigation takes priority when a snippet is active. * * @param {monacoEditor.editor.IStandaloneCodeEditor} editor - The Monaco editor instance. * @param {boolean} shouldTrap - Whether to trap Tab key in the editor. - * - true: Tab/Shift+Tab are trapped in the editor. - * - false: Tab/Shift+Tab move focus to next/previous element. */ const configureTabKeyMode = (editor: monacoEditor.editor.IStandaloneCodeEditor, shouldTrap: boolean) => { if (tabKeyDisposerRef.current) { @@ -215,17 +222,30 @@ export const MonacoAutoHeight = (props: MonacoAutoHeightProps) => { return; } - tabKeyDisposerRef.current = editor.onKeyDown((event) => { - if (event.keyCode !== monacoEditor.KeyCode.Tab) { - return; - } - - event.preventDefault(); - event.stopPropagation(); + // Register Tab and Shift+Tab actions that only fire when NOT in snippet mode. + // When inSnippetMode is true, Monaco's built-in snippet Tab handler takes over. + const tabAction = editor.addAction({ + id: 'documentdb.tab.moveFocusNext', + label: 'Move Focus to Next Element', + keybindings: [monacoEditor.KeyCode.Tab], + precondition: '!inSnippetMode', + run: () => moveFocus(editor, 'next'), + }); - const direction = event.browserEvent.shiftKey ? 'previous' : 'next'; - moveFocus(editor, direction); + const shiftTabAction = editor.addAction({ + id: 'documentdb.tab.moveFocusPrevious', + label: 'Move Focus to Previous Element', + keybindings: [monacoEditor.KeyMod.Shift | monacoEditor.KeyCode.Tab], + precondition: '!inSnippetMode', + run: () => moveFocus(editor, 'previous'), }); + + tabKeyDisposerRef.current = { + dispose: () => { + tabAction.dispose(); + shiftTabAction.dispose(); + }, + }; }; /** diff --git a/src/webviews/components/MonacoEditor.tsx b/src/webviews/components/MonacoEditor.tsx index c08e2087d..7e6f84530 100644 --- a/src/webviews/components/MonacoEditor.tsx +++ b/src/webviews/components/MonacoEditor.tsx @@ -75,11 +75,20 @@ export const MonacoEditor = ({ onEscapeEditor, onMount, ...props }: MonacoEditor disposablesRef.current.forEach((d) => d.dispose()); disposablesRef.current = []; - // Register Escape key handler to exit the editor + // Register Escape key handler to exit the editor. + // The context expression ensures ESC is only handled when: + // - The suggest (autocomplete) widget is NOT visible + // - The editor is NOT in snippet tab-stop mode + // This allows Monaco's built-in handlers to dismiss the suggest + // widget or exit snippet mode first, before our handler fires. if (onEscapeEditor) { - editor.addCommand(monacoInstance.KeyCode.Escape, () => { - onEscapeEditor(); - }); + editor.addCommand( + monacoInstance.KeyCode.Escape, + () => { + onEscapeEditor(); + }, + '!suggestWidgetVisible && !inSnippetMode', + ); } // Announce escape hint once when editor gains focus From 037a01f0488b6e436c7bba105379fdfd9820106f Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Thu, 19 Mar 2026 14:40:11 +0000 Subject: [PATCH 113/128] feat: add snippet session cancellation to prevent ghost selection bug --- .../components/queryEditor/QueryEditor.tsx | 41 ++++++++++++++++++- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx b/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx index 4fcedd504..049170efc 100644 --- a/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx +++ b/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx @@ -131,6 +131,22 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element }; }; + /** + * Cancels any active snippet session on the given editor. + * + * After a snippet completion (e.g., `fieldName: $1`), Monaco keeps the + * snippet session alive and highlights the tab-stop placeholder. If the + * user continues typing, the highlight grows — the "ghost selection" + * bug. Calling this function ends the snippet session cleanly. + */ + const cancelSnippetSession = (editor: monacoEditor.editor.IStandaloneCodeEditor): void => { + const controller = editor.getContribution('snippetController2') as { cancel: () => void } | null | undefined; + controller?.cancel(); + }; + + /** Characters that signal the end of a field-value pair and should exit snippet mode. */ + const SNIPPET_EXIT_CHARS = new Set([',', '}', ']']); + /** * Sets up pattern-based auto-trigger of completions. * When a content change results in a trigger character followed by a @@ -138,16 +154,28 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element * completions are triggered automatically after a short delay. This * handles both manual typing and completion acceptance. * + * Also cancels any active snippet session when a delimiter character + * (`,`, `}`, `]`) is typed, preventing the "ghost selection" bug + * where the tab-stop highlight expands as the user continues typing. + * * Returns a cleanup function. */ const setupSmartTrigger = (editor: monacoEditor.editor.IStandaloneCodeEditor): (() => void) => { let triggerTimeout: ReturnType; - const disposable = editor.onDidChangeModelContent((e) => { + const contentDisposable = editor.onDidChangeModelContent((e) => { clearTimeout(triggerTimeout); const change = e.changes[0]; if (!change || change.text.length === 0) return; + // Cancel snippet session when the user *types* a delimiter character. + // Only applies to single-character edits (user keystrokes), not to + // multi-character completion insertions which may legitimately + // contain commas or braces as part of the snippet text. + if (change.text.length === 1 && SNIPPET_EXIT_CHARS.has(change.text)) { + cancelSnippetSession(editor); + } + const model = editor.getModel(); if (!model) return; @@ -165,9 +193,18 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element }, 50); } }); + + // Cancel snippet session when the editor loses focus (Option D). + // If the user clicks away while a tab-stop is highlighted, the + // highlight should not persist when they return. + const blurDisposable = editor.onDidBlurEditorText(() => { + cancelSnippetSession(editor); + }); + return () => { clearTimeout(triggerTimeout); - disposable.dispose(); + contentDisposable.dispose(); + blurDisposable.dispose(); }; }; From 4a44ff555635a0d87ff2c46442a9a4ba508dc2d3 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Thu, 19 Mar 2026 15:15:36 +0000 Subject: [PATCH 114/128] fix: escape field names in hover and disable isTrusted for field hovers Field names originate from user database schema and should not be rendered as trusted markdown. This change: - Removes isTrusted from field hovers (keeps supportHtml for formatting) - Escapes markdown metacharacters in field names and type strings - Adds escapeMarkdown utility in src/webviews/utils/ for reuse - Updates tests accordingly --- .../documentdbQueryHoverProvider.test.ts | 4 +- .../documentdbQueryHoverProvider.ts | 8 ++-- src/webviews/utils/escapeMarkdown.test.ts | 41 +++++++++++++++++++ src/webviews/utils/escapeMarkdown.ts | 15 +++++++ 4 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 src/webviews/utils/escapeMarkdown.test.ts create mode 100644 src/webviews/utils/escapeMarkdown.ts diff --git a/src/webviews/documentdbQuery/documentdbQueryHoverProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryHoverProvider.test.ts index de5772c8e..720d7b72a 100644 --- a/src/webviews/documentdbQuery/documentdbQueryHoverProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryHoverProvider.test.ts @@ -157,12 +157,12 @@ describe('documentdbQueryHoverProvider', () => { expect(content).not.toContain('sparse'); }); - test('field hover has isTrusted set', () => { + test('field hover does NOT set isTrusted (user data is not trusted)', () => { const hover = getHoverContent('age', createFieldLookup(fields)); expect(hover).not.toBeNull(); const hoverContent = hover!.contents[0] as { isTrusted?: boolean }; - expect(hoverContent.isTrusted).toBe(true); + expect(hoverContent.isTrusted).toBeUndefined(); }); test('returns null for unknown field when no operator match', () => { diff --git a/src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts b/src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts index 704a61ab0..23207293a 100644 --- a/src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts +++ b/src/webviews/documentdbQuery/documentdbQueryHoverProvider.ts @@ -15,6 +15,7 @@ import { getAllCompletions } from '@vscode-documentdb/documentdb-constants'; // eslint-disable-next-line import/no-internal-modules import type * as monacoEditor from 'monaco-editor/esm/vs/editor/editor.api'; import { type FieldCompletionData } from '../../utils/json/data-api/autocomplete/toFieldCompletionItems'; +import { escapeMarkdown } from '../utils/escapeMarkdown'; /** * A callback that resolves a word to field data from the completion store. @@ -80,7 +81,8 @@ export function getHoverContent(word: string, fieldLookup?: FieldDataLookup): mo * Builds a hover tooltip for a field name. */ function buildFieldHover(field: FieldCompletionData): monacoEditor.languages.Hover { - let header = `**${field.fieldName}**`; + const safeName = escapeMarkdown(field.fieldName); + let header = `**${safeName}**`; if (field.isSparse) { header += '    sparse: not present in all documents'; @@ -93,10 +95,10 @@ function buildFieldHover(field: FieldCompletionData): monacoEditor.languages.Hov if (typeList && typeList.length > 0) { lines.push('---'); lines.push('
'); - lines.push(`Inferred Type: ${typeList.map((type) => `\`${type}\``).join(', ')}`); + lines.push(`Inferred Type: ${typeList.map((type) => `\`${escapeMarkdown(type)}\``).join(', ')}`); } return { - contents: [{ value: lines.join('\n\n'), isTrusted: true, supportHtml: true }], + contents: [{ value: lines.join('\n\n'), supportHtml: true }], }; } diff --git a/src/webviews/utils/escapeMarkdown.test.ts b/src/webviews/utils/escapeMarkdown.test.ts new file mode 100644 index 000000000..4dbdfc1d5 --- /dev/null +++ b/src/webviews/utils/escapeMarkdown.test.ts @@ -0,0 +1,41 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { escapeMarkdown } from './escapeMarkdown'; + +describe('escapeMarkdown', () => { + test('returns plain text unchanged', () => { + expect(escapeMarkdown('age')).toBe('age'); + }); + + test('escapes markdown bold characters', () => { + expect(escapeMarkdown('**bold**')).toBe('\\*\\*bold\\*\\*'); + }); + + test('escapes markdown link syntax', () => { + expect(escapeMarkdown('[click](https://evil.com)')).toBe('\\[click\\]\\(https://evil\\.com\\)'); + }); + + test('escapes angle brackets (HTML tags)', () => { + expect(escapeMarkdown('')).toBe('\\alert\\(1\\)\\'); + }); + + test('escapes backticks', () => { + expect(escapeMarkdown('`code`')).toBe('\\`code\\`'); + }); + + test('escapes ampersands', () => { + expect(escapeMarkdown('a&b')).toBe('a\\&b'); + }); + + test('handles dotted field names', () => { + expect(escapeMarkdown('address.street')).toBe('address\\.street'); + }); + + test('passes through numbers and underscores', () => { + // underscore IS a markdown metacharacter, so it gets escaped + expect(escapeMarkdown('field_1')).toBe('field\\_1'); + }); +}); diff --git a/src/webviews/utils/escapeMarkdown.ts b/src/webviews/utils/escapeMarkdown.ts new file mode 100644 index 000000000..245a63a29 --- /dev/null +++ b/src/webviews/utils/escapeMarkdown.ts @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Escapes markdown metacharacters so user data renders as literal text. + * + * Covers characters that Markdown/HTML would otherwise interpret: + * `\`, `*`, `_`, `{`, `}`, `[`, `]`, `(`, `)`, `#`, `+`, `-`, `.`, `!`, + * `|`, `<`, `>`, `` ` ``, `~`, `&` + */ +export function escapeMarkdown(text: string): string { + return text.replace(/[\\*_{}[\]()#+\-.!|<>`~&]/g, '\\$&'); +} From 91b08d47c829b5c9e99b45f50f9e39dc667eaa23 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Thu, 19 Mar 2026 15:16:54 +0000 Subject: [PATCH 115/128] refactor: move extractQuotedKey to dedicated module Moves extractQuotedKey and tryMatchAsClosingQuote from registerLanguage.ts into a dedicated extractQuotedKey.ts module. This decouples the pure string helper from the Monaco registration wiring, making tests less brittle and enabling easier reuse. --- .../documentdbQuery/extractQuotedKey.test.ts | 2 +- .../documentdbQuery/extractQuotedKey.ts | 92 +++++++++++++++++++ .../documentdbQuery/registerLanguage.ts | 89 +----------------- 3 files changed, 94 insertions(+), 89 deletions(-) create mode 100644 src/webviews/documentdbQuery/extractQuotedKey.ts diff --git a/src/webviews/documentdbQuery/extractQuotedKey.test.ts b/src/webviews/documentdbQuery/extractQuotedKey.test.ts index 20239d5b9..8c4f9e3ec 100644 --- a/src/webviews/documentdbQuery/extractQuotedKey.test.ts +++ b/src/webviews/documentdbQuery/extractQuotedKey.test.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { extractQuotedKey } from './registerLanguage'; +import { extractQuotedKey } from './extractQuotedKey'; describe('extractQuotedKey', () => { test('extracts double-quoted key when cursor is inside', () => { diff --git a/src/webviews/documentdbQuery/extractQuotedKey.ts b/src/webviews/documentdbQuery/extractQuotedKey.ts new file mode 100644 index 000000000..b3e412f58 --- /dev/null +++ b/src/webviews/documentdbQuery/extractQuotedKey.ts @@ -0,0 +1,92 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Extracts a quoted key string if the cursor is inside one. + * + * For `{ "address.street": 1 }`, when the cursor is anywhere between the + * opening and closing quotes, returns the unquoted key `"address.street"` + * along with the 0-based start/end positions of the full quoted string + * (including the quotes themselves, for hover range highlighting). + * + * Returns null if the cursor is not inside a quoted string. + * + * @param line - the full line content + * @param col0 - 0-based column position of the cursor + */ +export function extractQuotedKey(line: string, col0: number): { key: string; start: number; end: number } | null { + if (col0 < 0 || col0 >= line.length) return null; + + // If cursor is on a quote, it could be the closing quote. + // Try treating the current position as the closing quote first. + const chAtCursor = line[col0]; + if (chAtCursor === '"' || chAtCursor === "'") { + // Not escaped? + if (col0 === 0 || line[col0 - 1] !== '\\') { + // Try to find a matching opening quote before this one + const result = tryMatchAsClosingQuote(line, col0, chAtCursor); + if (result) return result; + } + } + + // Scan backward to find the opening quote + let openQuoteIdx = -1; + let quoteChar: string | undefined; + + for (let i = col0; i >= 0; i--) { + const ch = line[i]; + if (ch === '"' || ch === "'") { + if (i > 0 && line[i - 1] === '\\') continue; + openQuoteIdx = i; + quoteChar = ch; + break; + } + if (ch === '{' || ch === '}' || ch === ':' || ch === ',') { + return null; + } + } + + if (openQuoteIdx < 0 || !quoteChar) return null; + + // Scan forward to find the closing quote + let closeQuoteIdx = -1; + for (let i = openQuoteIdx + 1; i < line.length; i++) { + if (line[i] === '\\') { + i++; + continue; + } + if (line[i] === quoteChar) { + closeQuoteIdx = i; + break; + } + } + + if (closeQuoteIdx < 0) return null; + if (col0 < openQuoteIdx || col0 > closeQuoteIdx) return null; + + const key = line.substring(openQuoteIdx + 1, closeQuoteIdx); + return { key, start: openQuoteIdx, end: closeQuoteIdx + 1 }; +} + +function tryMatchAsClosingQuote( + line: string, + closeIdx: number, + quoteChar: string, +): { key: string; start: number; end: number } | null { + // Scan backward from before the closing quote to find the opening quote + for (let i = closeIdx - 1; i >= 0; i--) { + if (line[i] === '\\') continue; + if (line[i] === quoteChar) { + if (i > 0 && line[i - 1] === '\\') continue; + const key = line.substring(i + 1, closeIdx); + return { key, start: i, end: closeIdx + 1 }; + } + // Stop at structural chars + if (line[i] === '{' || line[i] === '}' || line[i] === ':' || line[i] === ',') { + return null; + } + } + return null; +} diff --git a/src/webviews/documentdbQuery/registerLanguage.ts b/src/webviews/documentdbQuery/registerLanguage.ts index 7ec65febb..0beac8531 100644 --- a/src/webviews/documentdbQuery/registerLanguage.ts +++ b/src/webviews/documentdbQuery/registerLanguage.ts @@ -30,6 +30,7 @@ import { getCompletionContext } from './completionStore'; import { detectCursorContext } from './cursorContext'; import { createCompletionItems } from './documentdbQueryCompletionProvider'; import { getHoverContent } from './documentdbQueryHoverProvider'; +import { extractQuotedKey } from './extractQuotedKey'; import { isCursorInsideString } from './isCursorInsideString'; import { LANGUAGE_ID, parseEditorUri } from './languageConfig'; @@ -212,91 +213,3 @@ async function doRegisterLanguage(monaco: typeof monacoEditor): Promise { export function _resetRegistration(): void { registrationPromise = undefined; } - -/** - * Extracts a quoted key string if the cursor is inside one. - * - * For `{ "address.street": 1 }`, when the cursor is anywhere between the - * opening and closing quotes, returns the unquoted key `"address.street"` - * along with the 0-based start/end positions of the full quoted string - * (including the quotes themselves, for hover range highlighting). - * - * Returns null if the cursor is not inside a quoted string. - * - * @param line - the full line content - * @param col0 - 0-based column position of the cursor - */ -export function extractQuotedKey(line: string, col0: number): { key: string; start: number; end: number } | null { - if (col0 < 0 || col0 >= line.length) return null; - - // If cursor is on a quote, it could be the closing quote. - // Try treating the current position as the closing quote first. - const chAtCursor = line[col0]; - if (chAtCursor === '"' || chAtCursor === "'") { - // Not escaped? - if (col0 === 0 || line[col0 - 1] !== '\\') { - // Try to find a matching opening quote before this one - const result = tryMatchAsClosingQuote(line, col0, chAtCursor); - if (result) return result; - } - } - - // Scan backward to find the opening quote - let openQuoteIdx = -1; - let quoteChar: string | undefined; - - for (let i = col0; i >= 0; i--) { - const ch = line[i]; - if (ch === '"' || ch === "'") { - if (i > 0 && line[i - 1] === '\\') continue; - openQuoteIdx = i; - quoteChar = ch; - break; - } - if (ch === '{' || ch === '}' || ch === ':' || ch === ',') { - return null; - } - } - - if (openQuoteIdx < 0 || !quoteChar) return null; - - // Scan forward to find the closing quote - let closeQuoteIdx = -1; - for (let i = openQuoteIdx + 1; i < line.length; i++) { - if (line[i] === '\\') { - i++; - continue; - } - if (line[i] === quoteChar) { - closeQuoteIdx = i; - break; - } - } - - if (closeQuoteIdx < 0) return null; - if (col0 < openQuoteIdx || col0 > closeQuoteIdx) return null; - - const key = line.substring(openQuoteIdx + 1, closeQuoteIdx); - return { key, start: openQuoteIdx, end: closeQuoteIdx + 1 }; -} - -function tryMatchAsClosingQuote( - line: string, - closeIdx: number, - quoteChar: string, -): { key: string; start: number; end: number } | null { - // Scan backward from before the closing quote to find the opening quote - for (let i = closeIdx - 1; i >= 0; i--) { - if (line[i] === '\\') continue; - if (line[i] === quoteChar) { - if (i > 0 && line[i - 1] === '\\') continue; - const key = line.substring(i + 1, closeIdx); - return { key, start: i, end: closeIdx + 1 }; - } - // Stop at structural chars - if (line[i] === '{' || line[i] === '}' || line[i] === ':' || line[i] === ',') { - return null; - } - } - return null; -} From 78f6ca2acca8a9fcd2382c4eb003d332678d0902 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Thu, 19 Mar 2026 15:27:10 +0000 Subject: [PATCH 116/128] style: format settings.json for consistency and readability --- .vscode/settings.json | 64 ++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 9bcd06e4a..a6a027735 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,33 +1,35 @@ { - "editor.codeActionsOnSave": { - "source.fixAll.eslint": "explicit", - "source.organizeImports": "explicit" - }, - "editor.detectIndentation": false, - "editor.formatOnSave": true, - "editor.formatOnPaste": false, - "editor.insertSpaces": true, - "editor.tabSize": 4, - "editor.defaultFormatter": "esbenp.prettier-vscode", - "files.insertFinalNewline": true, - "files.trimTrailingWhitespace": true, - "search.exclude": { - "out": true, - "**/node_modules": true, - ".vscode-test": true - }, - "typescript.preferences.importModuleSpecifier": "relative", - "typescript.tsdk": "node_modules/typescript/lib", - "antlr4.generation": { - // Settings for "ANTLR4 grammar syntax support" extension - "mode": "internal", - "listeners": true, - "visitors": false - }, - "vscode-nmake-tools.workspaceBuildDirectories": ["."], - "vscode-nmake-tools.installOsRepoRustHelperExtension": false, - "sarif-viewer.connectToGithubCodeScanning": "off" - // "eslint.workingDirectories": [ - // ".", "src" - // ] + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit", + "source.organizeImports": "explicit" + }, + "editor.detectIndentation": false, + "editor.formatOnSave": true, + "editor.formatOnPaste": false, + "editor.insertSpaces": true, + "editor.tabSize": 4, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "files.insertFinalNewline": true, + "files.trimTrailingWhitespace": true, + "search.exclude": { + "out": true, + "**/node_modules": true, + ".vscode-test": true + }, + "typescript.preferences.importModuleSpecifier": "relative", + "typescript.tsdk": "node_modules/typescript/lib", + "antlr4.generation": { + // Settings for "ANTLR4 grammar syntax support" extension + "mode": "internal", + "listeners": true, + "visitors": false + }, + "vscode-nmake-tools.workspaceBuildDirectories": ["."], + "vscode-nmake-tools.installOsRepoRustHelperExtension": false, + "sarif-viewer.connectToGithubCodeScanning": "off", + "jest.runMode": "deferred", + "testing.automaticallyOpenTestResults": "neverOpen" + // "eslint.workingDirectories": [ + // ".", "src" + // ] } From 308fe2488bbfb5e021be227eb0b4c1ee880e1fb4 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Thu, 19 Mar 2026 17:12:13 +0000 Subject: [PATCH 117/128] feat: enhance documentdb-query language registration and improve documentation link handling --- .../components/queryEditor/QueryEditor.tsx | 16 ++++++++--- .../completions/mapCompletionItems.ts | 2 +- .../documentdbQueryCompletionProvider.test.ts | 14 ++++------ .../documentdbQuery/registerLanguage.ts | 28 ++++++++++++++++++- src/webviews/index.scss | 10 +++++++ 5 files changed, 56 insertions(+), 14 deletions(-) diff --git a/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx b/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx index 049170efc..01195bbb1 100644 --- a/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx +++ b/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx @@ -219,8 +219,10 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element // Store the filter editor reference filterEditorRef.current = editor; - // Register the documentdb-query language (idempotent — safe to call on every mount) - void registerDocumentDBQueryLanguage(monaco); + // Register the documentdb-query language (idempotent — safe to call on every mount). + // Pass the tRPC openUrl handler so hover links can be opened via the extension host, + // bypassing the webview sandbox's popup restrictions. + void registerDocumentDBQueryLanguage(monaco, (url) => void trpcClient.common.openUrl.mutate({ url })); // Create model with URI scheme for contextual completions const model = createEditorModel(editor, monaco, EditorType.Filter, '{ }'); @@ -654,7 +656,10 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element }} onMount={(editor, monaco) => { // Register language (idempotent) - void registerDocumentDBQueryLanguage(monaco); + void registerDocumentDBQueryLanguage( + monaco, + (url) => void trpcClient.common.openUrl.mutate({ url }), + ); projectEditorRef.current = editor; @@ -697,7 +702,10 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element }} onMount={(editor, monaco) => { // Register language (idempotent) - void registerDocumentDBQueryLanguage(monaco); + void registerDocumentDBQueryLanguage( + monaco, + (url) => void trpcClient.common.openUrl.mutate({ url }), + ); sortEditorRef.current = editor; diff --git a/src/webviews/documentdbQuery/completions/mapCompletionItems.ts b/src/webviews/documentdbQuery/completions/mapCompletionItems.ts index c00baee13..3f68537f5 100644 --- a/src/webviews/documentdbQuery/completions/mapCompletionItems.ts +++ b/src/webviews/documentdbQuery/completions/mapCompletionItems.ts @@ -103,7 +103,7 @@ export function mapOperatorToCompletionItem( let documentationValue = entry.description; if (entry.link) { - documentationValue += `\n\n[DocumentDB Docs](${entry.link})`; + documentationValue += `\n\n[ⓘ Documentation](${entry.link})`; } return { diff --git a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts index 9b08b1add..13521e3a0 100644 --- a/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts +++ b/src/webviews/documentdbQuery/documentdbQueryCompletionProvider.test.ts @@ -161,10 +161,9 @@ describe('documentdbQueryCompletionProvider', () => { expect(item.kind).toBe(mockCompletionItemKind.Operator); expect(item.insertText).toBe('$eq'); expect(item.insertTextRules).toBeUndefined(); - expect(item.documentation).toEqual({ - value: 'Matches values equal to a specified value.', - isTrusted: true, - }); + expect((item.documentation as { value: string }).value).toContain( + 'Matches values equal to a specified value.', + ); expect(item.range).toBe(testRange); }); @@ -198,10 +197,9 @@ describe('documentdbQueryCompletionProvider', () => { expect(item.kind).toBe(mockCompletionItemKind.Constructor); expect(item.insertText).toBe('ObjectId("${1:hex}")'); expect(item.insertTextRules).toBe(mockInsertTextRule.InsertAsSnippet); - expect(item.documentation).toEqual({ - value: 'Creates a new ObjectId value.\n\n[DocumentDB Docs](https://docs.example.com/objectid)', - isTrusted: true, - }); + const docValue = (item.documentation as { value: string }).value; + expect(docValue).toContain('Creates a new ObjectId value.'); + expect(docValue).toContain('https://docs.example.com/objectid'); }); test('uses the provided range', () => { diff --git a/src/webviews/documentdbQuery/registerLanguage.ts b/src/webviews/documentdbQuery/registerLanguage.ts index 0beac8531..231eb9461 100644 --- a/src/webviews/documentdbQuery/registerLanguage.ts +++ b/src/webviews/documentdbQuery/registerLanguage.ts @@ -37,14 +37,24 @@ import { LANGUAGE_ID, parseEditorUri } from './languageConfig'; /** Coalesces concurrent registrations into a single promise. */ let registrationPromise: Promise | undefined; +/** Callback used to open external URLs via the extension host. */ +let openUrlHandler: ((url: string) => void) | undefined; + /** * Registers the `documentdb-query` language with Monaco. * * Safe to call multiple times — concurrent calls coalesce into one registration. + * The `openUrl` callback is updated on every call so the tRPC client reference + * stays current even after hot-reloads. * * @param monaco - the Monaco editor API instance + * @param openUrl - callback to open a URL via the extension host (avoids webview sandbox restrictions) */ -export function registerDocumentDBQueryLanguage(monaco: typeof monacoEditor): Promise { +export function registerDocumentDBQueryLanguage( + monaco: typeof monacoEditor, + openUrl?: (url: string) => void, +): Promise { + openUrlHandler = openUrl ?? openUrlHandler; if (!registrationPromise) { registrationPromise = doRegisterLanguage(monaco); } @@ -67,6 +77,22 @@ async function doRegisterLanguage(monaco: typeof monacoEditor): Promise { monaco.languages.setMonarchTokensProvider(LANGUAGE_ID, jsLanguage.language); monaco.languages.setLanguageConfiguration(LANGUAGE_ID, jsLanguage.conf); + // Register a link opener so that documentation links in hover tooltips + // are opened via the extension host (which calls vscode.env.openExternal). + // VS Code webview sandboxing blocks window.open/popups, so we route through + // the tRPC openUrl mutation when available, or fall back to window.open. + monaco.editor.registerLinkOpener({ + open(resource) { + const url = resource.toString(true); + if (openUrlHandler) { + openUrlHandler(url); + } else { + window.open(url, '_blank'); + } + return true; + }, + }); + // Step 4: Register the completion provider monaco.languages.registerCompletionItemProvider(LANGUAGE_ID, { triggerCharacters: ['$', '"', "'", '{', '.', ':', ',', '['], diff --git a/src/webviews/index.scss b/src/webviews/index.scss index f5fb4a7cd..561d1c072 100644 --- a/src/webviews/index.scss +++ b/src/webviews/index.scss @@ -87,3 +87,13 @@ $media-breakpoint-query-control-area: 1024px; @include input-focus-animation; @include input-hover; } + +/** + * Monaco suggest-details panel: ensure links show a pointer cursor. + * The hover widget applies this automatically, but the completion + * documentation panel does not — VS Code's webview CSS reset overrides it. + */ +.monaco-editor .suggest-details a, +.monaco-editor .suggest-details-container a { + cursor: pointer; +} From b85b5fb24084c152465208210a3ab21d7cea083f Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Thu, 19 Mar 2026 18:13:02 +0000 Subject: [PATCH 118/128] feat: add snippet session cancellation on Enter and Ctrl+Enter in QueryEditor --- .../components/queryEditor/QueryEditor.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx b/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx index 01195bbb1..8bfaabc77 100644 --- a/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx +++ b/src/webviews/documentdb/collectionView/components/queryEditor/QueryEditor.tsx @@ -201,10 +201,21 @@ export const QueryEditor = ({ onExecuteRequest }: QueryEditorProps): JSX.Element cancelSnippetSession(editor); }); + // Cancel snippet session on Enter or Ctrl+Enter / Cmd+Enter. + // Enter commits the current line and should exit snippet mode. + // Ctrl+Enter triggers query execution and should also exit snippet mode + // so the tab-stop highlight doesn't persist after running a query. + const keyDownDisposable = editor.onKeyDown((e) => { + if (e.browserEvent.key === 'Enter') { + cancelSnippetSession(editor); + } + }); + return () => { clearTimeout(triggerTimeout); contentDisposable.dispose(); blurDisposable.dispose(); + keyDownDisposable.dispose(); }; }; From 0f1b44e8f3fa8d509ccb43027d93f8ec60668c7c Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Fri, 20 Mar 2026 10:05:25 +0000 Subject: [PATCH 119/128] Step 5, Task 1: Relocate reusable utilities out of scrapbook Move connectToClient.ts, mongoConnectionStrings.ts, and mongoConnectionStrings.test.ts from src/documentdb/scrapbook/ to src/documentdb/. Update import paths in relocated files and extension.bundle.ts to reflect new locations. --- extension.bundle.ts | 4 +- src/documentdb/connectToClient.ts | 61 +++ src/documentdb/mongoConnectionStrings.test.ts | 400 ++++++++++++++++++ src/documentdb/mongoConnectionStrings.ts | 101 +++++ 4 files changed, 564 insertions(+), 2 deletions(-) create mode 100644 src/documentdb/connectToClient.ts create mode 100644 src/documentdb/mongoConnectionStrings.test.ts create mode 100644 src/documentdb/mongoConnectionStrings.ts diff --git a/extension.bundle.ts b/extension.bundle.ts index 547308d19..2c4f5314f 100644 --- a/extension.bundle.ts +++ b/extension.bundle.ts @@ -22,13 +22,13 @@ export { AzureAccountTreeItemBase, createAzureClient } from '@microsoft/vscode-a // eslint-disable-next-line no-restricted-imports -- bundle intentionally re-exports many helpers for tests; nonNull helpers are provided locally in this repo export * from '@microsoft/vscode-azext-utils'; export { isWindows, wellKnownEmulatorPassword } from './src/constants'; -export { connectToClient, isCosmosEmulatorConnectionString } from './src/documentdb/scrapbook/connectToClient'; +export { connectToClient, isCosmosEmulatorConnectionString } from './src/documentdb/connectToClient'; export { MongoCommand } from './src/documentdb/scrapbook/MongoCommand'; export { addDatabaseToAccountConnectionString, encodeMongoConnectionString, getDatabaseNameFromConnectionString, -} from './src/documentdb/scrapbook/mongoConnectionStrings'; +} from './src/documentdb/mongoConnectionStrings'; export * from './src/documentdb/scrapbook/registerScrapbookCommands'; export { findCommandAtPosition, getAllCommandsFromText } from './src/documentdb/scrapbook/ScrapbookHelpers'; export { ShellScriptRunner as MongoShell } from './src/documentdb/scrapbook/ShellScriptRunner'; diff --git a/src/documentdb/connectToClient.ts b/src/documentdb/connectToClient.ts new file mode 100644 index 000000000..2f20a9d6f --- /dev/null +++ b/src/documentdb/connectToClient.ts @@ -0,0 +1,61 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as l10n from '@vscode/l10n'; +import { MongoClient, type MongoClientOptions } from 'mongodb'; +import { Links, wellKnownEmulatorPassword } from '../constants'; +import { type EmulatorConfiguration } from '../utils/emulatorConfiguration'; + +export async function connectToClient( + connectionString: string, + appName: string, + emulatorConfiguration?: EmulatorConfiguration, +): Promise { + // appname appears to be the correct equivalent to user-agent for mongo + const options: MongoClientOptions = { + // appName should be wrapped in '@'s when trying to connect to a Mongo account, this doesn't effect the appendUserAgent string + appName: `${appName}[RU]`, + // https://github.com/lmammino/mongo-uri-builder/issues/2 + useNewUrlParser: true, + useUnifiedTopology: true, + }; + + if (emulatorConfiguration && emulatorConfiguration.isEmulator && emulatorConfiguration.disableEmulatorSecurity) { + // Prevents self signed certificate error for emulator https://github.com/microsoft/vscode-cosmosdb/issues/1241#issuecomment-614446198 + options.tlsAllowInvalidCertificates = true; + } + + try { + return await MongoClient.connect(connectionString, options); + } catch (err) { + // Note: This file can't use `parseError` from `@microsoft/vscode-azext-utils` because it's used by languageService.ts - see that file for more info + const error = <{ message?: string; name?: string }>err; + const message = error && error.message; + + // Example error: "failed to connect to server [localhost:10255] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:10255]" + // Example error: "failed to connect to server [127.0.0.1:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017]" + if (message && /ECONNREFUSED/.test(message) && /(localhost|127\.0\.0\.1)/.test(message)) { + throw new MongoConnectError(); + } + + // eslint-disable-next-line @typescript-eslint/only-throw-error + throw error; + } +} + +export class MongoConnectError extends Error { + constructor() { + super( + l10n.t( + 'Unable to connect to the local database instance. Make sure it is started correctly. See {link} for tips.', + { link: Links.LocalConnectionDebuggingTips }, + ), + ); + } +} + +export function isCosmosEmulatorConnectionString(connectionString: string): boolean { + return connectionString.includes(encodeURIComponent(wellKnownEmulatorPassword)); +} diff --git a/src/documentdb/mongoConnectionStrings.test.ts b/src/documentdb/mongoConnectionStrings.test.ts new file mode 100644 index 000000000..68af20c79 --- /dev/null +++ b/src/documentdb/mongoConnectionStrings.test.ts @@ -0,0 +1,400 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { wellKnownEmulatorPassword } from '../constants'; +import { isCosmosEmulatorConnectionString } from './connectToClient'; +import { + addDatabaseToAccountConnectionString, + encodeMongoConnectionString, + getDatabaseNameFromConnectionString, +} from './mongoConnectionStrings'; + +describe(`mongoCollectionStrings`, () => { + it(`getDatabaseNameFromConnectionString`, () => { + // Connection strings follow the following format (https://docs.mongodb.com/manual/reference/connection-string/): + // mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] + function testDatabaseNameFromConnectionString( + connectionString: string, + expectedDatabaseName: string | undefined, + ): void { + const databaseName = getDatabaseNameFromConnectionString(connectionString); + expect(databaseName).toEqual(expectedDatabaseName); + } + + // const databaseName = getDatabaseNameFromConnectionString(`mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`,); + // expect(databaseName).toEqual(undefined); + testDatabaseNameFromConnectionString( + `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, + undefined, + ); + testDatabaseNameFromConnectionString( + `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb`, + 'our-mongo', + ); + + testDatabaseNameFromConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, undefined); + testDatabaseNameFromConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118/`, undefined); + testDatabaseNameFromConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118/dbname`, `dbname`); + + testDatabaseNameFromConnectionString( + `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, + undefined, + ); + testDatabaseNameFromConnectionString( + `mongodb://db1.example.net:27017,db2.example.net:2500/my-database?replicaSet=test`, + 'my-database', + ); + + testDatabaseNameFromConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/`, undefined); + testDatabaseNameFromConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017`, undefined); + testDatabaseNameFromConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/db`, 'db'); + + testDatabaseNameFromConnectionString(`mongodb+srv://server.example.com/`, undefined); + testDatabaseNameFromConnectionString(`mongodb+srv://server.example.com/db`, 'db'); + + testDatabaseNameFromConnectionString( + `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, + undefined, + ); + testDatabaseNameFromConnectionString( + `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/MYDB?replicaSet=mySet&authSource=authDB`, + 'MYDB', + ); + + testDatabaseNameFromConnectionString( + `mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB`, + undefined, + ); + testDatabaseNameFromConnectionString( + `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/my_db?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB`, + 'my_db', + ); + testDatabaseNameFromConnectionString( + `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000`, + undefined, + ); + testDatabaseNameFromConnectionString( + `mongodb://host.example.com/hello?readPreference=secondary&maxStalenessSeconds=120`, + 'hello', + ); + testDatabaseNameFromConnectionString(`mongodb://localhost`, undefined); + testDatabaseNameFromConnectionString(`mongodb://localhost/db`, 'db'); + testDatabaseNameFromConnectionString(`mongodb://sysop:moon@localhost/records`, 'records'); + testDatabaseNameFromConnectionString(`mongodb://%2Ftmp%2Fmongodb-27017.sock/db`, 'db'); + testDatabaseNameFromConnectionString( + `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/abc`, + 'abc', + ); + + // special characters + testDatabaseNameFromConnectionString( + `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/def-ghi_jkl`, + 'def-ghi_jkl', + ); + testDatabaseNameFromConnectionString( + `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/Icantlikespaces`, + 'Icantlikespaces', + ); + + // emulator: mongodb://localhost:C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==@localhost:10255?ssl=true + testDatabaseNameFromConnectionString( + `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/admin?ssl=true`, + 'admin', + ); + testDatabaseNameFromConnectionString( + `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/admin-master?ssl=true`, + 'admin-master', + ); + // test characters mentioned in : https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Database-Names-for-Windows + testDatabaseNameFromConnectionString( + `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/admin!@%^()-_,[]?ssl=true`, + 'admin!@%^()-_,[]', + ); + }); + + it('addDatabaseToAccountConnectionString', () => { + function testDatabaseToAccountConnectionString( + connectionString: string, + databaseName: string, + expectedConnectionString: string | undefined, + ): void { + const databaseConnectionString = addDatabaseToAccountConnectionString(connectionString, databaseName); + expect(databaseConnectionString).toEqual(expectedConnectionString); + } + + testDatabaseToAccountConnectionString( + `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, + 'somedatabase', + 'mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/somedatabase?ssl=true&replicaSet=globaldb', + ); + testDatabaseToAccountConnectionString( + `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb`, + 'our-mongo', + 'mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb', + ); + + testDatabaseToAccountConnectionString( + `mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, + 'mydata', + 'mongodb://dbuser:dbpassword@dbname.mlab.com:14118/mydata', + ); + testDatabaseToAccountConnectionString( + `mongodb://dbuser:dbpassword@dbname.mlab.com:14118/`, + 'database', + 'mongodb://dbuser:dbpassword@dbname.mlab.com:14118/database', + ); + testDatabaseToAccountConnectionString( + `mongodb+srv://dbuser:dbpassword@dbname.mlab.com:14118/database`, + 'database', + 'mongodb+srv://dbuser:dbpassword@dbname.mlab.com:14118/database', + ); + + testDatabaseToAccountConnectionString( + `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, + 'my-database', + 'mongodb://db1.example.net:27017,db2.example.net:2500/my-database?replicaSet=test', + ); + testDatabaseToAccountConnectionString( + `mongodb://db1.example.net:27017,db2.example.net:2500/my-database?`, + 'my-database', + 'mongodb://db1.example.net:27017,db2.example.net:2500/my-database?', + ); + + testDatabaseToAccountConnectionString( + `mongodb://r1.example.net:27017,r2.example.net:27017/`, + 'undefined', + 'mongodb://r1.example.net:27017,r2.example.net:27017/undefined', + ); + testDatabaseToAccountConnectionString( + `mongodb://r1.example.net:27017,r2.example.net:27017`, + 'undefined', + 'mongodb://r1.example.net:27017,r2.example.net:27017/undefined', + ); + testDatabaseToAccountConnectionString( + `mongodb://r1.example.net:27017,r2.example.net:27017/{SQL}data`, + '(NoSQL)data', + 'mongodb://r1.example.net:27017,r2.example.net:27017/(NoSQL)data', + ); + + testDatabaseToAccountConnectionString( + `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, + 'undefined', + 'mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/undefined?replicaSet=mySet&authSource=authDB', + ); + testDatabaseToAccountConnectionString( + `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, + 'MYDB', + 'mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/MYDB?replicaSet=mySet&authSource=authDB', + ); + + testDatabaseToAccountConnectionString( + `mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB?`, + 'basetoadd', + 'mongodb+srv://server.example.com/basetoadd?connectTimeoutMS=300000&authSource=aDifferentAuthDB?', + ); + + testDatabaseToAccountConnectionString( + `mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB`, + '', + 'mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB', + ); + testDatabaseToAccountConnectionString( + `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/my_db?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB`, + 'not_mydatabase', + 'mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/not_mydatabase?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB', + ); + testDatabaseToAccountConnectionString( + `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000`, + '', + 'mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000', + ); + testDatabaseToAccountConnectionString( + `mongodb://host.example.com/hello?readPreference=secondary&maxStalenessSeconds=120`, + 'hellno', + 'mongodb://host.example.com/hellno?readPreference=secondary&maxStalenessSeconds=120', + ); + testDatabaseToAccountConnectionString(`mongodb://localhost`, '', 'mongodb://localhost/'); + testDatabaseToAccountConnectionString( + `mongodb://localhost/db`, + 'new{}db', + `mongodb://localhost/${encodeURIComponent('new{}db')}`, + ); + testDatabaseToAccountConnectionString( + `mongodb://sysop:moon@localhost/records`, + 'records', + 'mongodb://sysop:moon@localhost/records', + ); + testDatabaseToAccountConnectionString( + `mongodb://%2Ftmp%2Fmongodb-27017.sock/onemorefundatabase`, + 'notfun', + 'mongodb://%2Ftmp%2Fmongodb-27017.sock/notfun', + ); + testDatabaseToAccountConnectionString( + `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/wowsomethingnew?ssl=true`, + 'notsure', + 'mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/notsure?ssl=true', + ); + + // special characters + testDatabaseToAccountConnectionString( + `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/?`, + 'def-ghi_jkl', + 'mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/def-ghi_jkl?', + ); + testDatabaseToAccountConnectionString( + `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017`, + 'icantlikespaces', + 'mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/icantlikespaces', + ); + + // Emulator + testDatabaseToAccountConnectionString( + `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/?ssl=true`, + 'admin', + `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/admin?ssl=true`, + ); + // Collection within emulator + testDatabaseToAccountConnectionString( + `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/?ssl=true`, + 'admin-master', + `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/admin-master?ssl=true`, + ); + testDatabaseToAccountConnectionString( + `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/?ssl=true`, + 'admin!@%^()-_,[]', + `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/${encodeURIComponent('admin!@%^()-_,[]')}?ssl=true`, + ); + }); + + it('isCosmosEmulatorConnectionString', () => { + function testIsCosmosEmulatorConnectionString(connectionString: string, expected: boolean): void { + const actual: boolean = isCosmosEmulatorConnectionString(connectionString); + expect(actual).toEqual(expected); + } + + testIsCosmosEmulatorConnectionString( + `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, + false, + ); + testIsCosmosEmulatorConnectionString( + `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb`, + false, + ); + + testIsCosmosEmulatorConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, false); + testIsCosmosEmulatorConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118/`, false); + testIsCosmosEmulatorConnectionString(`mongodb+srv://dbuser:dbpassword@dbname.mlab.com:14118/database`, false); + + testIsCosmosEmulatorConnectionString( + `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, + false, + ); + testIsCosmosEmulatorConnectionString( + `mongodb://db1.example.net:27017,db2.example.net:2500/my-database?`, + false, + ); + + testIsCosmosEmulatorConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/`, false); + testIsCosmosEmulatorConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017`, false); + testIsCosmosEmulatorConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/{SQL}data`, false); + + testIsCosmosEmulatorConnectionString( + `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, + false, + ); + testIsCosmosEmulatorConnectionString( + `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, + false, + ); + + testIsCosmosEmulatorConnectionString( + `mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB`, + false, + ); + testIsCosmosEmulatorConnectionString( + `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/my_db?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB`, + false, + ); + testIsCosmosEmulatorConnectionString( + `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000`, + false, + ); + testIsCosmosEmulatorConnectionString( + `mongodb://host.example.com/hello?readPreference=secondary&maxStalenessSeconds=120`, + false, + ); + testIsCosmosEmulatorConnectionString(`mongodb://localhost`, false); + testIsCosmosEmulatorConnectionString(`mongodb://localhost/db`, false); + testIsCosmosEmulatorConnectionString(`mongodb://sysop:moon@localhost/records`, false); + testIsCosmosEmulatorConnectionString(`mongodb://%2Ftmp%2Fmongodb-27017.sock/onemorefundatabase`, false); + testIsCosmosEmulatorConnectionString( + `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/wowsomethingnew?ssl=true`, + false, + ); + + testIsCosmosEmulatorConnectionString( + `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/abc...`, + false, + ); + testIsCosmosEmulatorConnectionString( + `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/?`, + false, + ); + testIsCosmosEmulatorConnectionString( + `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017`, + false, + ); + + // Emulator + testIsCosmosEmulatorConnectionString( + `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/?ssl=true`, + true, + ); + testIsCosmosEmulatorConnectionString( + `mongodb://127.0.0.1:${encodeURIComponent(wellKnownEmulatorPassword)}@127.0.0.1:10255/?ssl=true`, + true, + ); + testIsCosmosEmulatorConnectionString( + `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/database?ssl=true`, + true, + ); + }); + + it('encodeMongoConnectionString', () => { + function testEncodeMongoConnectionString(connectionString: string, expectedConnectionString: string): void { + connectionString = encodeMongoConnectionString(connectionString); + expect(connectionString).toEqual(expectedConnectionString); + } + testEncodeMongoConnectionString( + `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, + `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg%3D%3D@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, + ); + testEncodeMongoConnectionString( + `mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, + `mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, + ); + testEncodeMongoConnectionString( + `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, + `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, + ); + testEncodeMongoConnectionString( + `mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB?`, + `mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB?`, + ); + testEncodeMongoConnectionString(`mongodb://localhost`, `mongodb://localhost`); + testEncodeMongoConnectionString( + `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/?ssl=true`, + `mongodb://localhost:${encodeURIComponent(encodeURIComponent(wellKnownEmulatorPassword))}@localhost:10255/?ssl=true`, + ); + testEncodeMongoConnectionString( + `mongodb://username@example.com:password@localhost/`, + `mongodb://username%40example.com:password@localhost/`, + ); + testEncodeMongoConnectionString( + `mongodb://crazy@:/%username:even@crazier%/password@localhost/`, + `mongodb://crazy%40%3A%2F%25username:even%40crazier%25%2Fpassword@localhost/`, + ); + }); +}); diff --git a/src/documentdb/mongoConnectionStrings.ts b/src/documentdb/mongoConnectionStrings.ts new file mode 100644 index 000000000..cbeb57ab0 --- /dev/null +++ b/src/documentdb/mongoConnectionStrings.ts @@ -0,0 +1,101 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { appendExtensionUserAgent, parseError, type IParsedError } from '@microsoft/vscode-azext-utils'; +import { type MongoClient } from 'mongodb'; +import { ParsedConnectionString } from '../ParsedConnectionString'; +import { nonNullValue } from '../utils/nonNull'; +import { connectToClient } from './connectToClient'; + +// Connection strings follow the following format (https://docs.mongodb.com/manual/reference/connection-string/): +// mongodb[+srv]://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] +// Some example connection strings: +// mongodb://dbuser:dbpassword@dbname.mlab.com:14118 +// mongodb+srv://db1.example.net:27017,db2.example.net:2500/?replicaSet=test +// mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/database?ssh=true +// Regex splits into three parts: +// Full match +// mongodb[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]] +// [database] + +const parsePrefix = '([a-zA-Z]+://[^/]*)'; +const parseDatabaseName = '/?([^/?]+)?'; +const mongoConnectionStringRegExp = new RegExp(parsePrefix + parseDatabaseName); + +export function getDatabaseNameFromConnectionString(connectionString: string): string | undefined { + try { + const [, , databaseName] = nonNullValue( + connectionString.match(mongoConnectionStringRegExp), + 'connectionString.match(mongoConnectionStringRegExp)', + 'mongoConnectionStrings.ts', + ); + return databaseName; + } catch { + // Shouldn't happen, but ignore if does + } + + return undefined; +} + +export function addDatabaseToAccountConnectionString(connectionString: string, databaseName: string): string { + try { + return connectionString.replace(mongoConnectionStringRegExp, `$1/${encodeURIComponent(databaseName)}`); + } catch { + // Shouldn't happen, but ignore if does. Original connection string could be in a format we don't expect, but might already have the db name or might still work without it + return connectionString; + } +} + +export async function parseMongoConnectionString(connectionString: string): Promise { + let mongoClient: MongoClient; + try { + mongoClient = await connectToClient(connectionString, appendExtensionUserAgent()); + } catch (error) { + const parsedError: IParsedError = parseError(error); + if (parsedError.message.match(/unescaped/i)) { + // Prevents https://github.com/microsoft/vscode-cosmosdb/issues/1209 + connectionString = encodeMongoConnectionString(connectionString); + mongoClient = await connectToClient(connectionString, appendExtensionUserAgent()); + } else { + throw error; + } + } + + const { host, port } = mongoClient.options.hosts[0]; + + return new ParsedMongoConnectionString( + connectionString, + host as string, + (port as number).toString(), + getDatabaseNameFromConnectionString(connectionString), + ); +} + +export class ParsedMongoConnectionString extends ParsedConnectionString { + public readonly hostName: string; + public readonly port: string; + + constructor(connectionString: string, hostName: string, port: string, databaseName: string | undefined) { + super(connectionString, databaseName); + this.hostName = hostName; + this.port = port; + } +} + +/** + * Encodes the username and password in the given Mongo DB connection string. + */ +export function encodeMongoConnectionString(connectionString: string): string { + const matches: RegExpMatchArray | null = connectionString.match(/^(.*):\/\/(.*):(.*)@(.*)/); + if (matches) { + const prefix: string = matches[1]; + const username: string = matches[2]; + const password: string = matches[3]; + const hostAndQuery: string = matches[4]; + connectionString = `${prefix}://${encodeURIComponent(username)}:${encodeURIComponent(password)}@${hostAndQuery}`; + } + + return connectionString; +} From 1c9718eefd96db3efdee9415e6c34f1efefa1884 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Fri, 20 Mar 2026 10:05:57 +0000 Subject: [PATCH 120/128] Step 5, Task 2: Delete scrapbook source files, commands, and grammar Remove entire src/documentdb/scrapbook/ directory (17 files), src/commands/scrapbook-commands/ (4 files), src/documentdb/grammar/ (7 ANTLR-generated files), and root grammar/ directory (5 files). --- grammar/JavaScript.tmLanguage.json | 3711 ----------------- grammar/Readme.md | 10 - ...egular Expressions (JavaScript).tmLanguage | 240 -- grammar/configuration.json | 39 - grammar/mongo.g4 | 109 - .../scrapbook-commands/connectCluster.ts | 31 - .../scrapbook-commands/createScrapbook.ts | 24 - .../scrapbook-commands/executeAllCommand.ts | 21 - .../scrapbook-commands/executeCommand.ts | 24 - src/documentdb/grammar/mongo.tokens | 36 - src/documentdb/grammar/mongoLexer.tokens | 36 - src/documentdb/grammar/mongoLexer.ts | 316 -- src/documentdb/grammar/mongoListener.ts | 225 - src/documentdb/grammar/mongoParser.ts | 1561 ------- src/documentdb/grammar/mongoVisitor.ts | 160 - src/documentdb/grammar/visitors.ts | 90 - src/documentdb/scrapbook/MongoCommand.ts | 24 - src/documentdb/scrapbook/ScrapbookHelpers.ts | 466 --- src/documentdb/scrapbook/ScrapbookService.ts | 295 -- src/documentdb/scrapbook/ShellScriptRunner.ts | 486 --- src/documentdb/scrapbook/connectToClient.ts | 61 - src/documentdb/scrapbook/errorListeners.ts | 67 - src/documentdb/scrapbook/languageClient.ts | 88 - src/documentdb/scrapbook/languageServer.ts | 21 - .../scrapbook/mongoConnectionStrings.test.ts | 400 -- .../scrapbook/mongoConnectionStrings.ts | 101 - .../scrapbook/registerScrapbookCommands.ts | 116 - .../scrapbook/services/IConnectionParams.ts | 13 - .../services/MongoCodeLensProvider.ts | 112 - .../services/completionItemProvider.ts | 507 --- .../scrapbook/services/languageService.ts | 121 - .../scrapbook/services/mongoScript.ts | 120 - .../scrapbook/services/schemaService.ts | 666 --- 33 files changed, 10297 deletions(-) delete mode 100644 grammar/JavaScript.tmLanguage.json delete mode 100644 grammar/Readme.md delete mode 100644 grammar/Regular Expressions (JavaScript).tmLanguage delete mode 100644 grammar/configuration.json delete mode 100644 grammar/mongo.g4 delete mode 100644 src/commands/scrapbook-commands/connectCluster.ts delete mode 100644 src/commands/scrapbook-commands/createScrapbook.ts delete mode 100644 src/commands/scrapbook-commands/executeAllCommand.ts delete mode 100644 src/commands/scrapbook-commands/executeCommand.ts delete mode 100644 src/documentdb/grammar/mongo.tokens delete mode 100644 src/documentdb/grammar/mongoLexer.tokens delete mode 100644 src/documentdb/grammar/mongoLexer.ts delete mode 100644 src/documentdb/grammar/mongoListener.ts delete mode 100644 src/documentdb/grammar/mongoParser.ts delete mode 100644 src/documentdb/grammar/mongoVisitor.ts delete mode 100644 src/documentdb/grammar/visitors.ts delete mode 100644 src/documentdb/scrapbook/MongoCommand.ts delete mode 100644 src/documentdb/scrapbook/ScrapbookHelpers.ts delete mode 100644 src/documentdb/scrapbook/ScrapbookService.ts delete mode 100644 src/documentdb/scrapbook/ShellScriptRunner.ts delete mode 100644 src/documentdb/scrapbook/connectToClient.ts delete mode 100644 src/documentdb/scrapbook/errorListeners.ts delete mode 100644 src/documentdb/scrapbook/languageClient.ts delete mode 100644 src/documentdb/scrapbook/languageServer.ts delete mode 100644 src/documentdb/scrapbook/mongoConnectionStrings.test.ts delete mode 100644 src/documentdb/scrapbook/mongoConnectionStrings.ts delete mode 100644 src/documentdb/scrapbook/registerScrapbookCommands.ts delete mode 100644 src/documentdb/scrapbook/services/IConnectionParams.ts delete mode 100644 src/documentdb/scrapbook/services/MongoCodeLensProvider.ts delete mode 100644 src/documentdb/scrapbook/services/completionItemProvider.ts delete mode 100644 src/documentdb/scrapbook/services/languageService.ts delete mode 100644 src/documentdb/scrapbook/services/mongoScript.ts delete mode 100644 src/documentdb/scrapbook/services/schemaService.ts diff --git a/grammar/JavaScript.tmLanguage.json b/grammar/JavaScript.tmLanguage.json deleted file mode 100644 index 0191da450..000000000 --- a/grammar/JavaScript.tmLanguage.json +++ /dev/null @@ -1,3711 +0,0 @@ -{ - "name.$comment": "** Changed **", - "name": "DocumentDB & MongoDB Scrapbooks (JavaScript)", - "scopeName.$comment": "** Changed **", - "scopeName": "source.mongo.js", - "fileTypes.$comment": "** Changed from .js/.jsx **", - "fileTypes": [".vscode-documentdb-scrapbook"], - "uuid.$comment": "** Changed **", - "uuid": "311c363f-7b1d-4dc4-b237-da46f717cca4", - "patterns": [ - { - "include": "#directives" - }, - { - "include": "#statements" - }, - { - "name": "comment.line.shebang.ts", - "match": "\\A(#!).*(?=$)", - "captures": { - "1": { - "name": "punctuation.definition.comment.ts" - } - } - } - ], - "repository": { - "statements": { - "patterns": [ - { - "include": "#string" - }, - { - "include": "#template" - }, - { - "include": "#comment" - }, - { - "include": "#declaration" - }, - { - "include": "#switch-statement" - }, - { - "include": "#for-loop" - }, - { - "include": "#after-operator-block" - }, - { - "include": "#decl-block" - }, - { - "include": "#control-statement" - }, - { - "include": "#expression" - }, - { - "include": "#punctuation-semicolon" - } - ] - }, - "var-expr": { - "name": "meta.var.expr.js", - "begin": "(?) |\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))\n ) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n )))\n )\n)", - "beginCaptures": { - "1": { - "name": "meta.definition.variable.js entity.name.function.js" - } - }, - "end": "(?=$|[;,=}]|(\\s+(of|in)\\s+))", - "patterns": [ - { - "include": "#var-single-variable-type-annotation" - } - ] - }, - { - "name": "meta.var-single-variable.expr.js", - "begin": "([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])", - "beginCaptures": { - "1": { - "name": "meta.definition.variable.js variable.other.constant.js" - } - }, - "end": "(?=$|[;,=}]|(\\s+(of|in)\\s+))", - "patterns": [ - { - "include": "#var-single-variable-type-annotation" - } - ] - }, - { - "name": "meta.var-single-variable.expr.js", - "begin": "([_$[:alpha:]][_$[:alnum:]]*)", - "beginCaptures": { - "1": { - "name": "meta.definition.variable.js variable.other.readwrite.js" - } - }, - "end": "(?=$|[;,=}]|(\\s+(of|in)\\s+))", - "patterns": [ - { - "include": "#var-single-variable-type-annotation" - } - ] - } - ] - }, - "var-single-variable-type-annotation": { - "patterns": [ - { - "include": "#type-annotation" - }, - { - "include": "#string" - }, - { - "include": "#comment" - } - ] - }, - "destructuring-variable": { - "patterns": [ - { - "name": "meta.object-binding-pattern-variable.js", - "begin": "(?) |\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))\n ) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n )))\n )\n)" - }, - { - "name": "meta.definition.property.js variable.object.property.js", - "match": "[_$[:alpha:]][_$[:alnum:]]*" - }, - { - "name": "keyword.operator.optional.js", - "match": "\\?" - } - ] - } - ] - }, - "method-declaration": { - "name": "meta.method.declaration.js", - "begin": "(?) |\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))\n ) |\n (:\\s*(\n (<) |\n ([(]\\s*(\n ([)]) |\n (\\.\\.\\.) |\n ([_$[:alnum:]]+\\s*(\n ([:,?=])|\n ([)]\\s*=>)\n ))\n )))\n )\n)", - "captures": { - "1": { - "name": "storage.modifier.js" - }, - "2": { - "name": "keyword.operator.rest.js" - }, - "3": { - "name": "entity.name.function.js" - }, - "4": { - "name": "keyword.operator.optional.js" - } - } - }, - { - "match": "(?:\\s*\\b(public|private|protected|readonly)\\s+)?(\\.\\.\\.)?\\s*(?])|(?<=[\\}>\\]\\)]|[_$[:alpha:]])\\s*(?=\\{)", - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#type" - } - ] - }, - "type": { - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#string" - }, - { - "include": "#numeric-literal" - }, - { - "include": "#type-primitive" - }, - { - "include": "#type-builtin-literals" - }, - { - "include": "#type-parameters" - }, - { - "include": "#type-tuple" - }, - { - "include": "#type-object" - }, - { - "include": "#type-operators" - }, - { - "include": "#type-fn-type-parameters" - }, - { - "include": "#type-paren-or-function-parameters" - }, - { - "include": "#type-function-return-type" - }, - { - "include": "#type-name" - } - ] - }, - "function-parameters": { - "name": "meta.parameters.js", - "begin": "\\(", - "beginCaptures": { - "0": { - "name": "punctuation.definition.parameters.begin.js" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "punctuation.definition.parameters.end.js" - } - }, - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#decorator" - }, - { - "include": "#destructuring-parameter" - }, - { - "include": "#parameter-name" - }, - { - "include": "#type-annotation" - }, - { - "include": "#variable-initializer" - }, - { - "name": "punctuation.separator.parameter.js", - "match": "," - } - ] - }, - "type-primitive": { - "name": "support.type.primitive.js", - "match": "(?)\n ))\n )\n )\n)", - "end": "(?<=\\))", - "patterns": [ - { - "include": "#function-parameters" - } - ] - } - ] - }, - "type-operators": { - "patterns": [ - { - "include": "#typeof-operator" - }, - { - "name": "keyword.operator.type.js", - "match": "[&|]" - }, - { - "name": "keyword.operator.expression.keyof.js", - "match": "(?", - "beginCaptures": { - "0": { - "name": "storage.type.function.arrow.js" - } - }, - "end": "(?)(?=[,\\]\\)\\{\\}=;>]|//|$)", - "patterns": [ - { - "include": "#comment" - }, - { - "name": "meta.object.type.js", - "begin": "(?<==>)\\s*(\\{)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.block.js" - } - }, - "end": "\\}", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.js" - } - }, - "patterns": [ - { - "include": "#type-object-members" - } - ] - }, - { - "include": "#type-predicate-operator" - }, - { - "include": "#type" - } - ] - }, - "type-tuple": { - "name": "meta.type.tuple.js", - "begin": "\\[", - "beginCaptures": { - "0": { - "name": "meta.brace.square.js" - } - }, - "end": "\\]", - "endCaptures": { - "0": { - "name": "meta.brace.square.js" - } - }, - "patterns": [ - { - "include": "#type" - }, - { - "include": "#punctuation-comma" - } - ] - }, - "type-name": { - "patterns": [ - { - "match": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(\\.)", - "captures": { - "1": { - "name": "entity.name.type.module.js" - }, - "2": { - "name": "punctuation.accessor.js" - } - } - }, - { - "name": "entity.name.type.js", - "match": "[_$[:alpha:]][_$[:alnum:]]*" - } - ] - }, - "type-parameters": { - "name": "meta.type.parameters.js", - "begin": "(<)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.typeparameters.begin.js" - } - }, - "end": "(?=$)|(>)", - "endCaptures": { - "1": { - "name": "punctuation.definition.typeparameters.end.js" - } - }, - "patterns": [ - { - "include": "#comment" - }, - { - "name": "storage.modifier.js", - "match": "(?)" - }, - { - "include": "#type" - }, - { - "include": "#punctuation-comma" - } - ] - }, - "variable-initializer": { - "patterns": [ - { - "begin": "(?]|\\<[^<>]+\\>)+>\\s*)?\\()", - "captures": { - "1": { - "name": "punctuation.accessor.js" - }, - "2": { - "name": "support.constant.dom.js" - }, - "3": { - "name": "support.variable.property.dom.js" - } - } - }, - { - "name": "support.class.node.js", - "match": "(?x)(?]|\\<[^<>]+\\>)+>\\s*)?\\()", - "end": "(?<=\\))(?!(([_$[:alpha:]][_$[:alnum:]]*\\s*\\.\\s*)*|(\\.\\s*)?)([_$[:alpha:]][_$[:alnum:]]*)\\s*(<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\()", - "patterns": [ - { - "include": "#literal" - }, - { - "include": "#support-objects" - }, - { - "include": "#object-identifiers" - }, - { - "include": "#punctuation-accessor" - }, - { - "name": "entity.name.function.js", - "match": "([_$[:alpha:]][_$[:alnum:]]*)" - }, - { - "include": "#comment" - }, - { - "name": "meta.type.parameters.js", - "begin": "\\<", - "beginCaptures": { - "0": { - "name": "punctuation.definition.typeparameters.begin.js" - } - }, - "end": "\\>", - "endCaptures": { - "0": { - "name": "punctuation.definition.typeparameters.end.js" - } - }, - "patterns": [ - { - "include": "#type" - }, - { - "include": "#punctuation-comma" - } - ] - }, - { - "include": "#paren-expression" - } - ] - }, - "identifiers": { - "patterns": [ - { - "include": "#object-identifiers" - }, - { - "match": "(?x)(?:(\\.)\\s*)?([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*=\\s*(\n (async\\s+)|(function\\s*[(<])|(function\\s+)|\n ([_$[:alpha:]][_$[:alnum:]]*\\s*=>)|\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>)))", - "captures": { - "1": { - "name": "punctuation.accessor.js" - }, - "2": { - "name": "entity.name.function.js" - } - } - }, - { - "match": "(\\.)\\s*([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])", - "captures": { - "1": { - "name": "punctuation.accessor.js" - }, - "2": { - "name": "variable.other.constant.property.js" - } - } - }, - { - "match": "(\\.)\\s*([_$[:alpha:]][_$[:alnum:]]*)", - "captures": { - "1": { - "name": "punctuation.accessor.js" - }, - "2": { - "name": "variable.other.property.js" - } - } - }, - { - "name": "variable.other.constant.js", - "match": "([[:upper:]][_$[:digit:][:upper:]]*)(?![_$[:alnum:]])" - }, - { - "name": "variable.other.readwrite.js", - "match": "[_$[:alpha:]][_$[:alnum:]]*" - } - ] - }, - "object-identifiers": { - "patterns": [ - { - "name": "support.class.js", - "match": "([_$[:alpha:]][_$[:alnum:]]*)(?=\\s*\\.\\s*prototype\\b(?!\\$))" - }, - { - "match": "(?x)(\\.)\\s*(?:\n ([[:upper:]][_$[:digit:][:upper:]]*) |\n ([_$[:alpha:]][_$[:alnum:]]*)\n)(?=\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)", - "captures": { - "1": { - "name": "punctuation.accessor.js" - }, - "2": { - "name": "variable.other.constant.object.property.js" - }, - "3": { - "name": "variable.other.object.property.js" - } - } - }, - { - "match": "(?x)(?:\n ([[:upper:]][_$[:digit:][:upper:]]*) |\n ([_$[:alpha:]][_$[:alnum:]]*)\n)(?=\\s*\\.\\s*[_$[:alpha:]][_$[:alnum:]]*)", - "captures": { - "1": { - "name": "variable.other.constant.object.js" - }, - "2": { - "name": "variable.other.object.js" - } - } - } - ] - }, - "cast": { - "patterns": [ - { - "include": "#jsx" - } - ] - }, - "new-expr": { - "name": "new.expr.js", - "begin": "(?)|\n ([(]\\s*(([)]\\s*:)|([_$[:alpha:]][_$[:alnum:]]*\\s*:)|(\\.\\.\\.) )) |\n ([<]\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s*[^=>])|(\\s*[,]))) |\n ((<([^<>]|\\<[^<>]+\\>)+>\\s*)?\\(([^()]|\\([^()]*\\))*\\)(\\s*:\\s*(.)*)?\\s*=>))))", - "beginCaptures": { - "0": { - "name": "meta.object-literal.key.js" - }, - "1": { - "name": "entity.name.function.js" - }, - "2": { - "name": "punctuation.separator.key-value.js" - } - }, - "end": "(?=,|\\})", - "patterns": [ - { - "include": "#expression" - } - ] - }, - { - "name": "meta.object.member.js", - "begin": "(?:[_$[:alpha:]][_$[:alnum:]]*)\\s*(:)", - "beginCaptures": { - "0": { - "name": "meta.object-literal.key.js" - }, - "1": { - "name": "punctuation.separator.key-value.js" - } - }, - "end": "(?=,|\\})", - "patterns": [ - { - "include": "#expression" - } - ] - }, - { - "name": "meta.object.member.js", - "begin": "\\.\\.\\.", - "beginCaptures": { - "0": { - "name": "keyword.operator.spread.js" - } - }, - "end": "(?=,|\\})", - "patterns": [ - { - "include": "#expression" - } - ] - }, - { - "name": "meta.object.member.js", - "match": "([_$[:alpha:]][_$[:alnum:]]*)\\s*(?=,|\\}|$)", - "captures": { - "1": { - "name": "variable.other.readwrite.js" - } - } - }, - { - "include": "#punctuation-comma" - } - ] - }, - "expression-operators": { - "patterns": [ - { - "name": "keyword.control.flow.js", - "match": "(?>=|>>>=|\\|=" - }, - { - "name": "keyword.operator.bitwise.shift.js", - "match": "<<|>>>|>>" - }, - { - "name": "keyword.operator.comparison.js", - "match": "===|!==|==|!=" - }, - { - "name": "keyword.operator.relational.js", - "match": "<=|>=|<>|<|>" - }, - { - "name": "keyword.operator.logical.js", - "match": "\\!|&&|\\|\\|" - }, - { - "name": "keyword.operator.bitwise.js", - "match": "\\&|~|\\^|\\|" - }, - { - "name": "keyword.operator.assignment.js", - "match": "\\=" - }, - { - "name": "keyword.operator.decrement.js", - "match": "--" - }, - { - "name": "keyword.operator.increment.js", - "match": "\\+\\+" - }, - { - "name": "keyword.operator.arithmetic.js", - "match": "%|\\*|/|-|\\+" - }, - { - "match": "(?<=[_$[:alnum:])])\\s*(/)(?![/*])", - "captures": { - "1": { - "name": "keyword.operator.arithmetic.js" - } - } - } - ] - }, - "typeof-operator": { - "name": "keyword.operator.expression.typeof.js", - "match": "(?)", - "captures": { - "1": { - "name": "storage.modifier.async.js" - }, - "2": { - "name": "variable.parameter.js" - } - } - }, - { - "name": "meta.arrow.js", - "begin": "(?x) (?:\n (? is on new line\n (\n [(]\\s*\n (\n ([)]\\s*:) | # ():\n ([_$[:alpha:]][_$[:alnum:]]*\\s*:) | # [(]param:\n (\\.\\.\\.) # [(]...\n )\n ) |\n (\n [<]\\s*[_$[:alpha:]][_$[:alnum:]]*\\s+extends\\s*[^=>] # < typeparam extends \n ) |\n # arrow function possible to detect only with => on same line\n (\n (<([^<>]|\\<[^<>]+\\>)+>\\s*)? # typeparameters\n \\(([^()]|\\([^()]*\\))*\\) # parameteres\n (\\s*:\\s*(.)*)? # return type\n \\s*=> # arrow operator\n )\n )\n)", - "beginCaptures": { - "1": { - "name": "storage.modifier.async.js" - } - }, - "end": "(?==>|\\{)", - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#type-parameters" - }, - { - "include": "#function-parameters" - }, - { - "include": "#arrow-return-type" - } - ] - }, - { - "name": "meta.arrow.js", - "begin": "=>", - "beginCaptures": { - "0": { - "name": "storage.type.function.arrow.js" - } - }, - "end": "(?<=\\})|((?!\\{)(?=\\S))", - "patterns": [ - { - "include": "#decl-block" - }, - { - "include": "#expression" - } - ] - } - ] - }, - "arrow-return-type": { - "name": "meta.return.type.arrow.js", - "begin": "(?<=\\))\\s*(:)", - "beginCaptures": { - "1": { - "name": "keyword.operator.type.annotation.js" - } - }, - "end": "(?==>|\\{)", - "patterns": [ - { - "name": "meta.object.type.js", - "begin": "(?<=:)\\s*(\\{)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.block.js" - } - }, - "end": "\\}", - "endCaptures": { - "0": { - "name": "punctuation.definition.block.js" - } - }, - "patterns": [ - { - "include": "#type-object-members" - } - ] - }, - { - "include": "#type-predicate-operator" - }, - { - "include": "#type" - } - ] - }, - "punctuation-comma": { - "name": "punctuation.separator.comma.js", - "match": "," - }, - "punctuation-semicolon": { - "name": "punctuation.terminator.statement.js", - "match": ";" - }, - "punctuation-accessor": { - "name": "punctuation.accessor.js", - "match": "\\." - }, - "paren-expression": { - "begin": "\\(", - "beginCaptures": { - "0": { - "name": "meta.brace.round.js" - } - }, - "end": "\\)", - "endCaptures": { - "0": { - "name": "meta.brace.round.js" - } - }, - "patterns": [ - { - "include": "#expression" - }, - { - "include": "#punctuation-comma" - } - ] - }, - "qstring-double": { - "name": "string.quoted.double.js", - "begin": "\"", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.js" - } - }, - "end": "(\")|((?:[^\\\\\\n])$)", - "endCaptures": { - "1": { - "name": "punctuation.definition.string.end.js" - }, - "2": { - "name": "invalid.illegal.newline.js" - } - }, - "patterns": [ - { - "include": "#string-character-escape" - } - ] - }, - "qstring-single": { - "name": "string.quoted.single.js", - "begin": "'", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.js" - } - }, - "end": "(\\')|((?:[^\\\\\\n])$)", - "endCaptures": { - "1": { - "name": "punctuation.definition.string.end.js" - }, - "2": { - "name": "invalid.illegal.newline.js" - } - }, - "patterns": [ - { - "include": "#string-character-escape" - } - ] - }, - "regex": { - "patterns": [ - { - "name": "string.regexp.js", - "begin": "(?<=[=(:,\\[?+!]|return|case|=>|&&|\\|\\||\\*\\/)\\s*(/)(?![/*])(?=(?:[^/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+/(?![/*])[gimy]*(?!\\s*[a-zA-Z0-9_$]))", - "beginCaptures": { - "1": { - "name": "punctuation.definition.string.begin.js" - } - }, - "end": "(/)([gimuy]*)", - "endCaptures": { - "1": { - "name": "punctuation.definition.string.end.js" - }, - "2": { - "name": "keyword.other.js" - } - }, - "patterns": [ - { - "include": "#regexp" - } - ] - }, - { - "name": "string.regexp.js", - "begin": "(?\\s*$)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.comment.js" - } - }, - "end": "(?=$)", - "patterns": [ - { - "name": "meta.tag.js", - "begin": "(<)(reference|amd-dependency|amd-module)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.directive.js" - }, - "2": { - "name": "entity.name.tag.directive.js" - } - }, - "end": "/>", - "endCaptures": { - "0": { - "name": "punctuation.definition.tag.directive.js" - } - }, - "patterns": [ - { - "name": "entity.other.attribute-name.directive.js", - "match": "path|types|no-default-lib|name" - }, - { - "name": "keyword.operator.assignment.js", - "match": "=" - }, - { - "include": "#string" - } - ] - } - ] - }, - "docblock": { - "patterns": [ - { - "name": "storage.type.class.jsdoc", - "match": "(?x)(? # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n (?:\n [\\w$]*\n (?:\\[\\])? # {(string|number[])} type application, a string or an array of numbers\n ) |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n \\) |\n [a-zA-Z_$]+\n (?:\n (?:\n [\\w$]*\n (?:\\[\\])? # {(string|number[])} type application, a string or an array of numbers\n ) |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n )\n )\n # Check for suffix\n (?:\\[\\])? # {string[]} type application, an array of strings\n =? # {string=} optional parameter\n )\n)})\n\n\\s+\n\n(\n \\[ # [foo] optional parameter\n \\s*\n (?:\n [a-zA-Z_$][\\w$]*\n (?:\n (?:\\[\\])? # Foo[].bar properties within an array\n \\. # Foo.Bar namespaced parameter\n [a-zA-Z_$][\\w$]*\n )*\n (?:\n \\s*\n = # [foo=bar] Default parameter value\n \\s*\n [\\w$\\s]*\n )?\n )\n \\s*\n \\] |\n (?:\n [a-zA-Z_$][\\w$]*\n (?:\n (?:\\[\\])? # Foo[].bar properties within an array\n \\. # Foo.Bar namespaced parameter\n [a-zA-Z_$][\\w$]*\n )*\n )?\n)\n\n\\s+\n\n(?:-\\s+)? # optional hyphen before the description\n\n((?:(?!\\*\\/).)*) # The type description", - "captures": { - "0": { - "name": "other.meta.jsdoc" - }, - "1": { - "name": "entity.name.type.instance.jsdoc" - }, - "2": { - "name": "variable.other.jsdoc" - }, - "3": { - "name": "other.description.jsdoc" - } - } - }, - { - "match": "(?x)\n\n({(?:\n \\* | # {*} any type\n \\? | # {?} unknown type\n\n (?:\n (?: # Check for a prefix\n \\? | # {?string} nullable type\n ! | # {!string} non-nullable type\n \\.{3} # {...string} variable number of parameters\n )?\n\n (?:\n (?:\n function # {function(string, number)} function type\n \\s*\n \\(\n \\s*\n (?:\n [a-zA-Z_$][\\w$]*\n (?:\n \\s*,\\s*\n [a-zA-Z_$][\\w$]*\n )*\n )?\n \\s*\n \\)\n (?: # {function(): string} function return type\n \\s*:\\s*\n [a-zA-Z_$][\\w$]*\n )?\n )?\n |\n (?:\n \\( # Opening bracket of multiple types with parenthesis {(string|number)}\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n \\) |\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n (?:\n [\\.|~] # {Foo.bar} namespaced, {string|number} multiple, {Foo~bar} class-specific callback\n [a-zA-Z_$]+\n (?:\n [\\w$]* |\n \\.?<[\\w$]+(?:,\\s+[\\w$]+)*> # {Array} or {Object} type application (optional .)\n )\n )*\n )\n )\n # Check for suffix\n (?:\\[\\])? # {string[]} type application, an array of strings\n =? # {string=} optional parameter\n )\n)})\n\n\\s+\n\n(?:-\\s+)? # optional hyphen before the description\n\n((?:(?!\\*\\/).)*) # The type description", - "captures": { - "0": { - "name": "other.meta.jsdoc" - }, - "1": { - "name": "entity.name.type.instance.jsdoc" - }, - "2": { - "name": "other.description.jsdoc" - } - } - } - ] - }, - "jsx-tag-attributes": { - "patterns": [ - { - "include": "#jsx-tag-attribute-name" - }, - { - "include": "#jsx-tag-attribute-assignment" - }, - { - "include": "#jsx-string-double-quoted" - }, - { - "include": "#jsx-string-single-quoted" - }, - { - "include": "#jsx-evaluated-code" - } - ] - }, - "jsx-tag-attribute-name": { - "match": "(?x)\n \\s*\n ([_$a-zA-Z][-$\\w]*)\n (?=\\s|=|/?>|/\\*|//)", - "captures": { - "1": { - "name": "entity.other.attribute-name.js" - } - } - }, - "jsx-tag-attribute-assignment": { - "name": "keyword.operator.assignment.js", - "match": "=(?=\\s*(?:'|\"|{|/\\*|//|\\n))" - }, - "jsx-string-double-quoted": { - "name": "string.quoted.double.js", - "begin": "\"", - "end": "\"", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.js" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.definition.string.end.js" - } - }, - "patterns": [ - { - "include": "#jsx-entities" - } - ] - }, - "jsx-string-single-quoted": { - "name": "string.quoted.single.js", - "begin": "'", - "end": "'", - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.js" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.definition.string.end.js" - } - }, - "patterns": [ - { - "include": "#jsx-entities" - } - ] - }, - "jsx-entities": { - "patterns": [ - { - "name": "constant.character.entity.js", - "match": "(&)([a-zA-Z0-9]+|#[0-9]+|#x[0-9a-fA-F]+)(;)", - "captures": { - "1": { - "name": "punctuation.definition.entity.js" - }, - "3": { - "name": "punctuation.definition.entity.js" - } - } - }, - { - "name": "invalid.illegal.bad-ampersand.js", - "match": "&" - } - ] - }, - "jsx-evaluated-code": { - "name": "meta.embedded.expression.js", - "begin": "\\{", - "end": "\\}", - "beginCaptures": { - "0": { - "name": "punctuation.section.embedded.begin.js" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.section.embedded.end.js" - } - }, - "patterns": [ - { - "include": "#expression" - } - ] - }, - "jsx-tag-attributes-illegal": { - "name": "invalid.illegal.attribute.js", - "match": "\\S+" - }, - "jsx-tag-without-attributes": { - "name": "meta.tag.without-attributes.js", - "begin": "(<)\\s*([_$a-zA-Z][-$\\w.]*(?)", - "end": "()", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.begin.js" - }, - "2": { - "name": "entity.name.tag.js" - }, - "3": { - "name": "punctuation.definition.tag.end.js" - } - }, - "endCaptures": { - "1": { - "name": "punctuation.definition.tag.begin.js" - }, - "2": { - "name": "entity.name.tag.js" - }, - "3": { - "name": "punctuation.definition.tag.end.js" - } - }, - "contentName": "meta.jsx.children.tsx", - "patterns": [ - { - "include": "#jsx-children" - } - ] - }, - "jsx-tag-in-expression": { - "begin": "(?x)\n (?<=[({\\[,?=>:*]|&&|\\|\\||\\?|\\Wreturn|^return|\\Wdefault|^)\\s*\n (?!(<)\\s*([_$a-zA-Z][-$\\w.]*(?)) #look ahead is not start of tag without attributes\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", - "end": "(/>)|(?:())", - "endCaptures": { - "0": { - "name": "meta.tag.js" - }, - "1": { - "name": "punctuation.definition.tag.end.js" - }, - "2": { - "name": "punctuation.definition.tag.begin.js" - }, - "3": { - "name": "entity.name.tag.js" - }, - "4": { - "name": "punctuation.definition.tag.end.js" - } - }, - "patterns": [ - { - "include": "#jsx-tag" - } - ] - }, - "jsx-child-tag": { - "begin": "(?x)\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", - "end": "(/>)|(?:())", - "endCaptures": { - "0": { - "name": "meta.tag.js" - }, - "1": { - "name": "punctuation.definition.tag.end.js" - }, - "2": { - "name": "punctuation.definition.tag.begin.js" - }, - "3": { - "name": "entity.name.tag.js" - }, - "4": { - "name": "punctuation.definition.tag.end.js" - } - }, - "patterns": [ - { - "include": "#jsx-tag" - } - ] - }, - "jsx-tag": { - "name": "meta.tag.js", - "begin": "(?x)\n (?=(<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?))", - "end": "(?=(/>)|(?:()))", - "patterns": [ - { - "begin": "(?x)\n (<)\\s*\n ([_$a-zA-Z][-$\\w.]*(?)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.begin.js" - }, - "2": { - "name": "entity.name.tag.js" - } - }, - "end": "(?=[/]?>)", - "patterns": [ - { - "include": "#comment" - }, - { - "include": "#jsx-tag-attributes" - }, - { - "include": "#jsx-tag-attributes-illegal" - } - ] - }, - { - "begin": "(>)", - "beginCaptures": { - "1": { - "name": "punctuation.definition.tag.end.js" - } - }, - "end": "(?=" - }, - "jsx-children": { - "patterns": [ - { - "include": "#jsx-tag-without-attributes" - }, - { - "include": "#jsx-child-tag" - }, - { - "include": "#jsx-tag-invalid" - }, - { - "include": "#jsx-evaluated-code" - }, - { - "include": "#jsx-entities" - } - ] - }, - "jsx": { - "patterns": [ - { - "include": "#jsx-tag-without-attributes" - }, - { - "include": "#jsx-tag-in-expression" - }, - { - "include": "#jsx-tag-invalid" - } - ] - } - }, - "version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/5c16c3ce4ede362f39fca054d7b25d85b25ecc68" -} diff --git a/grammar/Readme.md b/grammar/Readme.md deleted file mode 100644 index 7d4d7ce13..000000000 --- a/grammar/Readme.md +++ /dev/null @@ -1,10 +0,0 @@ -Note: The file `JavaScript.tmLanguage.json` is derived from [TypeScriptReact.tmLanguage](https://github.com/Microsoft/TypeScript-TmLanguage/blob/master/TypeScriptReact.tmLanguage). - -# To update the grammar after making changes: - -1. npm run update-grammar -2. Re-comment imports in mongoParser.ts that are not used and cause compile errors - -# Debugging the grammar - -See instructions in launch.json. Be sure to explicitly save the mongo.g4 file to generate the debug info before trying to launch. diff --git a/grammar/Regular Expressions (JavaScript).tmLanguage b/grammar/Regular Expressions (JavaScript).tmLanguage deleted file mode 100644 index 18addf254..000000000 --- a/grammar/Regular Expressions (JavaScript).tmLanguage +++ /dev/null @@ -1,240 +0,0 @@ - - - - - fileTypes - - hideFromUser - - name - - Mongo Scrapbooks Regular Expressions (JavaScript) - patterns - - - include - #regexp - - - repository - - regex-character-class - - patterns - - - match - \\[wWsSdD]|\. - name - constant.character.character-class.regexp - - - match - \\([0-7]{3}|x\h\h|u\h\h\h\h) - name - constant.character.numeric.regexp - - - match - \\c[A-Z] - name - constant.character.control.regexp - - - match - \\. - name - constant.character.escape.backslash.regexp - - - - regexp - - patterns - - - match - \\[bB]|\^|\$ - name - keyword.control.anchor.regexp - - - match - \\[1-9]\d* - name - keyword.other.back-reference.regexp - - - match - [?+*]|\{(\d+,\d+|\d+,|,\d+|\d+)\}\?? - name - keyword.operator.quantifier.regexp - - - match - \| - name - keyword.operator.or.regexp - - - begin - (\()((\?=)|(\?!)) - beginCaptures - - 1 - - name - punctuation.definition.group.regexp - - 3 - - name - meta.assertion.look-ahead.regexp - - 4 - - name - meta.assertion.negative-look-ahead.regexp - - - end - (\)) - endCaptures - - 1 - - name - punctuation.definition.group.regexp - - - name - meta.group.assertion.regexp - patterns - - - include - #regexp - - - - - begin - \((\?:)? - beginCaptures - - 0 - - name - punctuation.definition.group.regexp - - - end - \) - endCaptures - - 0 - - name - punctuation.definition.group.regexp - - - name - meta.group.regexp - patterns - - - include - #regexp - - - - - begin - (\[)(\^)? - beginCaptures - - 1 - - name - punctuation.definition.character-class.regexp - - 2 - - name - keyword.operator.negation.regexp - - - end - (\]) - endCaptures - - 1 - - name - punctuation.definition.character-class.regexp - - - name - constant.other.character-class.set.regexp - patterns - - - captures - - 1 - - name - constant.character.numeric.regexp - - 2 - - name - constant.character.control.regexp - - 3 - - name - constant.character.escape.backslash.regexp - - 4 - - name - constant.character.numeric.regexp - - 5 - - name - constant.character.control.regexp - - 6 - - name - constant.character.escape.backslash.regexp - - - match - (?:.|(\\(?:[0-7]{3}|x\h\h|u\h\h\h\h))|(\\c[A-Z])|(\\.))\-(?:[^\]\\]|(\\(?:[0-7]{3}|x\h\h|u\h\h\h\h))|(\\c[A-Z])|(\\.)) - name - constant.other.character-class.range.regexp - - - include - #regex-character-class - - - - - include - #regex-character-class - - - - - scopeName - - source.mongo.js.regexp - uuid - - c362a36f-6fd7-49c1-b7fb-90f53cdb7ee1 - - diff --git a/grammar/configuration.json b/grammar/configuration.json deleted file mode 100644 index c70acdfb0..000000000 --- a/grammar/configuration.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "comments": { - "lineComment": "//", - "blockComment": ["/*", "*/"] - }, - "brackets": [ - ["{", "}"], - ["[", "]"] - ], - "autoClosingPairs": [ - { - "open": "{", - "close": "}" - }, - { - "open": "[", - "close": "]" - }, - { - "open": "(", - "close": ")" - }, - { - "open": "'", - "close": "'", - "notIn": ["string", "comment"] - }, - { - "open": "\"", - "close": "\"", - "notIn": ["string"] - }, - { - "open": "/**", - "close": " */", - "notIn": ["string"] - } - ] -} diff --git a/grammar/mongo.g4 b/grammar/mongo.g4 deleted file mode 100644 index f2f0e5ad5..000000000 --- a/grammar/mongo.g4 +++ /dev/null @@ -1,109 +0,0 @@ -grammar mongo; - -@header { -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -} - -@lexer::members { - private isExternalIdentifierText(text) { - return text === 'db'; - } -} - -mongoCommands: commands EOF; - -commands: ( command | emptyCommand | comment)*; - -command: DB (DOT collection)? (DOT functionCall)+ SEMICOLON?; - -emptyCommand: SEMICOLON; - -collection: IDENTIFIER (DOT IDENTIFIER)*; - -functionCall: FUNCTION_NAME = IDENTIFIER arguments; - -arguments: - OPEN_PARENTHESIS = '(' (argument ( ',' argument)*)? CLOSED_PARENTHESIS = ')'; - -argument: literal | objectLiteral | arrayLiteral; - -objectLiteral: '{' propertyNameAndValueList? ','? '}'; - -arrayLiteral: '[' elementList? ']'; - -elementList: propertyValue ( ',' propertyValue)*; - -propertyNameAndValueList: - propertyAssignment (',' propertyAssignment)*; - -propertyAssignment: propertyName ':' propertyValue; - -propertyValue: - literal - | objectLiteral - | arrayLiteral - | functionCall; - -literal: (NullLiteral | BooleanLiteral | StringLiteral) - | RegexLiteral - | NumericLiteral; - -propertyName: StringLiteral | IDENTIFIER; - -comment: SingleLineComment | MultiLineComment; - -RegexLiteral: - '/' (~[/\n\r*] | '\\/') (~[/\n\r] | '\\/')* '/' (RegexFlag)*; -// Disallow '*' to succeed the opening '/'. This ensures we don't wrongly parse multi-line comments. -// Disallow carriage returns too. - -fragment RegexFlag: [gimuy]; - -SingleLineComment: - '//' ~[\r\n\u2028\u2029]* -> channel(HIDDEN); - -MultiLineComment: '/*' .*? '*/' -> channel(HIDDEN); - -StringLiteral: - SINGLE_QUOTED_STRING_LITERAL - | DOUBLE_QUOTED_STRING_LITERAL; - -NullLiteral: 'null'; - -BooleanLiteral: 'true' | 'false'; - -NumericLiteral: '-'? DecimalLiteral; - -DecimalLiteral: - DecimalIntegerLiteral '.' DecimalDigit+ ExponentPart? - | '.' DecimalDigit+ ExponentPart? - | DecimalIntegerLiteral ExponentPart?; - -LineTerminator: [\r\n\u2028\u2029] -> channel(HIDDEN); - -SEMICOLON: ';'; -DOT: '.'; -DB: 'db'; - -// Don't declare LR/CRLF tokens - they'll interfere with matching against LineTerminator LF: '\n'; -// CRLF: '\r\n'; - -IDENTIFIER: ((~[[\]"',\\ \t\n\r:.;(){}\-]) | STRING_ESCAPE)+ {!this.isExternalIdentifierText(this.text) - }?; -DOUBLE_QUOTED_STRING_LITERAL: - '"' ((~["\\]) | STRING_ESCAPE)* '"'; -SINGLE_QUOTED_STRING_LITERAL: - '\'' ((~['\\]) | STRING_ESCAPE)* '\''; - -fragment STRING_ESCAPE: '\\' [\\"\\']; - -fragment DecimalIntegerLiteral: '0' | [1-9] DecimalDigit*; - -fragment ExponentPart: [eE] [+-]? DecimalDigit+; - -fragment DecimalDigit: [0-9]; - -WHITESPACE: [ \t] -> skip; diff --git a/src/commands/scrapbook-commands/connectCluster.ts b/src/commands/scrapbook-commands/connectCluster.ts deleted file mode 100644 index fa7c226b9..000000000 --- a/src/commands/scrapbook-commands/connectCluster.ts +++ /dev/null @@ -1,31 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { type IActionContext } from '@microsoft/vscode-azext-utils'; -import * as l10n from '@vscode/l10n'; -import * as vscode from 'vscode'; -import { ScrapbookService } from '../../documentdb/scrapbook/ScrapbookService'; -import { type CollectionItem } from '../../tree/documentdb/CollectionItem'; -import { type DatabaseItem } from '../../tree/documentdb/DatabaseItem'; - -export async function connectCluster(_context: IActionContext, node?: DatabaseItem | CollectionItem): Promise { - if (!node) { - await vscode.window.showInformationMessage( - l10n.t('You can connect to a different DocumentDB by:') + - '\n\n' + - l10n.t("1. Locating the one you'd like from the DocumentDB side panel,") + - '\n' + - l10n.t('2. Selecting a database or a collection,') + - '\n' + - l10n.t('3. Right-clicking and then choosing the "Mongo Scrapbook" submenu,') + - '\n' + - l10n.t('4. Selecting the "Connect to this database" command.'), - { modal: true }, - ); - return; - } - - await ScrapbookService.setConnectedCluster(node.cluster, node.databaseInfo); -} diff --git a/src/commands/scrapbook-commands/createScrapbook.ts b/src/commands/scrapbook-commands/createScrapbook.ts deleted file mode 100644 index 96be6fe07..000000000 --- a/src/commands/scrapbook-commands/createScrapbook.ts +++ /dev/null @@ -1,24 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { type IActionContext } from '@microsoft/vscode-azext-utils'; -import { ScrapbookService } from '../../documentdb/scrapbook/ScrapbookService'; -import { type CollectionItem } from '../../tree/documentdb/CollectionItem'; -import { type DatabaseItem } from '../../tree/documentdb/DatabaseItem'; -import * as vscodeUtil from '../../utils/vscodeUtils'; - -export async function createScrapbook(_context: IActionContext, node: DatabaseItem | CollectionItem): Promise { - const initialFileContents: string = '// MongoDB API Scrapbook: Use this file to run MongoDB API commands\n\n'; - - // if (node instanceof CollectionItem) { - // initialFileContents += `\n\n// You are connected to the "${node.collectionInfo.name}" collection in the "${node.databaseInfo.name}" database.`; - // } else if (node instanceof DatabaseItem) { - // initialFileContents += `\n\n// You are connected to the "${node.databaseInfo.name}" database.`; - // } - - await ScrapbookService.setConnectedCluster(node.cluster, node.databaseInfo); - - await vscodeUtil.showNewFile(initialFileContents, 'Scrapbook', '.vscode-documentdb-scrapbook'); -} diff --git a/src/commands/scrapbook-commands/executeAllCommand.ts b/src/commands/scrapbook-commands/executeAllCommand.ts deleted file mode 100644 index 8b2de473e..000000000 --- a/src/commands/scrapbook-commands/executeAllCommand.ts +++ /dev/null @@ -1,21 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { type IActionContext } from '@microsoft/vscode-azext-utils'; -import * as l10n from '@vscode/l10n'; -import * as vscode from 'vscode'; -import { ScrapbookService } from '../../documentdb/scrapbook/ScrapbookService'; -import { withProgress } from '../../utils/withProgress'; - -export async function executeAllCommand(context: IActionContext): Promise { - const editor = vscode.window.activeTextEditor; - if (!editor) { - throw new Error(l10n.t('You must open a *.vscode-documentdb-scrapbook file to run commands.')); - } - await withProgress( - ScrapbookService.executeAllCommands(context, editor.document), - l10n.t('Executing all commands in shell…'), - ); -} diff --git a/src/commands/scrapbook-commands/executeCommand.ts b/src/commands/scrapbook-commands/executeCommand.ts deleted file mode 100644 index b3c2bc7bf..000000000 --- a/src/commands/scrapbook-commands/executeCommand.ts +++ /dev/null @@ -1,24 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { type IActionContext } from '@microsoft/vscode-azext-utils'; -import * as l10n from '@vscode/l10n'; -import * as vscode from 'vscode'; -import { ScrapbookService } from '../../documentdb/scrapbook/ScrapbookService'; -import { withProgress } from '../../utils/withProgress'; - -export async function executeCommand(context: IActionContext, position?: vscode.Position): Promise { - const editor = vscode.window.activeTextEditor; - if (!editor) { - throw new Error(l10n.t('You must open a *.vscode-documentdb-scrapbook file to run commands.')); - } - - const pos = position ?? editor.selection.start; - - await withProgress( - ScrapbookService.executeCommandAtPosition(context, editor.document, pos), - l10n.t('Executing the command in shell…'), - ); -} diff --git a/src/documentdb/grammar/mongo.tokens b/src/documentdb/grammar/mongo.tokens deleted file mode 100644 index c54199908..000000000 --- a/src/documentdb/grammar/mongo.tokens +++ /dev/null @@ -1,36 +0,0 @@ -T__0=1 -T__1=2 -T__2=3 -T__3=4 -T__4=5 -T__5=6 -T__6=7 -T__7=8 -RegexLiteral=9 -SingleLineComment=10 -MultiLineComment=11 -StringLiteral=12 -NullLiteral=13 -BooleanLiteral=14 -NumericLiteral=15 -DecimalLiteral=16 -LineTerminator=17 -SEMICOLON=18 -DOT=19 -DB=20 -IDENTIFIER=21 -DOUBLE_QUOTED_STRING_LITERAL=22 -SINGLE_QUOTED_STRING_LITERAL=23 -WHITESPACE=24 -'('=1 -','=2 -')'=3 -'{'=4 -'}'=5 -'['=6 -']'=7 -':'=8 -'null'=13 -';'=18 -'.'=19 -'db'=20 diff --git a/src/documentdb/grammar/mongoLexer.tokens b/src/documentdb/grammar/mongoLexer.tokens deleted file mode 100644 index c54199908..000000000 --- a/src/documentdb/grammar/mongoLexer.tokens +++ /dev/null @@ -1,36 +0,0 @@ -T__0=1 -T__1=2 -T__2=3 -T__3=4 -T__4=5 -T__5=6 -T__6=7 -T__7=8 -RegexLiteral=9 -SingleLineComment=10 -MultiLineComment=11 -StringLiteral=12 -NullLiteral=13 -BooleanLiteral=14 -NumericLiteral=15 -DecimalLiteral=16 -LineTerminator=17 -SEMICOLON=18 -DOT=19 -DB=20 -IDENTIFIER=21 -DOUBLE_QUOTED_STRING_LITERAL=22 -SINGLE_QUOTED_STRING_LITERAL=23 -WHITESPACE=24 -'('=1 -','=2 -')'=3 -'{'=4 -'}'=5 -'['=6 -']'=7 -':'=8 -'null'=13 -';'=18 -'.'=19 -'db'=20 diff --git a/src/documentdb/grammar/mongoLexer.ts b/src/documentdb/grammar/mongoLexer.ts deleted file mode 100644 index 6b32a6a99..000000000 --- a/src/documentdb/grammar/mongoLexer.ts +++ /dev/null @@ -1,316 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// This is legacy code that we are not maintaining for Typescript 4 -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-nocheck - -import { type ATN } from 'antlr4ts/atn/ATN'; -import { ATNDeserializer } from 'antlr4ts/atn/ATNDeserializer'; -import { LexerATNSimulator } from 'antlr4ts/atn/LexerATNSimulator'; -import { type CharStream } from 'antlr4ts/CharStream'; -import { NotNull, Override } from 'antlr4ts/Decorators'; -import { Lexer } from 'antlr4ts/Lexer'; -import * as Utils from 'antlr4ts/misc/Utils'; -import { type RuleContext } from 'antlr4ts/RuleContext'; -import { type Vocabulary } from 'antlr4ts/Vocabulary'; -import { VocabularyImpl } from 'antlr4ts/VocabularyImpl'; - -export class mongoLexer extends Lexer { - public static readonly T__0 = 1; - public static readonly T__1 = 2; - public static readonly T__2 = 3; - public static readonly T__3 = 4; - public static readonly T__4 = 5; - public static readonly T__5 = 6; - public static readonly T__6 = 7; - public static readonly T__7 = 8; - public static readonly RegexLiteral = 9; - public static readonly SingleLineComment = 10; - public static readonly MultiLineComment = 11; - public static readonly StringLiteral = 12; - public static readonly NullLiteral = 13; - public static readonly BooleanLiteral = 14; - public static readonly NumericLiteral = 15; - public static readonly DecimalLiteral = 16; - public static readonly LineTerminator = 17; - public static readonly SEMICOLON = 18; - public static readonly DOT = 19; - public static readonly DB = 20; - public static readonly IDENTIFIER = 21; - public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; - public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; - public static readonly WHITESPACE = 24; - public static readonly modeNames: string[] = ['DEFAULT_MODE']; - - public static readonly ruleNames: string[] = [ - 'T__0', - 'T__1', - 'T__2', - 'T__3', - 'T__4', - 'T__5', - 'T__6', - 'T__7', - 'RegexLiteral', - 'RegexFlag', - 'SingleLineComment', - 'MultiLineComment', - 'StringLiteral', - 'NullLiteral', - 'BooleanLiteral', - 'NumericLiteral', - 'DecimalLiteral', - 'LineTerminator', - 'SEMICOLON', - 'DOT', - 'DB', - 'IDENTIFIER', - 'DOUBLE_QUOTED_STRING_LITERAL', - 'SINGLE_QUOTED_STRING_LITERAL', - 'STRING_ESCAPE', - 'DecimalIntegerLiteral', - 'ExponentPart', - 'DecimalDigit', - 'WHITESPACE', - ]; - - private static readonly _LITERAL_NAMES: (string | undefined)[] = [ - undefined, - "'('", - "','", - "')'", - "'{'", - "'}'", - "'['", - "']'", - "':'", - undefined, - undefined, - undefined, - undefined, - "'null'", - undefined, - undefined, - undefined, - undefined, - "';'", - "'.'", - "'db'", - ]; - private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - 'RegexLiteral', - 'SingleLineComment', - 'MultiLineComment', - 'StringLiteral', - 'NullLiteral', - 'BooleanLiteral', - 'NumericLiteral', - 'DecimalLiteral', - 'LineTerminator', - 'SEMICOLON', - 'DOT', - 'DB', - 'IDENTIFIER', - 'DOUBLE_QUOTED_STRING_LITERAL', - 'SINGLE_QUOTED_STRING_LITERAL', - 'WHITESPACE', - ]; - public static readonly VOCABULARY: Vocabulary = new VocabularyImpl( - mongoLexer._LITERAL_NAMES, - mongoLexer._SYMBOLIC_NAMES, - [], - ); - - @Override - @NotNull - public get vocabulary(): Vocabulary { - return mongoLexer.VOCABULARY; - } - - private isExternalIdentifierText(text) { - return text === 'db'; - } - - constructor(input: CharStream) { - super(input); - this._interp = new LexerATNSimulator(mongoLexer._ATN, this); - } - - @Override - public get grammarFileName(): string { - return 'mongo.g4'; - } - - @Override - public get ruleNames(): string[] { - return mongoLexer.ruleNames; - } - - @Override - public get serializedATN(): string { - return mongoLexer._serializedATN; - } - - @Override - public get modeNames(): string[] { - return mongoLexer.modeNames; - } - - @Override - public sempred(_localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { - switch (ruleIndex) { - case 21: - return this.IDENTIFIER_sempred(_localctx, predIndex); - } - return true; - } - private IDENTIFIER_sempred(_localctx: RuleContext, predIndex: number): boolean { - switch (predIndex) { - case 0: - return !this.isExternalIdentifierText(this.text); - } - return true; - } - - public static readonly _serializedATN: string = - '\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x02\x1A\xF2\b\x01' + - '\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06' + - '\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r' + - '\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t' + - '\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t' + - '\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t' + - '\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x03\x02\x03\x02\x03\x03\x03\x03\x03\x04' + - '\x03\x04\x03\x05\x03\x05\x03\x06\x03\x06\x03\x07\x03\x07\x03\b\x03\b\x03' + - '\t\x03\t\x03\n\x03\n\x03\n\x03\n\x05\nR\n\n\x03\n\x03\n\x03\n\x07\nW\n' + - '\n\f\n\x0E\nZ\v\n\x03\n\x03\n\x07\n^\n\n\f\n\x0E\na\v\n\x03\v\x03\v\x03' + - '\f\x03\f\x03\f\x03\f\x07\fi\n\f\f\f\x0E\fl\v\f\x03\f\x03\f\x03\r\x03\r' + - '\x03\r\x03\r\x07\rt\n\r\f\r\x0E\rw\v\r\x03\r\x03\r\x03\r\x03\r\x03\r\x03' + - '\x0E\x03\x0E\x05\x0E\x80\n\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F\x03\x0F' + - '\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x10' + - '\x05\x10\x90\n\x10\x03\x11\x05\x11\x93\n\x11\x03\x11\x03\x11\x03\x12\x03' + - '\x12\x03\x12\x06\x12\x9A\n\x12\r\x12\x0E\x12\x9B\x03\x12\x05\x12\x9F\n' + - '\x12\x03\x12\x03\x12\x06\x12\xA3\n\x12\r\x12\x0E\x12\xA4\x03\x12\x05\x12' + - '\xA8\n\x12\x03\x12\x03\x12\x05\x12\xAC\n\x12\x05\x12\xAE\n\x12\x03\x13' + - '\x03\x13\x03\x13\x03\x13\x03\x14\x03\x14\x03\x15\x03\x15\x03\x16\x03\x16' + - '\x03\x16\x03\x17\x03\x17\x06\x17\xBD\n\x17\r\x17\x0E\x17\xBE\x03\x17\x03' + - '\x17\x03\x18\x03\x18\x03\x18\x07\x18\xC6\n\x18\f\x18\x0E\x18\xC9\v\x18' + - '\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x07\x19\xD0\n\x19\f\x19\x0E\x19' + - '\xD3\v\x19\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03' + - '\x1B\x07\x1B\xDD\n\x1B\f\x1B\x0E\x1B\xE0\v\x1B\x05\x1B\xE2\n\x1B\x03\x1C' + - '\x03\x1C\x05\x1C\xE6\n\x1C\x03\x1C\x06\x1C\xE9\n\x1C\r\x1C\x0E\x1C\xEA' + - '\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1E\x03u\x02\x02\x1F\x03' + - '\x02\x03\x05\x02\x04\x07\x02\x05\t\x02\x06\v\x02\x07\r\x02\b\x0F\x02\t' + - '\x11\x02\n\x13\x02\v\x15\x02\x02\x17\x02\f\x19\x02\r\x1B\x02\x0E\x1D\x02' + - "\x0F\x1F\x02\x10!\x02\x11#\x02\x12%\x02\x13'\x02\x14)\x02\x15+\x02\x16" + - '-\x02\x17/\x02\x181\x02\x193\x02\x025\x02\x027\x02\x029\x02\x02;\x02\x1A' + - '\x03\x02\x0F\x06\x02\f\f\x0F\x0F,,11\x05\x02\f\f\x0F\x0F11\x07\x02iik' + - 'kooww{{\x05\x02\f\f\x0F\x0F\u202A\u202B\f\x02\v\f\x0F\x0F""$$)+.0<=' + - ']_}}\x7F\x7F\x04\x02$$^^\x04\x02))^^\x05\x02$$))^^\x03\x023;\x04\x02G' + - 'Ggg\x04\x02--//\x03\x022;\x04\x02\v\v""\u0106\x02\x03\x03\x02\x02\x02' + - '\x02\x05\x03\x02\x02\x02\x02\x07\x03\x02\x02\x02\x02\t\x03\x02\x02\x02' + - '\x02\v\x03\x02\x02\x02\x02\r\x03\x02\x02\x02\x02\x0F\x03\x02\x02\x02\x02' + - '\x11\x03\x02\x02\x02\x02\x13\x03\x02\x02\x02\x02\x17\x03\x02\x02\x02\x02' + - '\x19\x03\x02\x02\x02\x02\x1B\x03\x02\x02\x02\x02\x1D\x03\x02\x02\x02\x02' + - '\x1F\x03\x02\x02\x02\x02!\x03\x02\x02\x02\x02#\x03\x02\x02\x02\x02%\x03' + - "\x02\x02\x02\x02'\x03\x02\x02\x02\x02)\x03\x02\x02\x02\x02+\x03\x02\x02" + - '\x02\x02-\x03\x02\x02\x02\x02/\x03\x02\x02\x02\x021\x03\x02\x02\x02\x02' + - ';\x03\x02\x02\x02\x03=\x03\x02\x02\x02\x05?\x03\x02\x02\x02\x07A\x03\x02' + - '\x02\x02\tC\x03\x02\x02\x02\vE\x03\x02\x02\x02\rG\x03\x02\x02\x02\x0F' + - 'I\x03\x02\x02\x02\x11K\x03\x02\x02\x02\x13M\x03\x02\x02\x02\x15b\x03\x02' + - '\x02\x02\x17d\x03\x02\x02\x02\x19o\x03\x02\x02\x02\x1B\x7F\x03\x02\x02' + - '\x02\x1D\x81\x03\x02\x02\x02\x1F\x8F\x03\x02\x02\x02!\x92\x03\x02\x02' + - "\x02#\xAD\x03\x02\x02\x02%\xAF\x03\x02\x02\x02'\xB3\x03\x02\x02\x02)" + - '\xB5\x03\x02\x02\x02+\xB7\x03\x02\x02\x02-\xBC\x03\x02\x02\x02/\xC2\x03' + - '\x02\x02\x021\xCC\x03\x02\x02\x023\xD6\x03\x02\x02\x025\xE1\x03\x02\x02' + - '\x027\xE3\x03\x02\x02\x029\xEC\x03\x02\x02\x02;\xEE\x03\x02\x02\x02=>' + - '\x07*\x02\x02>\x04\x03\x02\x02\x02?@\x07.\x02\x02@\x06\x03\x02\x02\x02' + - 'AB\x07+\x02\x02B\b\x03\x02\x02\x02CD\x07}\x02\x02D\n\x03\x02\x02\x02E' + - 'F\x07\x7F\x02\x02F\f\x03\x02\x02\x02GH\x07]\x02\x02H\x0E\x03\x02\x02\x02' + - 'IJ\x07_\x02\x02J\x10\x03\x02\x02\x02KL\x07<\x02\x02L\x12\x03\x02\x02\x02' + - 'MQ\x071\x02\x02NR\n\x02\x02\x02OP\x07^\x02\x02PR\x071\x02\x02QN\x03\x02' + - '\x02\x02QO\x03\x02\x02\x02RX\x03\x02\x02\x02SW\n\x03\x02\x02TU\x07^\x02' + - '\x02UW\x071\x02\x02VS\x03\x02\x02\x02VT\x03\x02\x02\x02WZ\x03\x02\x02' + - '\x02XV\x03\x02\x02\x02XY\x03\x02\x02\x02Y[\x03\x02\x02\x02ZX\x03\x02\x02' + - '\x02[_\x071\x02\x02\\^\x05\x15\v\x02]\\\x03\x02\x02\x02^a\x03\x02\x02' + - '\x02_]\x03\x02\x02\x02_`\x03\x02\x02\x02`\x14\x03\x02\x02\x02a_\x03\x02' + - '\x02\x02bc\t\x04\x02\x02c\x16\x03\x02\x02\x02de\x071\x02\x02ef\x071\x02' + - '\x02fj\x03\x02\x02\x02gi\n\x05\x02\x02hg\x03\x02\x02\x02il\x03\x02\x02' + - '\x02jh\x03\x02\x02\x02jk\x03\x02\x02\x02km\x03\x02\x02\x02lj\x03\x02\x02' + - '\x02mn\b\f\x02\x02n\x18\x03\x02\x02\x02op\x071\x02\x02pq\x07,\x02\x02' + - 'qu\x03\x02\x02\x02rt\v\x02\x02\x02sr\x03\x02\x02\x02tw\x03\x02\x02\x02' + - 'uv\x03\x02\x02\x02us\x03\x02\x02\x02vx\x03\x02\x02\x02wu\x03\x02\x02\x02' + - 'xy\x07,\x02\x02yz\x071\x02\x02z{\x03\x02\x02\x02{|\b\r\x02\x02|\x1A\x03' + - '\x02\x02\x02}\x80\x051\x19\x02~\x80\x05/\x18\x02\x7F}\x03\x02\x02\x02' + - '\x7F~\x03\x02\x02\x02\x80\x1C\x03\x02\x02\x02\x81\x82\x07p\x02\x02\x82' + - '\x83\x07w\x02\x02\x83\x84\x07n\x02\x02\x84\x85\x07n\x02\x02\x85\x1E\x03' + - '\x02\x02\x02\x86\x87\x07v\x02\x02\x87\x88\x07t\x02\x02\x88\x89\x07w\x02' + - '\x02\x89\x90\x07g\x02\x02\x8A\x8B\x07h\x02\x02\x8B\x8C\x07c\x02\x02\x8C' + - '\x8D\x07n\x02\x02\x8D\x8E\x07u\x02\x02\x8E\x90\x07g\x02\x02\x8F\x86\x03' + - '\x02\x02\x02\x8F\x8A\x03\x02\x02\x02\x90 \x03\x02\x02\x02\x91\x93\x07' + - '/\x02\x02\x92\x91\x03\x02\x02\x02\x92\x93\x03\x02\x02\x02\x93\x94\x03' + - '\x02\x02\x02\x94\x95\x05#\x12\x02\x95"\x03\x02\x02\x02\x96\x97\x055\x1B' + - '\x02\x97\x99\x070\x02\x02\x98\x9A\x059\x1D\x02\x99\x98\x03\x02\x02\x02' + - '\x9A\x9B\x03\x02\x02\x02\x9B\x99\x03\x02\x02\x02\x9B\x9C\x03\x02\x02\x02' + - '\x9C\x9E\x03\x02\x02\x02\x9D\x9F\x057\x1C\x02\x9E\x9D\x03\x02\x02\x02' + - '\x9E\x9F\x03\x02\x02\x02\x9F\xAE\x03\x02\x02\x02\xA0\xA2\x070\x02\x02' + - '\xA1\xA3\x059\x1D\x02\xA2\xA1\x03\x02\x02\x02\xA3\xA4\x03\x02\x02\x02' + - '\xA4\xA2\x03\x02\x02\x02\xA4\xA5\x03\x02\x02\x02\xA5\xA7\x03\x02\x02\x02' + - '\xA6\xA8\x057\x1C\x02\xA7\xA6\x03\x02\x02\x02\xA7\xA8\x03\x02\x02\x02' + - '\xA8\xAE\x03\x02\x02\x02\xA9\xAB\x055\x1B\x02\xAA\xAC\x057\x1C\x02\xAB' + - '\xAA\x03\x02\x02\x02\xAB\xAC\x03\x02\x02\x02\xAC\xAE\x03\x02\x02\x02\xAD' + - '\x96\x03\x02\x02\x02\xAD\xA0\x03\x02\x02\x02\xAD\xA9\x03\x02\x02\x02\xAE' + - '$\x03\x02\x02\x02\xAF\xB0\t\x05\x02\x02\xB0\xB1\x03\x02\x02\x02\xB1\xB2' + - '\b\x13\x02\x02\xB2&\x03\x02\x02\x02\xB3\xB4\x07=\x02\x02\xB4(\x03\x02' + - '\x02\x02\xB5\xB6\x070\x02\x02\xB6*\x03\x02\x02\x02\xB7\xB8\x07f\x02\x02' + - '\xB8\xB9\x07d\x02\x02\xB9,\x03\x02\x02\x02\xBA\xBD\n\x06\x02\x02\xBB\xBD' + - '\x053\x1A\x02\xBC\xBA\x03\x02\x02\x02\xBC\xBB\x03\x02\x02\x02\xBD\xBE' + - '\x03\x02\x02\x02\xBE\xBC\x03\x02\x02\x02\xBE\xBF\x03\x02\x02\x02\xBF\xC0' + - '\x03\x02\x02\x02\xC0\xC1\x06\x17\x02\x02\xC1.\x03\x02\x02\x02\xC2\xC7' + - '\x07$\x02\x02\xC3\xC6\n\x07\x02\x02\xC4\xC6\x053\x1A\x02\xC5\xC3\x03\x02' + - '\x02\x02\xC5\xC4\x03\x02\x02\x02\xC6\xC9\x03\x02\x02\x02\xC7\xC5\x03\x02' + - '\x02\x02\xC7\xC8\x03\x02\x02\x02\xC8\xCA\x03\x02\x02\x02\xC9\xC7\x03\x02' + - '\x02\x02\xCA\xCB\x07$\x02\x02\xCB0\x03\x02\x02\x02\xCC\xD1\x07)\x02\x02' + - '\xCD\xD0\n\b\x02\x02\xCE\xD0\x053\x1A\x02\xCF\xCD\x03\x02\x02\x02\xCF' + - '\xCE\x03\x02\x02\x02\xD0\xD3\x03\x02\x02\x02\xD1\xCF\x03\x02\x02\x02\xD1' + - '\xD2\x03\x02\x02\x02\xD2\xD4\x03\x02\x02\x02\xD3\xD1\x03\x02\x02\x02\xD4' + - '\xD5\x07)\x02\x02\xD52\x03\x02\x02\x02\xD6\xD7\x07^\x02\x02\xD7\xD8\t' + - '\t\x02\x02\xD84\x03\x02\x02\x02\xD9\xE2\x072\x02\x02\xDA\xDE\t\n\x02\x02' + - '\xDB\xDD\x059\x1D\x02\xDC\xDB\x03\x02\x02\x02\xDD\xE0\x03\x02\x02\x02' + - '\xDE\xDC\x03\x02\x02\x02\xDE\xDF\x03\x02\x02\x02\xDF\xE2\x03\x02\x02\x02' + - '\xE0\xDE\x03\x02\x02\x02\xE1\xD9\x03\x02\x02\x02\xE1\xDA\x03\x02\x02\x02' + - '\xE26\x03\x02\x02\x02\xE3\xE5\t\v\x02\x02\xE4\xE6\t\f\x02\x02\xE5\xE4' + - '\x03\x02\x02\x02\xE5\xE6\x03\x02\x02\x02\xE6\xE8\x03\x02\x02\x02\xE7\xE9' + - '\x059\x1D\x02\xE8\xE7\x03\x02\x02\x02\xE9\xEA\x03\x02\x02\x02\xEA\xE8' + - '\x03\x02\x02\x02\xEA\xEB\x03\x02\x02\x02\xEB8\x03\x02\x02\x02\xEC\xED' + - '\t\r\x02\x02\xED:\x03\x02\x02\x02\xEE\xEF\t\x0E\x02\x02\xEF\xF0\x03\x02' + - '\x02\x02\xF0\xF1\b\x1E\x03\x02\xF1<\x03\x02\x02\x02\x1C\x02QVX_ju\x7F' + - '\x8F\x92\x9B\x9E\xA4\xA7\xAB\xAD\xBC\xBE\xC5\xC7\xCF\xD1\xDE\xE1\xE5\xEA' + - '\x04\x02\x03\x02\b\x02\x02'; - public static __ATN: ATN; - public static get _ATN(): ATN { - if (!mongoLexer.__ATN) { - mongoLexer.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(mongoLexer._serializedATN)); - } - - return mongoLexer.__ATN; - } -} diff --git a/src/documentdb/grammar/mongoListener.ts b/src/documentdb/grammar/mongoListener.ts deleted file mode 100644 index bfbdd1170..000000000 --- a/src/documentdb/grammar/mongoListener.ts +++ /dev/null @@ -1,225 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { type ParseTreeListener } from 'antlr4ts/tree/ParseTreeListener'; -import { - type ArgumentContext, - type ArgumentsContext, - type ArrayLiteralContext, - type CollectionContext, - type CommandContext, - type CommandsContext, - type CommentContext, - type ElementListContext, - type EmptyCommandContext, - type FunctionCallContext, - type LiteralContext, - type MongoCommandsContext, - type ObjectLiteralContext, - type PropertyAssignmentContext, - type PropertyNameAndValueListContext, - type PropertyNameContext, - type PropertyValueContext, -} from './mongoParser'; - -/** - * This interface defines a complete listener for a parse tree produced by - * `mongoParser`. - */ -export interface mongoListener extends ParseTreeListener { - /** - * Enter a parse tree produced by `mongoParser.mongoCommands`. - * @param ctx the parse tree - */ - enterMongoCommands?: (ctx: MongoCommandsContext) => void; - /** - * Exit a parse tree produced by `mongoParser.mongoCommands`. - * @param ctx the parse tree - */ - exitMongoCommands?: (ctx: MongoCommandsContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.commands`. - * @param ctx the parse tree - */ - enterCommands?: (ctx: CommandsContext) => void; - /** - * Exit a parse tree produced by `mongoParser.commands`. - * @param ctx the parse tree - */ - exitCommands?: (ctx: CommandsContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.command`. - * @param ctx the parse tree - */ - enterCommand?: (ctx: CommandContext) => void; - /** - * Exit a parse tree produced by `mongoParser.command`. - * @param ctx the parse tree - */ - exitCommand?: (ctx: CommandContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.emptyCommand`. - * @param ctx the parse tree - */ - enterEmptyCommand?: (ctx: EmptyCommandContext) => void; - /** - * Exit a parse tree produced by `mongoParser.emptyCommand`. - * @param ctx the parse tree - */ - exitEmptyCommand?: (ctx: EmptyCommandContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.collection`. - * @param ctx the parse tree - */ - enterCollection?: (ctx: CollectionContext) => void; - /** - * Exit a parse tree produced by `mongoParser.collection`. - * @param ctx the parse tree - */ - exitCollection?: (ctx: CollectionContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.functionCall`. - * @param ctx the parse tree - */ - enterFunctionCall?: (ctx: FunctionCallContext) => void; - /** - * Exit a parse tree produced by `mongoParser.functionCall`. - * @param ctx the parse tree - */ - exitFunctionCall?: (ctx: FunctionCallContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.arguments`. - * @param ctx the parse tree - */ - enterArguments?: (ctx: ArgumentsContext) => void; - /** - * Exit a parse tree produced by `mongoParser.arguments`. - * @param ctx the parse tree - */ - exitArguments?: (ctx: ArgumentsContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.argument`. - * @param ctx the parse tree - */ - enterArgument?: (ctx: ArgumentContext) => void; - /** - * Exit a parse tree produced by `mongoParser.argument`. - * @param ctx the parse tree - */ - exitArgument?: (ctx: ArgumentContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.objectLiteral`. - * @param ctx the parse tree - */ - enterObjectLiteral?: (ctx: ObjectLiteralContext) => void; - /** - * Exit a parse tree produced by `mongoParser.objectLiteral`. - * @param ctx the parse tree - */ - exitObjectLiteral?: (ctx: ObjectLiteralContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.arrayLiteral`. - * @param ctx the parse tree - */ - enterArrayLiteral?: (ctx: ArrayLiteralContext) => void; - /** - * Exit a parse tree produced by `mongoParser.arrayLiteral`. - * @param ctx the parse tree - */ - exitArrayLiteral?: (ctx: ArrayLiteralContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.elementList`. - * @param ctx the parse tree - */ - enterElementList?: (ctx: ElementListContext) => void; - /** - * Exit a parse tree produced by `mongoParser.elementList`. - * @param ctx the parse tree - */ - exitElementList?: (ctx: ElementListContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.propertyNameAndValueList`. - * @param ctx the parse tree - */ - enterPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => void; - /** - * Exit a parse tree produced by `mongoParser.propertyNameAndValueList`. - * @param ctx the parse tree - */ - exitPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.propertyAssignment`. - * @param ctx the parse tree - */ - enterPropertyAssignment?: (ctx: PropertyAssignmentContext) => void; - /** - * Exit a parse tree produced by `mongoParser.propertyAssignment`. - * @param ctx the parse tree - */ - exitPropertyAssignment?: (ctx: PropertyAssignmentContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.propertyValue`. - * @param ctx the parse tree - */ - enterPropertyValue?: (ctx: PropertyValueContext) => void; - /** - * Exit a parse tree produced by `mongoParser.propertyValue`. - * @param ctx the parse tree - */ - exitPropertyValue?: (ctx: PropertyValueContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.literal`. - * @param ctx the parse tree - */ - enterLiteral?: (ctx: LiteralContext) => void; - /** - * Exit a parse tree produced by `mongoParser.literal`. - * @param ctx the parse tree - */ - exitLiteral?: (ctx: LiteralContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.propertyName`. - * @param ctx the parse tree - */ - enterPropertyName?: (ctx: PropertyNameContext) => void; - /** - * Exit a parse tree produced by `mongoParser.propertyName`. - * @param ctx the parse tree - */ - exitPropertyName?: (ctx: PropertyNameContext) => void; - - /** - * Enter a parse tree produced by `mongoParser.comment`. - * @param ctx the parse tree - */ - enterComment?: (ctx: CommentContext) => void; - /** - * Exit a parse tree produced by `mongoParser.comment`. - * @param ctx the parse tree - */ - exitComment?: (ctx: CommentContext) => void; -} diff --git a/src/documentdb/grammar/mongoParser.ts b/src/documentdb/grammar/mongoParser.ts deleted file mode 100644 index 7e4c52933..000000000 --- a/src/documentdb/grammar/mongoParser.ts +++ /dev/null @@ -1,1561 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// This is legacy code that we are not maintaining for Typescript 4 -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-nocheck - -import { ATN } from 'antlr4ts/atn/ATN'; -import { ATNDeserializer } from 'antlr4ts/atn/ATNDeserializer'; -import { ParserATNSimulator } from 'antlr4ts/atn/ParserATNSimulator'; -import { NotNull, Override } from 'antlr4ts/Decorators'; -import * as Utils from 'antlr4ts/misc/Utils'; -import { NoViableAltException } from 'antlr4ts/NoViableAltException'; -import { Parser } from 'antlr4ts/Parser'; -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { RecognitionException } from 'antlr4ts/RecognitionException'; -import { RuleVersion } from 'antlr4ts/RuleVersion'; -import { Token } from 'antlr4ts/Token'; -import { type TokenStream } from 'antlr4ts/TokenStream'; -import { type TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { type Vocabulary } from 'antlr4ts/Vocabulary'; -import { VocabularyImpl } from 'antlr4ts/VocabularyImpl'; -import { type mongoListener } from './mongoListener'; -import { type mongoVisitor } from './mongoVisitor'; - -export class mongoParser extends Parser { - public static readonly T__0 = 1; - public static readonly T__1 = 2; - public static readonly T__2 = 3; - public static readonly T__3 = 4; - public static readonly T__4 = 5; - public static readonly T__5 = 6; - public static readonly T__6 = 7; - public static readonly T__7 = 8; - public static readonly RegexLiteral = 9; - public static readonly SingleLineComment = 10; - public static readonly MultiLineComment = 11; - public static readonly StringLiteral = 12; - public static readonly NullLiteral = 13; - public static readonly BooleanLiteral = 14; - public static readonly NumericLiteral = 15; - public static readonly DecimalLiteral = 16; - public static readonly LineTerminator = 17; - public static readonly SEMICOLON = 18; - public static readonly DOT = 19; - public static readonly DB = 20; - public static readonly IDENTIFIER = 21; - public static readonly DOUBLE_QUOTED_STRING_LITERAL = 22; - public static readonly SINGLE_QUOTED_STRING_LITERAL = 23; - public static readonly WHITESPACE = 24; - public static readonly RULE_mongoCommands = 0; - public static readonly RULE_commands = 1; - public static readonly RULE_command = 2; - public static readonly RULE_emptyCommand = 3; - public static readonly RULE_collection = 4; - public static readonly RULE_functionCall = 5; - public static readonly RULE_arguments = 6; - public static readonly RULE_argument = 7; - public static readonly RULE_objectLiteral = 8; - public static readonly RULE_arrayLiteral = 9; - public static readonly RULE_elementList = 10; - public static readonly RULE_propertyNameAndValueList = 11; - public static readonly RULE_propertyAssignment = 12; - public static readonly RULE_propertyValue = 13; - public static readonly RULE_literal = 14; - public static readonly RULE_propertyName = 15; - public static readonly RULE_comment = 16; - public static readonly ruleNames: string[] = [ - 'mongoCommands', - 'commands', - 'command', - 'emptyCommand', - 'collection', - 'functionCall', - 'arguments', - 'argument', - 'objectLiteral', - 'arrayLiteral', - 'elementList', - 'propertyNameAndValueList', - 'propertyAssignment', - 'propertyValue', - 'literal', - 'propertyName', - 'comment', - ]; - - private static readonly _LITERAL_NAMES: (string | undefined)[] = [ - undefined, - "'('", - "','", - "')'", - "'{'", - "'}'", - "'['", - "']'", - "':'", - undefined, - undefined, - undefined, - undefined, - "'null'", - undefined, - undefined, - undefined, - undefined, - "';'", - "'.'", - "'db'", - ]; - private static readonly _SYMBOLIC_NAMES: (string | undefined)[] = [ - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - undefined, - 'RegexLiteral', - 'SingleLineComment', - 'MultiLineComment', - 'StringLiteral', - 'NullLiteral', - 'BooleanLiteral', - 'NumericLiteral', - 'DecimalLiteral', - 'LineTerminator', - 'SEMICOLON', - 'DOT', - 'DB', - 'IDENTIFIER', - 'DOUBLE_QUOTED_STRING_LITERAL', - 'SINGLE_QUOTED_STRING_LITERAL', - 'WHITESPACE', - ]; - public static readonly VOCABULARY: Vocabulary = new VocabularyImpl( - mongoParser._LITERAL_NAMES, - mongoParser._SYMBOLIC_NAMES, - [], - ); - - @Override - @NotNull - public get vocabulary(): Vocabulary { - return mongoParser.VOCABULARY; - } - - @Override - public get grammarFileName(): string { - return 'mongo.g4'; - } - - @Override - public get ruleNames(): string[] { - return mongoParser.ruleNames; - } - - @Override - public get serializedATN(): string { - return mongoParser._serializedATN; - } - - constructor(input: TokenStream) { - super(input); - this._interp = new ParserATNSimulator(mongoParser._ATN, this); - } - @RuleVersion(0) - public mongoCommands(): MongoCommandsContext { - const _localctx: MongoCommandsContext = new MongoCommandsContext(this._ctx, this.state); - this.enterRule(_localctx, 0, mongoParser.RULE_mongoCommands); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 34; - this.commands(); - this.state = 35; - this.match(mongoParser.EOF); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public commands(): CommandsContext { - const _localctx: CommandsContext = new CommandsContext(this._ctx, this.state); - this.enterRule(_localctx, 2, mongoParser.RULE_commands); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 42; - this._errHandler.sync(this); - _la = this._input.LA(1); - while ( - (_la & ~0x1f) === 0 && - ((1 << _la) & - ((1 << mongoParser.SingleLineComment) | - (1 << mongoParser.MultiLineComment) | - (1 << mongoParser.SEMICOLON) | - (1 << mongoParser.DB))) !== - 0 - ) { - { - this.state = 40; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.DB: - { - this.state = 37; - this.command(); - } - break; - case mongoParser.SEMICOLON: - { - this.state = 38; - this.emptyCommand(); - } - break; - case mongoParser.SingleLineComment: - case mongoParser.MultiLineComment: - { - this.state = 39; - this.comment(); - } - break; - default: - throw new NoViableAltException(this); - } - } - this.state = 44; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public command(): CommandContext { - const _localctx: CommandContext = new CommandContext(this._ctx, this.state); - this.enterRule(_localctx, 4, mongoParser.RULE_command); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 45; - this.match(mongoParser.DB); - this.state = 48; - this._errHandler.sync(this); - switch (this.interpreter.adaptivePredict(this._input, 2, this._ctx)) { - case 1: - { - this.state = 46; - this.match(mongoParser.DOT); - this.state = 47; - this.collection(); - } - break; - } - this.state = 52; - this._errHandler.sync(this); - _la = this._input.LA(1); - do { - { - { - this.state = 50; - this.match(mongoParser.DOT); - this.state = 51; - this.functionCall(); - } - } - this.state = 54; - this._errHandler.sync(this); - _la = this._input.LA(1); - } while (_la === mongoParser.DOT); - this.state = 57; - this._errHandler.sync(this); - switch (this.interpreter.adaptivePredict(this._input, 4, this._ctx)) { - case 1: - { - this.state = 56; - this.match(mongoParser.SEMICOLON); - } - break; - } - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public emptyCommand(): EmptyCommandContext { - const _localctx: EmptyCommandContext = new EmptyCommandContext(this._ctx, this.state); - this.enterRule(_localctx, 6, mongoParser.RULE_emptyCommand); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 59; - this.match(mongoParser.SEMICOLON); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public collection(): CollectionContext { - const _localctx: CollectionContext = new CollectionContext(this._ctx, this.state); - this.enterRule(_localctx, 8, mongoParser.RULE_collection); - try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 61; - this.match(mongoParser.IDENTIFIER); - this.state = 66; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 5, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 62; - this.match(mongoParser.DOT); - this.state = 63; - this.match(mongoParser.IDENTIFIER); - } - } - } - this.state = 68; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 5, this._ctx); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public functionCall(): FunctionCallContext { - const _localctx: FunctionCallContext = new FunctionCallContext(this._ctx, this.state); - this.enterRule(_localctx, 10, mongoParser.RULE_functionCall); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 69; - _localctx._FUNCTION_NAME = this.match(mongoParser.IDENTIFIER); - this.state = 70; - this.arguments(); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public arguments(): ArgumentsContext { - const _localctx: ArgumentsContext = new ArgumentsContext(this._ctx, this.state); - this.enterRule(_localctx, 12, mongoParser.RULE_arguments); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 72; - _localctx._OPEN_PARENTHESIS = this.match(mongoParser.T__0); - this.state = 81; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ( - (_la & ~0x1f) === 0 && - ((1 << _la) & - ((1 << mongoParser.T__3) | - (1 << mongoParser.T__5) | - (1 << mongoParser.RegexLiteral) | - (1 << mongoParser.StringLiteral) | - (1 << mongoParser.NullLiteral) | - (1 << mongoParser.BooleanLiteral) | - (1 << mongoParser.NumericLiteral))) !== - 0 - ) { - { - this.state = 73; - this.argument(); - this.state = 78; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === mongoParser.T__1) { - { - { - this.state = 74; - this.match(mongoParser.T__1); - this.state = 75; - this.argument(); - } - } - this.state = 80; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - - this.state = 83; - _localctx._CLOSED_PARENTHESIS = this.match(mongoParser.T__2); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public argument(): ArgumentContext { - const _localctx: ArgumentContext = new ArgumentContext(this._ctx, this.state); - this.enterRule(_localctx, 14, mongoParser.RULE_argument); - try { - this.state = 88; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.RegexLiteral: - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 85; - this.literal(); - } - break; - case mongoParser.T__3: - this.enterOuterAlt(_localctx, 2); - { - this.state = 86; - this.objectLiteral(); - } - break; - case mongoParser.T__5: - this.enterOuterAlt(_localctx, 3); - { - this.state = 87; - this.arrayLiteral(); - } - break; - default: - throw new NoViableAltException(this); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public objectLiteral(): ObjectLiteralContext { - const _localctx: ObjectLiteralContext = new ObjectLiteralContext(this._ctx, this.state); - this.enterRule(_localctx, 16, mongoParser.RULE_objectLiteral); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 90; - this.match(mongoParser.T__3); - this.state = 92; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (_la === mongoParser.StringLiteral || _la === mongoParser.IDENTIFIER) { - { - this.state = 91; - this.propertyNameAndValueList(); - } - } - - this.state = 95; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (_la === mongoParser.T__1) { - { - this.state = 94; - this.match(mongoParser.T__1); - } - } - - this.state = 97; - this.match(mongoParser.T__4); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public arrayLiteral(): ArrayLiteralContext { - const _localctx: ArrayLiteralContext = new ArrayLiteralContext(this._ctx, this.state); - this.enterRule(_localctx, 18, mongoParser.RULE_arrayLiteral); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 99; - this.match(mongoParser.T__5); - this.state = 101; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ( - (_la & ~0x1f) === 0 && - ((1 << _la) & - ((1 << mongoParser.T__3) | - (1 << mongoParser.T__5) | - (1 << mongoParser.RegexLiteral) | - (1 << mongoParser.StringLiteral) | - (1 << mongoParser.NullLiteral) | - (1 << mongoParser.BooleanLiteral) | - (1 << mongoParser.NumericLiteral) | - (1 << mongoParser.IDENTIFIER))) !== - 0 - ) { - { - this.state = 100; - this.elementList(); - } - } - - this.state = 103; - this.match(mongoParser.T__6); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public elementList(): ElementListContext { - const _localctx: ElementListContext = new ElementListContext(this._ctx, this.state); - this.enterRule(_localctx, 20, mongoParser.RULE_elementList); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 105; - this.propertyValue(); - this.state = 110; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === mongoParser.T__1) { - { - { - this.state = 106; - this.match(mongoParser.T__1); - this.state = 107; - this.propertyValue(); - } - } - this.state = 112; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyNameAndValueList(): PropertyNameAndValueListContext { - const _localctx: PropertyNameAndValueListContext = new PropertyNameAndValueListContext(this._ctx, this.state); - this.enterRule(_localctx, 22, mongoParser.RULE_propertyNameAndValueList); - try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 113; - this.propertyAssignment(); - this.state = 118; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 13, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 114; - this.match(mongoParser.T__1); - this.state = 115; - this.propertyAssignment(); - } - } - } - this.state = 120; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 13, this._ctx); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyAssignment(): PropertyAssignmentContext { - const _localctx: PropertyAssignmentContext = new PropertyAssignmentContext(this._ctx, this.state); - this.enterRule(_localctx, 24, mongoParser.RULE_propertyAssignment); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 121; - this.propertyName(); - this.state = 122; - this.match(mongoParser.T__7); - this.state = 123; - this.propertyValue(); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyValue(): PropertyValueContext { - const _localctx: PropertyValueContext = new PropertyValueContext(this._ctx, this.state); - this.enterRule(_localctx, 26, mongoParser.RULE_propertyValue); - try { - this.state = 129; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.RegexLiteral: - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 125; - this.literal(); - } - break; - case mongoParser.T__3: - this.enterOuterAlt(_localctx, 2); - { - this.state = 126; - this.objectLiteral(); - } - break; - case mongoParser.T__5: - this.enterOuterAlt(_localctx, 3); - { - this.state = 127; - this.arrayLiteral(); - } - break; - case mongoParser.IDENTIFIER: - this.enterOuterAlt(_localctx, 4); - { - this.state = 128; - this.functionCall(); - } - break; - default: - throw new NoViableAltException(this); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public literal(): LiteralContext { - const _localctx: LiteralContext = new LiteralContext(this._ctx, this.state); - this.enterRule(_localctx, 28, mongoParser.RULE_literal); - let _la: number; - try { - this.state = 134; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case mongoParser.StringLiteral: - case mongoParser.NullLiteral: - case mongoParser.BooleanLiteral: - this.enterOuterAlt(_localctx, 1); - { - this.state = 131; - _la = this._input.LA(1); - if ( - !( - (_la & ~0x1f) === 0 && - ((1 << _la) & - ((1 << mongoParser.StringLiteral) | - (1 << mongoParser.NullLiteral) | - (1 << mongoParser.BooleanLiteral))) !== - 0 - ) - ) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - break; - case mongoParser.RegexLiteral: - this.enterOuterAlt(_localctx, 2); - { - this.state = 132; - this.match(mongoParser.RegexLiteral); - } - break; - case mongoParser.NumericLiteral: - this.enterOuterAlt(_localctx, 3); - { - this.state = 133; - this.match(mongoParser.NumericLiteral); - } - break; - default: - throw new NoViableAltException(this); - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public propertyName(): PropertyNameContext { - const _localctx: PropertyNameContext = new PropertyNameContext(this._ctx, this.state); - this.enterRule(_localctx, 30, mongoParser.RULE_propertyName); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 136; - _la = this._input.LA(1); - if (!(_la === mongoParser.StringLiteral || _la === mongoParser.IDENTIFIER)) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - @RuleVersion(0) - public comment(): CommentContext { - const _localctx: CommentContext = new CommentContext(this._ctx, this.state); - this.enterRule(_localctx, 32, mongoParser.RULE_comment); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 138; - _la = this._input.LA(1); - if (!(_la === mongoParser.SingleLineComment || _la === mongoParser.MultiLineComment)) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return _localctx; - } - - public static readonly _serializedATN: string = - '\x03\uAF6F\u8320\u479D\uB75C\u4880\u1605\u191C\uAB37\x03\x1A\x8F\x04\x02' + - '\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07' + - '\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04' + - '\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x03' + - '\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x07\x03+\n\x03\f\x03\x0E' + - '\x03.\v\x03\x03\x04\x03\x04\x03\x04\x05\x043\n\x04\x03\x04\x03\x04\x06' + - '\x047\n\x04\r\x04\x0E\x048\x03\x04\x05\x04<\n\x04\x03\x05\x03\x05\x03' + - '\x06\x03\x06\x03\x06\x07\x06C\n\x06\f\x06\x0E\x06F\v\x06\x03\x07\x03\x07' + - '\x03\x07\x03\b\x03\b\x03\b\x03\b\x07\bO\n\b\f\b\x0E\bR\v\b\x05\bT\n\b' + - '\x03\b\x03\b\x03\t\x03\t\x03\t\x05\t[\n\t\x03\n\x03\n\x05\n_\n\n\x03\n' + - '\x05\nb\n\n\x03\n\x03\n\x03\v\x03\v\x05\vh\n\v\x03\v\x03\v\x03\f\x03\f' + - '\x03\f\x07\fo\n\f\f\f\x0E\fr\v\f\x03\r\x03\r\x03\r\x07\rw\n\r\f\r\x0E' + - '\rz\v\r\x03\x0E\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x0F' + - '\x05\x0F\x84\n\x0F\x03\x10\x03\x10\x03\x10\x05\x10\x89\n\x10\x03\x11\x03' + - '\x11\x03\x12\x03\x12\x03\x12\x02\x02\x02\x13\x02\x02\x04\x02\x06\x02\b' + - '\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02' + - '\x1C\x02\x1E\x02 \x02"\x02\x02\x05\x03\x02\x0E\x10\x04\x02\x0E\x0E\x17' + - '\x17\x03\x02\f\r\x92\x02$\x03\x02\x02\x02\x04,\x03\x02\x02\x02\x06/\x03' + - '\x02\x02\x02\b=\x03\x02\x02\x02\n?\x03\x02\x02\x02\fG\x03\x02\x02\x02' + - '\x0EJ\x03\x02\x02\x02\x10Z\x03\x02\x02\x02\x12\\\x03\x02\x02\x02\x14e' + - '\x03\x02\x02\x02\x16k\x03\x02\x02\x02\x18s\x03\x02\x02\x02\x1A{\x03\x02' + - '\x02\x02\x1C\x83\x03\x02\x02\x02\x1E\x88\x03\x02\x02\x02 \x8A\x03\x02' + - '\x02\x02"\x8C\x03\x02\x02\x02$%\x05\x04\x03\x02%&\x07\x02\x02\x03&\x03' + - "\x03\x02\x02\x02'+\x05\x06\x04\x02(+\x05\b\x05\x02)+\x05\"\x12\x02*'" + - '\x03\x02\x02\x02*(\x03\x02\x02\x02*)\x03\x02\x02\x02+.\x03\x02\x02\x02' + - ',*\x03\x02\x02\x02,-\x03\x02\x02\x02-\x05\x03\x02\x02\x02.,\x03\x02\x02' + - '\x02/2\x07\x16\x02\x0201\x07\x15\x02\x0213\x05\n\x06\x0220\x03\x02\x02' + - '\x0223\x03\x02\x02\x0236\x03\x02\x02\x0245\x07\x15\x02\x0257\x05\f\x07' + - '\x0264\x03\x02\x02\x0278\x03\x02\x02\x0286\x03\x02\x02\x0289\x03\x02\x02' + - '\x029;\x03\x02\x02\x02:<\x07\x14\x02\x02;:\x03\x02\x02\x02;<\x03\x02\x02' + - '\x02<\x07\x03\x02\x02\x02=>\x07\x14\x02\x02>\t\x03\x02\x02\x02?D\x07\x17' + - '\x02\x02@A\x07\x15\x02\x02AC\x07\x17\x02\x02B@\x03\x02\x02\x02CF\x03\x02' + - '\x02\x02DB\x03\x02\x02\x02DE\x03\x02\x02\x02E\v\x03\x02\x02\x02FD\x03' + - '\x02\x02\x02GH\x07\x17\x02\x02HI\x05\x0E\b\x02I\r\x03\x02\x02\x02JS\x07' + - '\x03\x02\x02KP\x05\x10\t\x02LM\x07\x04\x02\x02MO\x05\x10\t\x02NL\x03\x02' + - '\x02\x02OR\x03\x02\x02\x02PN\x03\x02\x02\x02PQ\x03\x02\x02\x02QT\x03\x02' + - '\x02\x02RP\x03\x02\x02\x02SK\x03\x02\x02\x02ST\x03\x02\x02\x02TU\x03\x02' + - '\x02\x02UV\x07\x05\x02\x02V\x0F\x03\x02\x02\x02W[\x05\x1E\x10\x02X[\x05' + - '\x12\n\x02Y[\x05\x14\v\x02ZW\x03\x02\x02\x02ZX\x03\x02\x02\x02ZY\x03\x02' + - '\x02\x02[\x11\x03\x02\x02\x02\\^\x07\x06\x02\x02]_\x05\x18\r\x02^]\x03' + - '\x02\x02\x02^_\x03\x02\x02\x02_a\x03\x02\x02\x02`b\x07\x04\x02\x02a`\x03' + - '\x02\x02\x02ab\x03\x02\x02\x02bc\x03\x02\x02\x02cd\x07\x07\x02\x02d\x13' + - '\x03\x02\x02\x02eg\x07\b\x02\x02fh\x05\x16\f\x02gf\x03\x02\x02\x02gh\x03' + - '\x02\x02\x02hi\x03\x02\x02\x02ij\x07\t\x02\x02j\x15\x03\x02\x02\x02kp' + - '\x05\x1C\x0F\x02lm\x07\x04\x02\x02mo\x05\x1C\x0F\x02nl\x03\x02\x02\x02' + - 'or\x03\x02\x02\x02pn\x03\x02\x02\x02pq\x03\x02\x02\x02q\x17\x03\x02\x02' + - '\x02rp\x03\x02\x02\x02sx\x05\x1A\x0E\x02tu\x07\x04\x02\x02uw\x05\x1A\x0E' + - '\x02vt\x03\x02\x02\x02wz\x03\x02\x02\x02xv\x03\x02\x02\x02xy\x03\x02\x02' + - '\x02y\x19\x03\x02\x02\x02zx\x03\x02\x02\x02{|\x05 \x11\x02|}\x07\n\x02' + - '\x02}~\x05\x1C\x0F\x02~\x1B\x03\x02\x02\x02\x7F\x84\x05\x1E\x10\x02\x80' + - '\x84\x05\x12\n\x02\x81\x84\x05\x14\v\x02\x82\x84\x05\f\x07\x02\x83\x7F' + - '\x03\x02\x02\x02\x83\x80\x03\x02\x02\x02\x83\x81\x03\x02\x02\x02\x83\x82' + - '\x03\x02\x02\x02\x84\x1D\x03\x02\x02\x02\x85\x89\t\x02\x02\x02\x86\x89' + - '\x07\v\x02\x02\x87\x89\x07\x11\x02\x02\x88\x85\x03\x02\x02\x02\x88\x86' + - '\x03\x02\x02\x02\x88\x87\x03\x02\x02\x02\x89\x1F\x03\x02\x02\x02\x8A\x8B' + - '\t\x03\x02\x02\x8B!\x03\x02\x02\x02\x8C\x8D\t\x04\x02\x02\x8D#\x03\x02' + - '\x02\x02\x12*,28;DPSZ^agpx\x83\x88'; - public static __ATN: ATN; - public static get _ATN(): ATN { - if (!mongoParser.__ATN) { - mongoParser.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(mongoParser._serializedATN)); - } - - return mongoParser.__ATN; - } -} - -export class MongoCommandsContext extends ParserRuleContext { - public commands(): CommandsContext { - return this.getRuleContext(0, CommandsContext); - } - public EOF(): TerminalNode { - return this.getToken(mongoParser.EOF, 0); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_mongoCommands; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterMongoCommands) listener.enterMongoCommands(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitMongoCommands) listener.exitMongoCommands(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitMongoCommands) return visitor.visitMongoCommands(this); - else return visitor.visitChildren(this); - } -} - -export class CommandsContext extends ParserRuleContext { - public command(): CommandContext[]; - public command(i: number): CommandContext; - public command(i?: number): CommandContext | CommandContext[] { - if (i === undefined) { - return this.getRuleContexts(CommandContext); - } else { - return this.getRuleContext(i, CommandContext); - } - } - public emptyCommand(): EmptyCommandContext[]; - public emptyCommand(i: number): EmptyCommandContext; - public emptyCommand(i?: number): EmptyCommandContext | EmptyCommandContext[] { - if (i === undefined) { - return this.getRuleContexts(EmptyCommandContext); - } else { - return this.getRuleContext(i, EmptyCommandContext); - } - } - public comment(): CommentContext[]; - public comment(i: number): CommentContext; - public comment(i?: number): CommentContext | CommentContext[] { - if (i === undefined) { - return this.getRuleContexts(CommentContext); - } else { - return this.getRuleContext(i, CommentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_commands; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCommands) listener.enterCommands(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCommands) listener.exitCommands(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCommands) return visitor.visitCommands(this); - else return visitor.visitChildren(this); - } -} - -export class CommandContext extends ParserRuleContext { - public DB(): TerminalNode { - return this.getToken(mongoParser.DB, 0); - } - public DOT(): TerminalNode[]; - public DOT(i: number): TerminalNode; - public DOT(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.DOT); - } else { - return this.getToken(mongoParser.DOT, i); - } - } - public collection(): CollectionContext | undefined { - return this.tryGetRuleContext(0, CollectionContext); - } - public functionCall(): FunctionCallContext[]; - public functionCall(i: number): FunctionCallContext; - public functionCall(i?: number): FunctionCallContext | FunctionCallContext[] { - if (i === undefined) { - return this.getRuleContexts(FunctionCallContext); - } else { - return this.getRuleContext(i, FunctionCallContext); - } - } - public SEMICOLON(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.SEMICOLON, 0); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_command; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCommand) listener.enterCommand(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCommand) listener.exitCommand(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCommand) return visitor.visitCommand(this); - else return visitor.visitChildren(this); - } -} - -export class EmptyCommandContext extends ParserRuleContext { - public SEMICOLON(): TerminalNode { - return this.getToken(mongoParser.SEMICOLON, 0); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_emptyCommand; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterEmptyCommand) listener.enterEmptyCommand(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitEmptyCommand) listener.exitEmptyCommand(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitEmptyCommand) return visitor.visitEmptyCommand(this); - else return visitor.visitChildren(this); - } -} - -export class CollectionContext extends ParserRuleContext { - public IDENTIFIER(): TerminalNode[]; - public IDENTIFIER(i: number): TerminalNode; - public IDENTIFIER(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.IDENTIFIER); - } else { - return this.getToken(mongoParser.IDENTIFIER, i); - } - } - public DOT(): TerminalNode[]; - public DOT(i: number): TerminalNode; - public DOT(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(mongoParser.DOT); - } else { - return this.getToken(mongoParser.DOT, i); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_collection; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterCollection) listener.enterCollection(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitCollection) listener.exitCollection(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitCollection) return visitor.visitCollection(this); - else return visitor.visitChildren(this); - } -} - -export class FunctionCallContext extends ParserRuleContext { - public _FUNCTION_NAME: Token; - public arguments(): ArgumentsContext { - return this.getRuleContext(0, ArgumentsContext); - } - public IDENTIFIER(): TerminalNode { - return this.getToken(mongoParser.IDENTIFIER, 0); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_functionCall; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterFunctionCall) listener.enterFunctionCall(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitFunctionCall) listener.exitFunctionCall(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitFunctionCall) return visitor.visitFunctionCall(this); - else return visitor.visitChildren(this); - } -} - -export class ArgumentsContext extends ParserRuleContext { - public _OPEN_PARENTHESIS: Token; - public _CLOSED_PARENTHESIS: Token; - public argument(): ArgumentContext[]; - public argument(i: number): ArgumentContext; - public argument(i?: number): ArgumentContext | ArgumentContext[] { - if (i === undefined) { - return this.getRuleContexts(ArgumentContext); - } else { - return this.getRuleContext(i, ArgumentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_arguments; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArguments) listener.enterArguments(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArguments) listener.exitArguments(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArguments) return visitor.visitArguments(this); - else return visitor.visitChildren(this); - } -} - -export class ArgumentContext extends ParserRuleContext { - public literal(): LiteralContext | undefined { - return this.tryGetRuleContext(0, LiteralContext); - } - public objectLiteral(): ObjectLiteralContext | undefined { - return this.tryGetRuleContext(0, ObjectLiteralContext); - } - public arrayLiteral(): ArrayLiteralContext | undefined { - return this.tryGetRuleContext(0, ArrayLiteralContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_argument; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArgument) listener.enterArgument(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArgument) listener.exitArgument(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArgument) return visitor.visitArgument(this); - else return visitor.visitChildren(this); - } -} - -export class ObjectLiteralContext extends ParserRuleContext { - public propertyNameAndValueList(): PropertyNameAndValueListContext | undefined { - return this.tryGetRuleContext(0, PropertyNameAndValueListContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_objectLiteral; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterObjectLiteral) listener.enterObjectLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitObjectLiteral) listener.exitObjectLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitObjectLiteral) return visitor.visitObjectLiteral(this); - else return visitor.visitChildren(this); - } -} - -export class ArrayLiteralContext extends ParserRuleContext { - public elementList(): ElementListContext | undefined { - return this.tryGetRuleContext(0, ElementListContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_arrayLiteral; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterArrayLiteral) listener.enterArrayLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitArrayLiteral) listener.exitArrayLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitArrayLiteral) return visitor.visitArrayLiteral(this); - else return visitor.visitChildren(this); - } -} - -export class ElementListContext extends ParserRuleContext { - public propertyValue(): PropertyValueContext[]; - public propertyValue(i: number): PropertyValueContext; - public propertyValue(i?: number): PropertyValueContext | PropertyValueContext[] { - if (i === undefined) { - return this.getRuleContexts(PropertyValueContext); - } else { - return this.getRuleContext(i, PropertyValueContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_elementList; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterElementList) listener.enterElementList(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitElementList) listener.exitElementList(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitElementList) return visitor.visitElementList(this); - else return visitor.visitChildren(this); - } -} - -export class PropertyNameAndValueListContext extends ParserRuleContext { - public propertyAssignment(): PropertyAssignmentContext[]; - public propertyAssignment(i: number): PropertyAssignmentContext; - public propertyAssignment(i?: number): PropertyAssignmentContext | PropertyAssignmentContext[] { - if (i === undefined) { - return this.getRuleContexts(PropertyAssignmentContext); - } else { - return this.getRuleContext(i, PropertyAssignmentContext); - } - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_propertyNameAndValueList; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyNameAndValueList) listener.enterPropertyNameAndValueList(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyNameAndValueList) listener.exitPropertyNameAndValueList(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyNameAndValueList) return visitor.visitPropertyNameAndValueList(this); - else return visitor.visitChildren(this); - } -} - -export class PropertyAssignmentContext extends ParserRuleContext { - public propertyName(): PropertyNameContext { - return this.getRuleContext(0, PropertyNameContext); - } - public propertyValue(): PropertyValueContext { - return this.getRuleContext(0, PropertyValueContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_propertyAssignment; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyAssignment) listener.enterPropertyAssignment(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyAssignment) listener.exitPropertyAssignment(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyAssignment) return visitor.visitPropertyAssignment(this); - else return visitor.visitChildren(this); - } -} - -export class PropertyValueContext extends ParserRuleContext { - public literal(): LiteralContext | undefined { - return this.tryGetRuleContext(0, LiteralContext); - } - public objectLiteral(): ObjectLiteralContext | undefined { - return this.tryGetRuleContext(0, ObjectLiteralContext); - } - public arrayLiteral(): ArrayLiteralContext | undefined { - return this.tryGetRuleContext(0, ArrayLiteralContext); - } - public functionCall(): FunctionCallContext | undefined { - return this.tryGetRuleContext(0, FunctionCallContext); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_propertyValue; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyValue) listener.enterPropertyValue(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyValue) listener.exitPropertyValue(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyValue) return visitor.visitPropertyValue(this); - else return visitor.visitChildren(this); - } -} - -export class LiteralContext extends ParserRuleContext { - public NullLiteral(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.NullLiteral, 0); - } - public BooleanLiteral(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.BooleanLiteral, 0); - } - public StringLiteral(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.StringLiteral, 0); - } - public RegexLiteral(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.RegexLiteral, 0); - } - public NumericLiteral(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.NumericLiteral, 0); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_literal; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterLiteral) listener.enterLiteral(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitLiteral) listener.exitLiteral(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitLiteral) return visitor.visitLiteral(this); - else return visitor.visitChildren(this); - } -} - -export class PropertyNameContext extends ParserRuleContext { - public StringLiteral(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.StringLiteral, 0); - } - public IDENTIFIER(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.IDENTIFIER, 0); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_propertyName; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterPropertyName) listener.enterPropertyName(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitPropertyName) listener.exitPropertyName(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitPropertyName) return visitor.visitPropertyName(this); - else return visitor.visitChildren(this); - } -} - -export class CommentContext extends ParserRuleContext { - public SingleLineComment(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.SingleLineComment, 0); - } - public MultiLineComment(): TerminalNode | undefined { - return this.tryGetToken(mongoParser.MultiLineComment, 0); - } - constructor(parent: ParserRuleContext, invokingState: number); - constructor(parent: ParserRuleContext, invokingState: number) { - super(parent, invokingState); - } - @Override public get ruleIndex(): number { - return mongoParser.RULE_comment; - } - @Override - public enterRule(listener: mongoListener): void { - if (listener.enterComment) listener.enterComment(this); - } - @Override - public exitRule(listener: mongoListener): void { - if (listener.exitComment) listener.exitComment(this); - } - @Override - public accept(visitor: mongoVisitor): Result { - if (visitor.visitComment) return visitor.visitComment(this); - else return visitor.visitChildren(this); - } -} diff --git a/src/documentdb/grammar/mongoVisitor.ts b/src/documentdb/grammar/mongoVisitor.ts deleted file mode 100644 index 34f9bf665..000000000 --- a/src/documentdb/grammar/mongoVisitor.ts +++ /dev/null @@ -1,160 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// Generated from ./grammar/mongo.g4 by ANTLR 4.6-SNAPSHOT - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { type ParseTreeVisitor } from 'antlr4ts/tree/ParseTreeVisitor'; -import { - type ArgumentContext, - type ArgumentsContext, - type ArrayLiteralContext, - type CollectionContext, - type CommandContext, - type CommandsContext, - type CommentContext, - type ElementListContext, - type EmptyCommandContext, - type FunctionCallContext, - type LiteralContext, - type MongoCommandsContext, - type ObjectLiteralContext, - type PropertyAssignmentContext, - type PropertyNameAndValueListContext, - type PropertyNameContext, - type PropertyValueContext, -} from './mongoParser'; - -/** - * This interface defines a complete generic visitor for a parse tree produced - * by `mongoParser`. - * - * @param The return type of the visit operation. Use `void` for - * operations with no return type. - */ -export interface mongoVisitor extends ParseTreeVisitor { - /** - * Visit a parse tree produced by `mongoParser.mongoCommands`. - * @param ctx the parse tree - * @return the visitor result - */ - visitMongoCommands?: (ctx: MongoCommandsContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.commands`. - * @param ctx the parse tree - * @return the visitor result - */ - visitCommands?: (ctx: CommandsContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.command`. - * @param ctx the parse tree - * @return the visitor result - */ - visitCommand?: (ctx: CommandContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.emptyCommand`. - * @param ctx the parse tree - * @return the visitor result - */ - visitEmptyCommand?: (ctx: EmptyCommandContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.collection`. - * @param ctx the parse tree - * @return the visitor result - */ - visitCollection?: (ctx: CollectionContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.functionCall`. - * @param ctx the parse tree - * @return the visitor result - */ - visitFunctionCall?: (ctx: FunctionCallContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.arguments`. - * @param ctx the parse tree - * @return the visitor result - */ - visitArguments?: (ctx: ArgumentsContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.argument`. - * @param ctx the parse tree - * @return the visitor result - */ - visitArgument?: (ctx: ArgumentContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.objectLiteral`. - * @param ctx the parse tree - * @return the visitor result - */ - visitObjectLiteral?: (ctx: ObjectLiteralContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.arrayLiteral`. - * @param ctx the parse tree - * @return the visitor result - */ - visitArrayLiteral?: (ctx: ArrayLiteralContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.elementList`. - * @param ctx the parse tree - * @return the visitor result - */ - visitElementList?: (ctx: ElementListContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.propertyNameAndValueList`. - * @param ctx the parse tree - * @return the visitor result - */ - visitPropertyNameAndValueList?: (ctx: PropertyNameAndValueListContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.propertyAssignment`. - * @param ctx the parse tree - * @return the visitor result - */ - visitPropertyAssignment?: (ctx: PropertyAssignmentContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.propertyValue`. - * @param ctx the parse tree - * @return the visitor result - */ - visitPropertyValue?: (ctx: PropertyValueContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.literal`. - * @param ctx the parse tree - * @return the visitor result - */ - visitLiteral?: (ctx: LiteralContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.propertyName`. - * @param ctx the parse tree - * @return the visitor result - */ - visitPropertyName?: (ctx: PropertyNameContext) => Result; - - /** - * Visit a parse tree produced by `mongoParser.comment`. - * @param ctx the parse tree - * @return the visitor result - */ - visitComment?: (ctx: CommentContext) => Result; -} diff --git a/src/documentdb/grammar/visitors.ts b/src/documentdb/grammar/visitors.ts deleted file mode 100644 index 053c101bd..000000000 --- a/src/documentdb/grammar/visitors.ts +++ /dev/null @@ -1,90 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { type ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { type ErrorNode } from 'antlr4ts/tree/ErrorNode'; -import { type ParseTree } from 'antlr4ts/tree/ParseTree'; -import { type TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { - type ArgumentContext, - type ArgumentsContext, - type CollectionContext, - type CommandContext, - type CommandsContext, - type FunctionCallContext, - type MongoCommandsContext, -} from './mongoParser'; -import { type mongoVisitor } from './mongoVisitor'; - -export class MongoVisitor implements mongoVisitor { - visitMongoCommands(ctx: MongoCommandsContext): T { - return this.visitChildren(ctx); - } - - visitCommands(ctx: CommandsContext): T { - return this.visitChildren(ctx); - } - - visitCommand(ctx: CommandContext): T { - return this.visitChildren(ctx); - } - - visitCollection(ctx: CollectionContext): T { - return this.visitChildren(ctx); - } - - visitFunctionCall(ctx: FunctionCallContext): T { - return this.visitChildren(ctx); - } - - visitArgument(ctx: ArgumentContext): T { - return this.visitChildren(ctx); - } - - visitArguments(ctx: ArgumentsContext): T { - return this.visitChildren(ctx); - } - - visit(tree: ParseTree): T { - return tree.accept(this); - } - - visitChildren(ctx: ParserRuleContext): T { - let result = this.defaultResult(ctx); - const n = ctx.childCount; - for (let i = 0; i < n; i++) { - if (!this.shouldVisitNextChild(ctx, result)) { - break; - } - - const childNode = ctx.getChild(i); - const childResult = childNode.accept(this); - result = this.aggregateResult(result, childResult); - } - return result; - } - - visitTerminal(node: TerminalNode): T { - return this.defaultResult(node); - } - - visitErrorNode(node: ErrorNode): T { - return this.defaultResult(node); - } - - protected defaultResult(_node: ParseTree): T { - // grandfathered-in. Unclear why this is null instead of type T - return (null); - } - - protected aggregateResult(aggregate: T, nextResult: T): T { - return !nextResult ? aggregate : nextResult; - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types - shouldVisitNextChild(_node, _currentResult: T): boolean { - return true; - } -} diff --git a/src/documentdb/scrapbook/MongoCommand.ts b/src/documentdb/scrapbook/MongoCommand.ts deleted file mode 100644 index bb54e498c..000000000 --- a/src/documentdb/scrapbook/MongoCommand.ts +++ /dev/null @@ -1,24 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { type RecognitionException } from 'antlr4ts'; -import type * as vscode from 'vscode'; - -export interface MongoCommand { - range: vscode.Range; - text: string; - collection?: string; - name?: string; - arguments?: string[]; - argumentObjects?: object[]; - errors?: ErrorDescription[]; - chained?: boolean; -} - -export interface ErrorDescription { - range: vscode.Range; - message: string; - exception?: RecognitionException; -} diff --git a/src/documentdb/scrapbook/ScrapbookHelpers.ts b/src/documentdb/scrapbook/ScrapbookHelpers.ts deleted file mode 100644 index b2bca937e..000000000 --- a/src/documentdb/scrapbook/ScrapbookHelpers.ts +++ /dev/null @@ -1,466 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { parseError, type IParsedError } from '@microsoft/vscode-azext-utils'; -import * as l10n from '@vscode/l10n'; -import { ANTLRInputStream as InputStream } from 'antlr4ts/ANTLRInputStream'; -import { CommonTokenStream } from 'antlr4ts/CommonTokenStream'; -import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; -import { type ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { EJSON, ObjectId } from 'bson'; -import * as vscode from 'vscode'; -import { filterType, findType } from '../../utils/array'; -import { nonNullProp, nonNullValue } from '../../utils/nonNull'; -import { mongoLexer } from '../grammar/mongoLexer'; -import * as mongoParser from '../grammar/mongoParser'; -import { MongoVisitor } from '../grammar/visitors'; -import { LexerErrorListener, ParserErrorListener } from './errorListeners'; -import { type ErrorDescription, type MongoCommand } from './MongoCommand'; - -export function stripQuotes(term: string): string { - if ((term.startsWith("'") && term.endsWith("'")) || (term.startsWith('"') && term.endsWith('"'))) { - return term.substring(1, term.length - 1); - } - return term; -} - -export function getAllErrorsFromTextDocument(document: vscode.TextDocument): vscode.Diagnostic[] { - const commands = getAllCommandsFromText(document.getText()); - const errors: vscode.Diagnostic[] = []; - for (const command of commands) { - for (const error of command.errors || []) { - const diagnostic = new vscode.Diagnostic(error.range, error.message); - errors.push(diagnostic); - } - } - - return errors; -} - -export function getAllCommandsFromText(content: string): MongoCommand[] { - const lexer = new mongoLexer(new InputStream(content)); - const lexerListener = new LexerErrorListener(); - lexer.removeErrorListeners(); // Default listener outputs to the console - lexer.addErrorListener(lexerListener); - const tokens: CommonTokenStream = new CommonTokenStream(lexer); - - const parser = new mongoParser.mongoParser(tokens); - const parserListener = new ParserErrorListener(); - parser.removeErrorListeners(); // Default listener outputs to the console - parser.addErrorListener(parserListener); - - const commandsContext: mongoParser.MongoCommandsContext = parser.mongoCommands(); - const commands = new FindMongoCommandsVisitor().visit(commandsContext); - - // Match errors with commands based on location - const errors = lexerListener.errors.concat(parserListener.errors); - errors.sort((a, b) => { - const linediff = a.range.start.line - b.range.start.line; - const chardiff = a.range.start.character - b.range.start.character; - return linediff || chardiff; - }); - for (const err of errors) { - const associatedCommand = findCommandAtPosition(commands, err.range.start); - if (associatedCommand) { - associatedCommand.errors = associatedCommand.errors || []; - associatedCommand.errors.push(err); - } else { - // Create a new command to hook this up to - const emptyCommand: MongoCommand = { - collection: undefined, - name: undefined, - range: err.range, - text: '', - }; - emptyCommand.errors = [err]; - commands.push(emptyCommand); - } - } - - return commands; -} - -export function findCommandAtPosition(commands: MongoCommand[], position?: vscode.Position): MongoCommand { - let lastCommandOnSameLine: MongoCommand | undefined; - let lastCommandBeforePosition: MongoCommand | undefined; - if (position) { - for (const command of commands) { - if (command.range.contains(position)) { - return command; - } - if (command.range.end.line === position.line) { - lastCommandOnSameLine = command; - } - if (command.range.end.isBefore(position)) { - lastCommandBeforePosition = command; - } - } - } - return lastCommandOnSameLine || lastCommandBeforePosition || commands[commands.length - 1]; -} - -class FindMongoCommandsVisitor extends MongoVisitor { - private commands: MongoCommand[] = []; - - public visitCommand(ctx: mongoParser.CommandContext): MongoCommand[] { - const funcCallCount: number = filterType(ctx.children, mongoParser.FunctionCallContext).length; - const stop = nonNullProp(ctx, 'stop', 'ctx.stop', 'ScrapbookHelpers.ts'); - this.commands.push({ - range: new vscode.Range( - ctx.start.line - 1, - ctx.start.charPositionInLine, - stop.line - 1, - stop.charPositionInLine, - ), - text: ctx.text, - name: '', - arguments: [], - argumentObjects: [], - chained: funcCallCount > 1 ? true : false, - }); - return super.visitCommand(ctx); - } - - public visitCollection(ctx: mongoParser.CollectionContext): MongoCommand[] { - this.commands[this.commands.length - 1].collection = ctx.text; - return super.visitCollection(ctx); - } - - public visitFunctionCall(ctx: mongoParser.FunctionCallContext): MongoCommand[] { - if (ctx.parent instanceof mongoParser.CommandContext) { - this.commands[this.commands.length - 1].name = (ctx._FUNCTION_NAME && ctx._FUNCTION_NAME.text) || ''; - } - return super.visitFunctionCall(ctx); - } - - public visitArgument(ctx: mongoParser.ArgumentContext): MongoCommand[] { - try { - const argumentsContext = ctx.parent; - if (argumentsContext) { - const functionCallContext = argumentsContext.parent; - if (functionCallContext && functionCallContext.parent instanceof mongoParser.CommandContext) { - const lastCommand = this.commands[this.commands.length - 1]; - const argAsObject = this.contextToObject(ctx); - - const argText = EJSON.stringify(argAsObject); - nonNullProp(lastCommand, 'arguments', 'lastCommand.arguments', 'ScrapbookHelpers.ts').push(argText); - const escapeHandled = this.deduplicateEscapesForRegex(argText); - let ejsonParsed = {}; - try { - // eslint-disable-next-line , @typescript-eslint/no-unsafe-assignment - ejsonParsed = EJSON.parse(escapeHandled); - } catch (error) { - //EJSON parse failed due to a wrong flag, etc. - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - } - nonNullProp( - lastCommand, - 'argumentObjects', - 'lastCommand.argumentObjects', - 'ScrapbookHelpers.ts', - ).push(ejsonParsed); - } - } - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - } - return super.visitArgument(ctx); - } - - protected defaultResult(_node: ParseTree): MongoCommand[] { - return this.commands; - } - - //eslint-disable-next-line @typescript-eslint/no-wrapper-object-types - private contextToObject(ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext): Object { - if (!ctx || ctx.childCount === 0) { - //Base case and malformed statements - return {}; - } - // In a well formed expression, Argument and propertyValue tokens should have exactly one child, from their definitions in mongo.g4 - const child: ParseTree = nonNullProp(ctx, 'children', 'ctx.children', 'ScrapbookHelpers.ts')[0]; - if (child instanceof mongoParser.LiteralContext) { - return this.literalContextToObject(child, ctx); - } else if (child instanceof mongoParser.ObjectLiteralContext) { - return this.objectLiteralContextToObject(child); - } else if (child instanceof mongoParser.ArrayLiteralContext) { - return this.arrayLiteralContextToObject(child); - } else if (child instanceof mongoParser.FunctionCallContext) { - return this.functionCallContextToObject(child, ctx); - } else if (child instanceof ErrorNode) { - return {}; - } else { - this.addErrorToCommand( - l10n.t('Unrecognized node type encountered. We could not parse {text}', { text: child.text }), - ctx, - ); - return {}; - } - } - - private literalContextToObject( - child: mongoParser.LiteralContext, - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, - //eslint-disable-next-line @typescript-eslint/no-wrapper-object-types - ): Object { - const text = child.text; - const tokenType = child.start.type; - const nonStringLiterals = [ - mongoParser.mongoParser.NullLiteral, - mongoParser.mongoParser.BooleanLiteral, - mongoParser.mongoParser.NumericLiteral, - ]; - if (tokenType === mongoParser.mongoParser.StringLiteral) { - return stripQuotes(text); - } else if (tokenType === mongoParser.mongoParser.RegexLiteral) { - return this.regexLiteralContextToObject(ctx, text); - } else if (nonStringLiterals.indexOf(tokenType) > -1) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return JSON.parse(text); - } else { - this.addErrorToCommand(l10n.t('Unrecognized token. Token text: {text}', { text }), ctx); - return {}; - } - } - - private objectLiteralContextToObject(child: mongoParser.ObjectLiteralContext): object { - const propertyNameAndValue = findType(child.children, mongoParser.PropertyNameAndValueListContext); - if (!propertyNameAndValue) { - // Argument is {} - return {}; - } else { - const parsedObject: object = {}; - const propertyAssignments = filterType( - propertyNameAndValue.children, - mongoParser.PropertyAssignmentContext, - ); - for (const propertyAssignment of propertyAssignments) { - const propertyAssignmentChildren = nonNullProp( - propertyAssignment, - 'children', - 'propertyAssignment.children', - 'ScrapbookHelpers.ts', - ); - const propertyName = propertyAssignmentChildren[0]; - const propertyValue = propertyAssignmentChildren[2]; - parsedObject[stripQuotes(propertyName.text)] = this.contextToObject(propertyValue); - } - return parsedObject; - } - } - - private arrayLiteralContextToObject(child: mongoParser.ArrayLiteralContext) { - const elementList = findType(child.children, mongoParser.ElementListContext); - if (elementList) { - const elementItems = filterType(elementList.children, mongoParser.PropertyValueContext); - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - return elementItems.map(this.contextToObject.bind(this)); - } else { - return []; - } - } - - private functionCallContextToObject( - child: mongoParser.FunctionCallContext, - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, - // eslint-disable-next-line @typescript-eslint/no-wrapper-object-types - ): Object { - const functionTokens = child.children; - const constructorCall: TerminalNode = nonNullValue( - findType(functionTokens, TerminalNode), - 'constructorCall', - 'ScrapbookHelpers.ts', - ); - const argumentsToken: mongoParser.ArgumentsContext = nonNullValue( - findType(functionTokens, mongoParser.ArgumentsContext), - 'argumentsToken', - 'ScrapbookHelpers.ts', - ); - if (!(argumentsToken._CLOSED_PARENTHESIS && argumentsToken._OPEN_PARENTHESIS)) { - //argumentsToken does not have '(' or ')' - this.addErrorToCommand( - l10n.t('Expecting parentheses or quotes at "{text}"', { text: constructorCall.text }), - ctx, - ); - return {}; - } - - const argumentContextArray: mongoParser.ArgumentContext[] = filterType( - argumentsToken.children, - mongoParser.ArgumentContext, - ); - if (argumentContextArray.length > 1) { - this.addErrorToCommand( - l10n.t('Too many arguments. Expecting 0 or 1 argument(s) to {constructorCall}', { - constructorCall: constructorCall.text, - }), - ctx, - ); - return {}; - } - - const tokenText: string | undefined = argumentContextArray.length ? argumentContextArray[0].text : undefined; - switch (constructorCall.text) { - case 'ObjectId': - return this.objectIdToObject(ctx, tokenText); - case 'ISODate': - return this.isodateToObject(ctx, tokenText); - case 'Date': - return this.dateToObject(ctx, tokenText); - default: - this.addErrorToCommand( - l10n.t( - 'Unrecognized node type encountered. Could not parse {constructorCall} as part of {functionCall}', - { constructorCall: constructorCall.text, functionCall: child.text }, - ), - ctx, - ); - return {}; - } - } - - private dateToObject( - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, - tokenText?: string, - // eslint-disable-next-line @typescript-eslint/no-wrapper-object-types - ): { $date: string } | Object { - // eslint-disable-next-line @typescript-eslint/no-wrapper-object-types - const date: Date | Object = this.tryToConstructDate(ctx, tokenText); - if (date instanceof Date) { - return { $date: date.toString() }; - } else { - return date; - } - } - - private isodateToObject( - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, - tokenText?: string, - // eslint-disable-next-line @typescript-eslint/no-wrapper-object-types - ): { $date: string } | Object { - // eslint-disable-next-line @typescript-eslint/no-wrapper-object-types - const date: Date | Object = this.tryToConstructDate(ctx, tokenText, true); - - if (date instanceof Date) { - return { $date: date.toISOString() }; - } else { - return date; - } - } - - private tryToConstructDate( - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, - tokenText?: string, - isIsodate: boolean = false, - // eslint-disable-next-line @typescript-eslint/no-wrapper-object-types - ): Date | Object { - if (!tokenText) { - // usage : ObjectID() - return new Date(); - } else { - try { - tokenText = stripQuotes(tokenText); - - // if the tokenText was an isodate, the last char must be Z - if (isIsodate) { - if (tokenText[tokenText.length - 1] !== 'Z') { - tokenText += 'Z'; - } - } - - return new Date(tokenText); - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - } - - private objectIdToObject( - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, - tokenText?: string, - // eslint-disable-next-line @typescript-eslint/no-wrapper-object-types - ): Object { - let hexID: string; - let constructedObject: ObjectId; - if (!tokenText) { - // usage : ObjectID() - constructedObject = new ObjectId(); - } else { - hexID = stripQuotes(tokenText); - try { - constructedObject = new ObjectId(hexID); - } catch (error) { - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - return { $oid: constructedObject.toString() }; - } - - private regexLiteralContextToObject( - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, - text: string, - // eslint-disable-next-line @typescript-eslint/no-wrapper-object-types - ): Object { - const separator = text.lastIndexOf('/'); - const flags = separator !== text.length - 1 ? text.substring(separator + 1) : ''; - const pattern = text.substring(1, separator); - try { - // validate the pattern and flags. - // It is intended for the errors thrown here to be handled by the catch block. - new RegExp(pattern, flags); - // we are passing back a $regex annotation, hence we ensure parity wit the $regex syntax - return { $regex: this.regexToStringNotation(pattern), $options: flags }; - } catch (error) { - //User may not have finished typing - const parsedError: IParsedError = parseError(error); - this.addErrorToCommand(parsedError.message, ctx); - return {}; - } - } - - private addErrorToCommand( - errorMessage: string, - ctx: mongoParser.ArgumentContext | mongoParser.PropertyValueContext, - ): void { - const command = this.commands[this.commands.length - 1]; - command.errors = command.errors || []; - const stop = nonNullProp(ctx, 'stop', 'ctx.stop', 'ScrapbookHelpers.ts'); - const currentErrorDesc: ErrorDescription = { - message: errorMessage, - range: new vscode.Range( - ctx.start.line - 1, - ctx.start.charPositionInLine, - stop.line - 1, - stop.charPositionInLine, - ), - }; - command.errors.push(currentErrorDesc); - } - - private regexToStringNotation(pattern: string): string { - // The equivalence: - // /ker\b/ <=> $regex: "ker\\b", /ker\\b/ <=> "ker\\\\b" - return pattern.replace(/\\([0-9a-z.*])/i, '\\\\$1'); - } - - private deduplicateEscapesForRegex(argAsString: string): string { - const removeDuplicatedBackslash = /\\{4}([0-9a-z.*])/gi; - /* - We remove duplicate backslashes due the behavior of '\b' - \b in a regex denotes word boundary, while \b in a string denotes backspace. - $regex syntax uses a string. Strings require slashes to be escaped, while /regex/ does not. Eg. /abc+\b/ is equivalent to {$regex: "abc+\\b"}. - {$regex: "abc+\b"} with an unescaped slash gets parsed as {$regex: }. The user can only type '\\b' (which is encoded as '\\\\b'). - We need to convert this appropriately. Other special characters (\n, \t, \r) don't carry significance in regexes - we don't handle those - What the regex does: '\\{4}' looks for the escaped slash 4 times. Lookahead checks if the character being escaped has a special meaning. - */ - return argAsString.replace(removeDuplicatedBackslash, '\\\\$1'); - } -} diff --git a/src/documentdb/scrapbook/ScrapbookService.ts b/src/documentdb/scrapbook/ScrapbookService.ts deleted file mode 100644 index b59639798..000000000 --- a/src/documentdb/scrapbook/ScrapbookService.ts +++ /dev/null @@ -1,295 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { openReadOnlyContent, type IActionContext } from '@microsoft/vscode-azext-utils'; -import * as l10n from '@vscode/l10n'; -import { EOL } from 'os'; -import * as vscode from 'vscode'; -import { ext } from '../../extensionVariables'; -import { type BaseClusterModel, type TreeCluster } from '../../tree/models/BaseClusterModel'; -import { type EmulatorConfiguration } from '../../utils/emulatorConfiguration'; -import { type DatabaseItemModel } from '../ClustersClient'; -import { CredentialCache } from '../CredentialCache'; -import { AuthMethodId } from '../auth/AuthMethod'; -import { type MongoCommand } from './MongoCommand'; -import { findCommandAtPosition, getAllCommandsFromText } from './ScrapbookHelpers'; -import { ShellScriptRunner } from './ShellScriptRunner'; -import { MongoCodeLensProvider } from './services/MongoCodeLensProvider'; - -export class ScrapbookServiceImpl { - //-------------------------------------------------------------------------------- - // Connection Management - //-------------------------------------------------------------------------------- - - private _cluster: TreeCluster | undefined; - private _database: DatabaseItemModel | undefined; - private readonly _mongoCodeLensProvider = new MongoCodeLensProvider(); - - /** - * Provides a CodeLens provider for the workspace. - */ - public getCodeLensProvider(): MongoCodeLensProvider { - return this._mongoCodeLensProvider; - } - - /** - * Sets the current cluster and database, updating the CodeLens provider. - */ - public async setConnectedCluster(cluster: TreeCluster, database: DatabaseItemModel) { - if (CredentialCache.getCredentials(cluster.clusterId)?.authMechanism !== AuthMethodId.NativeAuth) { - throw Error( - l10n.t('Unsupported authentication mechanism. Only SCRAM-SHA-256 (username/password) is supported.'), - ); - } - - // Update information - this._cluster = cluster; - this._database = database; - this._mongoCodeLensProvider.updateCodeLens(); - - // Update the Language Client/Server - // The language server needs credentials to connect to the cluster.. - // emulatorConfiguration is only available on ConnectionClusterModel (Connections View) - const emulatorConfig = - 'emulatorConfiguration' in cluster - ? (cluster.emulatorConfiguration as EmulatorConfiguration | undefined) - : undefined; - await ext.mongoLanguageClient.connect( - CredentialCache.getConnectionStringWithPassword(this._cluster.clusterId), - this._database.name, - emulatorConfig, - ); - } - - /** - * Clears the current connection. - */ - public async clearConnection() { - this._cluster = undefined; - this._database = undefined; - this._mongoCodeLensProvider.updateCodeLens(); - await ext.mongoLanguageClient.disconnect(); - } - - /** - * Returns true if a cluster and database are set. - */ - public isConnected(): boolean { - return !!this._cluster && !!this._database; - } - - /** - * Returns the current database name. - */ - public getDatabaseName(): string | undefined { - return this._database?.name; - } - - /** - * Returns the current cluster ID (stable identifier for caching). - */ - public getClusterId(): string | undefined { - return this._cluster?.clusterId; - } - - /** - * Returns a friendly display name of the connected cluster/database. - */ - public getDisplayName(): string | undefined { - return this._cluster && this._database ? `${this._cluster.name}/${this._database.name}` : undefined; - } - - //-------------------------------------------------------------------------------- - // Command Execution - //-------------------------------------------------------------------------------- - - private _isExecutingAllCommands: boolean = false; - private _singleCommandInExecution: MongoCommand | undefined; - - /** - * Executes all Mongo commands in the given document. - * - * Note: This method will call use() before executing the commands to - * ensure that the commands are run in the correct database. It's done for backwards - * compatibility with the previous behavior. - */ - public async executeAllCommands(context: IActionContext, document: vscode.TextDocument): Promise { - if (!this.isConnected()) { - throw new Error(l10n.t('Please connect to a MongoDB database before running a Scrapbook command.')); - } - - const commands: MongoCommand[] = getAllCommandsFromText(document.getText()); - if (!commands.length) { - void vscode.window.showInformationMessage(l10n.t('No commands found in this document.')); - return; - } - - this.setExecutingAllCommandsFlag(true); - try { - const label = 'Scrapbook-run-all-results'; - const fullId = `${this.getDisplayName()}/${label}`; - - const readOnlyContent = await openReadOnlyContent({ label, fullId }, '', '.json', { - viewColumn: vscode.ViewColumn.Beside, - preserveFocus: true, - }); - - const shellRunner = await ShellScriptRunner.createShell(context, { - connectionString: CredentialCache.getConnectionStringWithPassword(this.getClusterId()!), - emulatorConfiguration: CredentialCache.getEmulatorConfiguration(this.getClusterId()!), - }); - - try { - // preselect the database for the user - // this is done for backwards compatibility with the previous behavior - await shellRunner.executeScript(`use(\`${ScrapbookService.getDatabaseName()}\`)`); - - for (const cmd of commands) { - await this.executeSingleCommand(context, cmd, readOnlyContent, shellRunner); - } - } finally { - shellRunner.dispose(); - } - } finally { - this.setExecutingAllCommandsFlag(false); - } - } - - /** - * Executes a single Mongo command defined at the specified position in the document. - * - * Note: This method will call use() before executing the command to - * ensure that the command are is in the correct database. It's done for backwards - * compatibility with the previous behavior. - */ - public async executeCommandAtPosition( - context: IActionContext, - document: vscode.TextDocument, - position: vscode.Position, - ): Promise { - if (!this.isConnected()) { - throw new Error(l10n.t('Please connect to a MongoDB database before running a Scrapbook command.')); - } - - const commands = getAllCommandsFromText(document.getText()); - const command = findCommandAtPosition(commands, position); - - const label = 'Scrapbook-run-command-results'; - const fullId = `${this.getDisplayName()}/${label}`; - const readOnlyContent = await openReadOnlyContent({ label, fullId }, '', '.json', { - viewColumn: vscode.ViewColumn.Beside, - preserveFocus: true, - }); - - await this.executeSingleCommand(context, command, readOnlyContent, undefined, this.getDatabaseName()); - } - - /** - * Indicates whether multiple commands are being executed at once. - */ - public isExecutingAllCommands(): boolean { - return this._isExecutingAllCommands; - } - - /** - * Records the state for whether all commands are executing. - */ - public setExecutingAllCommandsFlag(state: boolean): void { - this._isExecutingAllCommands = state; - this._mongoCodeLensProvider.updateCodeLens(); - } - - /** - * Returns the command currently in execution, if any. - */ - public getSingleCommandInExecution(): MongoCommand | undefined { - return this._singleCommandInExecution; - } - - /** - * Sets or clears the command currently being executed. - */ - public setSingleCommandInExecution(command: MongoCommand | undefined): void { - this._singleCommandInExecution = command; - this._mongoCodeLensProvider.updateCodeLens(); - } - - //-------------------------------------------------------------------------------- - // Internal Helpers - //-------------------------------------------------------------------------------- - - /** - * Runs a single command against the Mongo shell. If a shell instance is not provided, - * this method creates its own, executes the command, then disposes the shell. This - * includes error handling for parse problems, ephemeral shell usage, and optional - * output to a read-only content view. - */ - private async executeSingleCommand( - context: IActionContext, - command: MongoCommand, - readOnlyContent?: { append(value: string): Promise }, - shellRunner?: ShellScriptRunner, - preselectedDatabase?: string, // this will run the 'use ' command before the actual command. - ): Promise { - if (!this.isConnected()) { - throw new Error(l10n.t('Not connected to any MongoDB database.')); - } - - if (command.errors?.length) { - const firstErr = command.errors[0]; - throw new Error( - l10n.t('Unable to parse syntax near line {line}, col {column}: {message}', { - line: firstErr.range.start.line + 1, - column: firstErr.range.start.character + 1, - message: firstErr.message, - }), - ); - } - - this.setSingleCommandInExecution(command); - let ephemeralShell = false; - - try { - if (!shellRunner) { - shellRunner = await ShellScriptRunner.createShell(context, { - connectionString: CredentialCache.getConnectionStringWithPassword(this.getClusterId()!), - emulatorConfiguration: CredentialCache.getEmulatorConfiguration( - this.getClusterId()!, - ) as EmulatorConfiguration, - }); - ephemeralShell = true; - } - - if (preselectedDatabase) { - await shellRunner.executeScript(`use(\`${preselectedDatabase}\`)`); - } - - const result = await shellRunner.executeScript(command.text); - if (!result) { - throw new Error(l10n.t('No result returned from the MongoDB shell.')); - } - - if (readOnlyContent) { - await readOnlyContent.append(result + EOL + EOL); - } else { - const fallbackLabel = 'Scrapbook-results'; - const fallbackId = `${this.getDatabaseName()}/${fallbackLabel}`; - await openReadOnlyContent({ label: fallbackLabel, fullId: fallbackId }, result, '.json', { - viewColumn: vscode.ViewColumn.Beside, - preserveFocus: true, - }); - } - } finally { - this.setSingleCommandInExecution(undefined); - - if (ephemeralShell) { - shellRunner?.dispose(); - } - } - } -} - -// Export a single instance that the rest of your extension can import -export const ScrapbookService = new ScrapbookServiceImpl(); diff --git a/src/documentdb/scrapbook/ShellScriptRunner.ts b/src/documentdb/scrapbook/ShellScriptRunner.ts deleted file mode 100644 index 61972a432..000000000 --- a/src/documentdb/scrapbook/ShellScriptRunner.ts +++ /dev/null @@ -1,486 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { parseError, UserCancelledError, type IActionContext } from '@microsoft/vscode-azext-utils'; -import * as l10n from '@vscode/l10n'; -import * as fs from 'node:fs/promises'; -import * as os from 'os'; -import * as path from 'path'; -import * as vscode from 'vscode'; -import { ext } from '../../extensionVariables'; -import * as cpUtils from '../../utils/cp'; -import { type EmulatorConfiguration } from '../../utils/emulatorConfiguration'; -import { pathExists } from '../../utils/fs/pathExists'; -import { InteractiveChildProcess } from '../../utils/InteractiveChildProcess'; -import { nonNullValue } from '../../utils/nonNull'; -import { randomUtils } from '../../utils/randomUtils'; -import { getBatchSizeSetting } from '../../utils/workspacUtils'; -import { wrapError } from '../../utils/wrapError'; - -const mongoExecutableFileName = process.platform === 'win32' ? 'mongo.exe' : 'mongosh'; - -const timeoutMessage = l10n.t( - "Timed out trying to execute the Mongo script. To use a longer timeout, modify the VS Code 'mongo.shell.timeout' setting.", -); - -const mongoShellMoreMessage = l10n.t('Type "it" for more'); -const extensionMoreMessage = '(More)'; - -const sentinelBase = 'EXECUTION COMPLETED'; -const sentinelRegex = /"?EXECUTION COMPLETED [0-9a-fA-F]{10}"?/; -function createSentinel(): string { - return `${sentinelBase} ${randomUtils.getRandomHexString(10)}`; -} - -export class ShellScriptRunner extends vscode.Disposable { - private static _previousShellPathSetting: string | undefined; - private static _cachedShellPathOrCmd: string | undefined; - - private constructor( - private _process: InteractiveChildProcess, - private _timeoutSeconds: number, - ) { - super(() => this.dispose()); - } - - public static async createShellProcessHelper( - execPath: string, - execArgs: string[], - connectionString: string, - outputChannel: vscode.OutputChannel, - timeoutSeconds: number, - emulatorConfiguration?: EmulatorConfiguration, - ): Promise { - try { - const args: string[] = execArgs.slice() || []; // Snapshot since we modify it - args.push(connectionString); - - if ( - emulatorConfiguration && - emulatorConfiguration.isEmulator && - emulatorConfiguration.disableEmulatorSecurity - ) { - // Without these the connection will fail due to the self-signed Document DB certificate - if (args.indexOf('--tlsAllowInvalidCertificates') < 0) { - args.push('--tlsAllowInvalidCertificates'); - } - } - - const process: InteractiveChildProcess = await InteractiveChildProcess.create({ - outputChannel: outputChannel, - command: execPath, - args, - outputFilterSearch: sentinelRegex, - outputFilterReplace: '', - }); - const shell: ShellScriptRunner = new ShellScriptRunner(process, timeoutSeconds); - - /** - * The 'unwrapIfCursor' helper is used to safely handle MongoDB queries in the shell, - * especially for commands like db.movies.find() that return a cursor. - * - * When a user runs a command returning a cursor, it points to a query's result set - * and exposes methods such as hasNext and next. Attempting to stringify - * the raw cursor directly with EJSON.stringify can fail due to circular references - * and other internal structures. - * - * To avoid this issue, 'unwrapIfCursor' checks if the returned object is indeed a - * cursor. If it is, we manually iterate up to a fixed limit of documents, and - * return those as a plain array. This prevents the shell from crashing or throwing - * errors about circular structures, while still returning actual document data in - * JSON format. - * - * For non-cursor commands (like db.hostInfo() or db.movies.findOne()), we - * simply return the object unchanged. - */ - const unwrapIfCursorFunction = - 'function unwrapIfCursor(value) {\n' + - " if (value && typeof value.hasNext === 'function' && typeof value.next === 'function') {\n" + - ' const docs = [];\n' + - ' const MAX_DOCS = 50;\n' + - ' let count = 0;\n' + - ' while (value.hasNext() && count < MAX_DOCS) {\n' + - ' docs.push(value.next());\n' + - ' count++;\n' + - ' }\n' + - ' if (value.hasNext()) {\n' + - ' docs.push({ cursor: "omitted", note: "Additional results are not displayed." });\n' + - ' }\n' + - ' return docs;\n' + - ' }\n' + - ' return value;\n' + - '}'; - process.writeLine(`${convertToSingleLine(unwrapIfCursorFunction)}`); - - // Try writing an empty script to verify the process is running correctly and allow us - // to catch any errors related to the start-up of the process before trying to write to it. - await shell.executeScript(''); - - ext.outputChannel.appendLine(l10n.t('Mongo Shell connected.')); - - // Configure the batch size - await shell.executeScript(`config.set("displayBatchSize", ${getBatchSizeSetting()})`); - - return shell; - } catch (error) { - throw wrapCheckOutputWindow(error); - } - } - - public static async createShell( - context: IActionContext, - connectionInfo: { connectionString: string; emulatorConfiguration?: EmulatorConfiguration }, - ): Promise { - const config = vscode.workspace.getConfiguration(); - let shellPath: string | undefined = config.get(ext.settingsKeys.shellPath); - const shellArgs: string[] = config.get(ext.settingsKeys.shellArgs, []); - - if ( - !shellPath || - !ShellScriptRunner._cachedShellPathOrCmd || - ShellScriptRunner._previousShellPathSetting !== shellPath - ) { - // Only do this if setting changed since last time - shellPath = await ShellScriptRunner._determineShellPathOrCmd(context, shellPath); - ShellScriptRunner._previousShellPathSetting = shellPath; - } - ShellScriptRunner._cachedShellPathOrCmd = shellPath; - - const timeout = - 1000 * - nonNullValue( - config.get(ext.settingsKeys.shellTimeout), - 'config.get(ext.settingsKeys.shellTimeout)', - 'ShellScriptRunner.ts', - ); - return ShellScriptRunner.createShellProcessHelper( - shellPath, - shellArgs, - connectionInfo.connectionString, - ext.outputChannel, - timeout, - connectionInfo.emulatorConfiguration, - ); - } - - public dispose(): void { - this._process.kill(); - } - - public async useDatabase(database: string): Promise { - return await this.executeScript(`use ${database}`); - } - - public async executeScript(script: string): Promise { - // 1. Convert to single line (existing logic) - script = convertToSingleLine(script); - - // 2. If the user typed something, wrap it in EJSON.stringify(...) - // This assumes the user has typed exactly one expression that - // returns something (e.g. db.hostInfo(), db.myCollection.find(), etc.) - if (script.trim().length > 0 && !script.startsWith('print(EJSON.stringify(')) { - // Remove trailing semicolons plus any trailing space - // e.g. "db.hostInfo(); " => "db.hostInfo()" - script = script.replace(/;+\s*$/, ''); - - // Wrap in EJSON.stringify() and unwrapIfCursor - script = `print(EJSON.stringify(unwrapIfCursor(${script}), null, 4))`; - } - - let stdOut = ''; - const sentinel = createSentinel(); - - const disposables: vscode.Disposable[] = []; - try { - // eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor - const result = await new Promise(async (resolve, reject) => { - try { - startScriptTimeout(this._timeoutSeconds, reject); - - // Hook up events - disposables.push( - this._process.onStdOut((text) => { - stdOut += text; - // eslint-disable-next-line prefer-const - let { text: stdOutNoSentinel, removed } = removeSentinel(stdOut, sentinel); - if (removed) { - // The sentinel was found, which means we are done. - - // Change the "type 'it' for more" message to one that doesn't ask users to type anything, - // since we're not currently interactive like that. - // CONSIDER: Ideally we would allow users to click a button to iterate through more data, - // or even just do it for them - stdOutNoSentinel = stdOutNoSentinel.replace( - mongoShellMoreMessage, - extensionMoreMessage, - ); - - const responseText = removePromptLeadingAndTrailing(stdOutNoSentinel); - - resolve(responseText); - } - }), - ); - disposables.push( - this._process.onStdErr((text) => { - // Mongo shell only writes to STDERR for errors relating to starting up. Script errors go to STDOUT. - // So consider this an error. - // (It's okay if we fire this multiple times, the first one wins.) - - // Split the stderr text into lines, trim them, and remove empty lines - const lines: string[] = text - .split(/\r?\n/) - .map((l) => l.trim()) - .filter(Boolean); - - // Filter out lines recognized as benign debug/telemetry info - const unknownErrorLines: string[] = lines.filter( - (line) => !this.isNonErrorMongoshStderrLine(line), - ); - - // If there are any lines left after filtering, assume they are real errors - if (unknownErrorLines.length > 0) { - for (const line of unknownErrorLines) { - ext.outputChannel.appendLine(l10n.t('Mongo Shell Error: {error}', line)); - } - // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors - reject(wrapCheckOutputWindow(unknownErrorLines.join('\n'))); - } else { - // Otherwise, ignore the lines since they're known safe - // (e.g. "Debugger listening on ws://..." or "Using Mongosh: 1.9.0", etc.) - } - }), - ); - disposables.push( - this._process.onError((error) => { - // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors - reject(error); - }), - ); - - // Write the script to STDIN - if (script) { - this._process.writeLine(script); - } - - // Mark end of result by sending the sentinel wrapped in quotes so the console will spit - // it back out as a string value after it's done processing the script - const quotedSentinel = `"${sentinel}"`; - this._process.writeLine(quotedSentinel); // (Don't display the sentinel) - } catch (error) { - // new Promise() doesn't seem to catch exceptions in an async function, we need to explicitly reject it - - if ((<{ code?: string }>error).code === 'EPIPE') { - // Give a chance for start-up errors to show up before rejecting with this more general error message - await delay(500); - // eslint-disable-next-line no-ex-assign - error = new Error(l10n.t('The process exited prematurely.')); - } - - // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors - reject(wrapCheckOutputWindow(error)); - } - }); - - return result.trim(); - } finally { - // Dispose event handlers - for (const d of disposables) { - d.dispose(); - } - } - } - - /** - * Checks if the stderr line from mongosh is a known "benign" message that - * should NOT be treated as an error. - */ - private isNonErrorMongoshStderrLine(line: string): boolean { - /** - * Certain versions of mongosh can print debug or telemetry messages to stderr - * that are not actually errors (especially if VS Code auto-attach is running). - * Below is a list of known message fragments that we can safely ignore. - * - * IMPORTANT: This list is not exhaustive and may need to be updated as new - * versions of mongosh introduce new messages. - */ - const knownNonErrorSubstrings: string[] = [ - // Node.js Inspector (auto-attach) messages: - 'Debugger listening on ws://', - 'Debugger attached.', - 'For help, see: https://nodejs.org/en/docs/inspector', - - // MongoDB Shell general info messages: - 'Current Mongosh Log ID:', - 'Using Mongosh:', - 'Using MongoDB:', - - // Telemetry or analytics prompts: - 'To enable telemetry, run:', - 'Disable telemetry by running:', - - // Occasionally, devtools or local shell info: - 'DevTools listening on ws://', - 'The server generated these startup warnings:', - ]; - - return knownNonErrorSubstrings.some((pattern) => line.includes(pattern)); - } - - private static async _determineShellPathOrCmd( - context: IActionContext, - shellPathSetting: string | undefined, - ): Promise { - if (!shellPathSetting) { - // User hasn't specified the path - if (await cpUtils.commandSucceeds('mongosh', '--version')) { - // If the user already has mongo in their system path, just use that - return 'mongosh'; - } else { - // If all else fails, prompt the user for the mongo path - const openFile: vscode.MessageItem = { - title: l10n.t('Browse to {mongoExecutableFileName}', { mongoExecutableFileName }), - }; - const browse: vscode.MessageItem = { title: l10n.t('Open installation page') }; - const noMongoError: string = l10n.t( - 'This functionality requires the Mongo DB shell, but we could not find it in the path or using the documentDB.mongoShell.path setting.', - ); - const response = await context.ui.showWarningMessage( - noMongoError, - { stepName: 'promptForMongoPath' }, - browse, - openFile, - ); - if (response === openFile) { - while (true) { - const newPath: vscode.Uri[] = await context.ui.showOpenDialog({ - filters: { 'Executable Files': [process.platform === 'win32' ? 'exe' : ''] }, - openLabel: l10n.t('Select {mongoExecutableFileName}', { mongoExecutableFileName }), - stepName: 'openMongoExeFile', - }); - const fsPath = newPath[0].fsPath; - const baseName = path.basename(fsPath); - if (baseName !== mongoExecutableFileName) { - const useAnyway: vscode.MessageItem = { title: l10n.t('Use anyway') }; - const tryAgain: vscode.MessageItem = { title: l10n.t('Try again') }; - const response2 = await context.ui.showWarningMessage( - l10n.t( - 'Expected a file name "{0}", but the selected filename is "{1}"', - mongoExecutableFileName, - baseName, - ), - { stepName: 'confirmMongoExeFile' }, - useAnyway, - tryAgain, - ); - if (response2 === tryAgain) { - continue; - } - } - - await vscode.workspace - .getConfiguration() - .update(ext.settingsKeys.shellPath, fsPath, vscode.ConfigurationTarget.Global); - return fsPath; - } - } else if (response === browse) { - void vscode.commands.executeCommand( - 'vscode.open', - vscode.Uri.parse('https://docs.mongodb.com/manual/installation/'), - ); - // default down to cancel error because MongoShell.create errors out if undefined is passed as the shellPath - } - - throw new UserCancelledError('createShell'); - } - } else { - // User has specified the path or command. Sometimes they set the folder instead of a path to the file, let's check that and auto fix - if (await pathExists(shellPathSetting)) { - const stat = await fs.stat(shellPathSetting); - if (stat.isDirectory()) { - return path.join(shellPathSetting, mongoExecutableFileName); - } - } - - return shellPathSetting; - } - } -} - -function startScriptTimeout(timeoutSeconds: number, reject: (err: unknown) => void): void { - if (timeoutSeconds > 0) { - setTimeout(() => { - reject(timeoutMessage); - }, timeoutSeconds * 1000); - } -} - -function convertToSingleLine(script: string): string { - return script - .split(os.EOL) - .map((line) => line.trim()) - .join(''); -} - -function removeSentinel(text: string, sentinel: string): { text: string; removed: boolean } { - const index = text.indexOf(sentinel); - if (index >= 0) { - return { text: text.slice(0, index), removed: true }; - } else { - return { text, removed: false }; - } -} - -/** - * Removes a Mongo shell prompt line if it exists at the very start or the very end of `text`. - */ -function removePromptLeadingAndTrailing(text: string): string { - // Trim trailing spaces/newlines, but keep internal newlines. - text = text.replace(/\s+$/, ''); - - // Regex to detect standard MongoDB shell prompts: - // 1) [mongos] secondDb> - // 2) [mongo] test> - // 3) globaldb [primary] SampleDB> - const promptRegex = /^(\[mongo.*?\].*?>|.*?\[.*?\]\s+\S+>)$/; - - // Check if the *first line* contains a prompt - const firstNewlineIndex = text.indexOf('\n'); - if (firstNewlineIndex === -1) { - return text.replace(promptRegex, '').trim(); - } - - // Extract the first line - const firstLine = text.substring(0, firstNewlineIndex).trim(); - if (promptRegex.test(firstLine)) { - // Remove the prompt from the first line - text = text.replace(firstLine, firstLine.replace(promptRegex, '').trim()); - } - - // Check if the *last line* contains a prompt - const lastNewlineIndex = text.lastIndexOf('\n'); - if (lastNewlineIndex === -1) { - return text.replace(promptRegex, '').trim(); - } - - const lastLine = text.substring(lastNewlineIndex + 1).trim(); - if (promptRegex.test(lastLine)) { - // Remove the prompt from the last line - text = text.replace(lastLine, lastLine.replace(promptRegex, '').trim()); - } - - return text; -} - -async function delay(milliseconds: number): Promise { - return new Promise((resolve) => { - setTimeout(resolve, milliseconds); - }); -} - -function wrapCheckOutputWindow(error: unknown): unknown { - const checkOutputMsg = l10n.t('The output window may contain additional information.'); - return parseError(error).message.includes(checkOutputMsg) ? error : wrapError(error, checkOutputMsg); -} diff --git a/src/documentdb/scrapbook/connectToClient.ts b/src/documentdb/scrapbook/connectToClient.ts deleted file mode 100644 index 25fe24c4b..000000000 --- a/src/documentdb/scrapbook/connectToClient.ts +++ /dev/null @@ -1,61 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as l10n from '@vscode/l10n'; -import { MongoClient, type MongoClientOptions } from 'mongodb'; -import { Links, wellKnownEmulatorPassword } from '../../constants'; -import { type EmulatorConfiguration } from '../../utils/emulatorConfiguration'; - -export async function connectToClient( - connectionString: string, - appName: string, - emulatorConfiguration?: EmulatorConfiguration, -): Promise { - // appname appears to be the correct equivalent to user-agent for mongo - const options: MongoClientOptions = { - // appName should be wrapped in '@'s when trying to connect to a Mongo account, this doesn't effect the appendUserAgent string - appName: `${appName}[RU]`, - // https://github.com/lmammino/mongo-uri-builder/issues/2 - useNewUrlParser: true, - useUnifiedTopology: true, - }; - - if (emulatorConfiguration && emulatorConfiguration.isEmulator && emulatorConfiguration.disableEmulatorSecurity) { - // Prevents self signed certificate error for emulator https://github.com/microsoft/vscode-cosmosdb/issues/1241#issuecomment-614446198 - options.tlsAllowInvalidCertificates = true; - } - - try { - return await MongoClient.connect(connectionString, options); - } catch (err) { - // Note: This file can't use `parseError` from `@microsoft/vscode-azext-utils` because it's used by languageService.ts - see that file for more info - const error = <{ message?: string; name?: string }>err; - const message = error && error.message; - - // Example error: "failed to connect to server [localhost:10255] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:10255]" - // Example error: "failed to connect to server [127.0.0.1:27017] on first connect [MongoError: connect ECONNREFUSED 127.0.0.1:27017]" - if (message && /ECONNREFUSED/.test(message) && /(localhost|127\.0\.0\.1)/.test(message)) { - throw new MongoConnectError(); - } - - // eslint-disable-next-line @typescript-eslint/only-throw-error - throw error; - } -} - -export class MongoConnectError extends Error { - constructor() { - super( - l10n.t( - 'Unable to connect to the local database instance. Make sure it is started correctly. See {link} for tips.', - { link: Links.LocalConnectionDebuggingTips }, - ), - ); - } -} - -export function isCosmosEmulatorConnectionString(connectionString: string): boolean { - return connectionString.includes(encodeURIComponent(wellKnownEmulatorPassword)); -} diff --git a/src/documentdb/scrapbook/errorListeners.ts b/src/documentdb/scrapbook/errorListeners.ts deleted file mode 100644 index ea4c11ff6..000000000 --- a/src/documentdb/scrapbook/errorListeners.ts +++ /dev/null @@ -1,67 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { type ANTLRErrorListener } from 'antlr4ts/ANTLRErrorListener'; -import { type RecognitionException } from 'antlr4ts/RecognitionException'; -import { type Recognizer } from 'antlr4ts/Recognizer'; -import { type Token } from 'antlr4ts/Token'; -import * as vscode from 'vscode'; -import { type ErrorDescription } from './MongoCommand'; - -export class ParserErrorListener implements ANTLRErrorListener { - private _errors: ErrorDescription[] = []; - - public get errors(): ErrorDescription[] { - return this._errors; - } - - public syntaxError( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - _recognizer: Recognizer, - _offendingSymbol: Token | undefined, - line: number, - charPositionInLine: number, - msg: string, - e: RecognitionException | undefined, - ): void { - const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed - const range = new vscode.Range(position, position); - - const error: ErrorDescription = { - message: msg, - range: range, - exception: e, - }; - this._errors.push(error); - } -} - -export class LexerErrorListener implements ANTLRErrorListener { - private _errors: ErrorDescription[] = []; - - public get errors(): ErrorDescription[] { - return this._errors; - } - - public syntaxError( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - _recognizer: Recognizer, - _offendingSymbol: number | undefined, - line: number, - charPositionInLine: number, - msg: string, - e: RecognitionException | undefined, - ): void { - const position = new vscode.Position(line - 1, charPositionInLine); // Symbol lines are 1-indexed. Position lines are 0-indexed - const range = new vscode.Range(position, position); - - const error: ErrorDescription = { - message: msg, - range: range, - exception: e, - }; - this._errors.push(error); - } -} diff --git a/src/documentdb/scrapbook/languageClient.ts b/src/documentdb/scrapbook/languageClient.ts deleted file mode 100644 index 75b5afd4c..000000000 --- a/src/documentdb/scrapbook/languageClient.ts +++ /dev/null @@ -1,88 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -/* eslint-disable import/no-internal-modules */ - -import { appendExtensionUserAgent } from '@microsoft/vscode-azext-utils'; -import * as path from 'path'; -import { - LanguageClient, - TransportKind, - type LanguageClientOptions, - type ServerOptions, -} from 'vscode-languageclient/node'; -import { ext } from '../../extensionVariables'; -import { type EmulatorConfiguration } from '../../utils/emulatorConfiguration'; -import { type IConnectionParams } from './services/IConnectionParams'; - -export class MongoDBLanguageClient { - public client: LanguageClient; - - constructor() { - // The server is implemented in node - const serverPath = ext.isBundle - ? path.join('vscode-documentdb-scrapbook-language-languageServer.bundle.js') // Run with webpack - : path.join('out', 'src', 'documentdb', 'scrapbook', 'languageServer.js'); // Run without webpack - const serverModule = ext.context.asAbsolutePath(serverPath); - // The debug options for the server - const debugOptions = { execArgv: ['--nolazy', '--inspect=6005'] }; - - // If the extension is launch in debug mode the debug server options are use - // Otherwise the run options are used - const serverOptions: ServerOptions = { - run: { module: serverModule, transport: TransportKind.ipc }, - debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions }, - }; - - // Options to control the language client - const clientOptions: LanguageClientOptions = { - // Register the server for mongo javascript documents - documentSelector: [ - { language: 'vscode-documentdb-scrapbook-language', scheme: 'file' }, - { language: 'vscode-documentdb-scrapbook-language', scheme: 'untitled' }, - ], - }; - - // Create the language client. - this.client = new LanguageClient( - 'vscode-documentdb-scrapbook-language', - 'DocumentDB Language Server', - serverOptions, - clientOptions, - ); - - // Push the disposable to the context's subscriptions so that the - // client can be deactivated on extension deactivation - ext.context.subscriptions.push({ - dispose: async () => { - try { - await this.client?.stop(); - } catch (error) { - console.error('Failed to stop the language client:', error); - } - }, - }); - - // Start the client. This will also launch the server - void this.client.start(); - } - - public async connect( - connectionString: string, - databaseName: string, - emulatorConfiguration?: EmulatorConfiguration, - ): Promise { - await this.client.sendRequest('connect', { - connectionString: connectionString, - databaseName: databaseName, - extensionUserAgent: appendExtensionUserAgent(), - emulatorConfiguration: emulatorConfiguration, - }); - } - - public async disconnect(): Promise { - await this.client.sendRequest('disconnect'); - } -} diff --git a/src/documentdb/scrapbook/languageServer.ts b/src/documentdb/scrapbook/languageServer.ts deleted file mode 100644 index a94ef70a7..000000000 --- a/src/documentdb/scrapbook/languageServer.ts +++ /dev/null @@ -1,21 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { LanguageService } from './services/languageService'; - -// -// -// -// HOW TO DEBUG THE LANGUAGE SERVER -// -// -// 1. Start the extension via F5 -// 2. Under vscode Debug pane, switch to "Attach to Language Server" -// 3. F5 -// -// -// - -new LanguageService(); diff --git a/src/documentdb/scrapbook/mongoConnectionStrings.test.ts b/src/documentdb/scrapbook/mongoConnectionStrings.test.ts deleted file mode 100644 index 4fabc88ec..000000000 --- a/src/documentdb/scrapbook/mongoConnectionStrings.test.ts +++ /dev/null @@ -1,400 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { wellKnownEmulatorPassword } from '../../constants'; -import { isCosmosEmulatorConnectionString } from './connectToClient'; -import { - addDatabaseToAccountConnectionString, - encodeMongoConnectionString, - getDatabaseNameFromConnectionString, -} from './mongoConnectionStrings'; - -describe(`mongoCollectionStrings`, () => { - it(`getDatabaseNameFromConnectionString`, () => { - // Connection strings follow the following format (https://docs.mongodb.com/manual/reference/connection-string/): - // mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] - function testDatabaseNameFromConnectionString( - connectionString: string, - expectedDatabaseName: string | undefined, - ): void { - const databaseName = getDatabaseNameFromConnectionString(connectionString); - expect(databaseName).toEqual(expectedDatabaseName); - } - - // const databaseName = getDatabaseNameFromConnectionString(`mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`,); - // expect(databaseName).toEqual(undefined); - testDatabaseNameFromConnectionString( - `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, - undefined, - ); - testDatabaseNameFromConnectionString( - `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb`, - 'our-mongo', - ); - - testDatabaseNameFromConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, undefined); - testDatabaseNameFromConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118/`, undefined); - testDatabaseNameFromConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118/dbname`, `dbname`); - - testDatabaseNameFromConnectionString( - `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, - undefined, - ); - testDatabaseNameFromConnectionString( - `mongodb://db1.example.net:27017,db2.example.net:2500/my-database?replicaSet=test`, - 'my-database', - ); - - testDatabaseNameFromConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/`, undefined); - testDatabaseNameFromConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017`, undefined); - testDatabaseNameFromConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/db`, 'db'); - - testDatabaseNameFromConnectionString(`mongodb+srv://server.example.com/`, undefined); - testDatabaseNameFromConnectionString(`mongodb+srv://server.example.com/db`, 'db'); - - testDatabaseNameFromConnectionString( - `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, - undefined, - ); - testDatabaseNameFromConnectionString( - `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/MYDB?replicaSet=mySet&authSource=authDB`, - 'MYDB', - ); - - testDatabaseNameFromConnectionString( - `mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB`, - undefined, - ); - testDatabaseNameFromConnectionString( - `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/my_db?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB`, - 'my_db', - ); - testDatabaseNameFromConnectionString( - `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000`, - undefined, - ); - testDatabaseNameFromConnectionString( - `mongodb://host.example.com/hello?readPreference=secondary&maxStalenessSeconds=120`, - 'hello', - ); - testDatabaseNameFromConnectionString(`mongodb://localhost`, undefined); - testDatabaseNameFromConnectionString(`mongodb://localhost/db`, 'db'); - testDatabaseNameFromConnectionString(`mongodb://sysop:moon@localhost/records`, 'records'); - testDatabaseNameFromConnectionString(`mongodb://%2Ftmp%2Fmongodb-27017.sock/db`, 'db'); - testDatabaseNameFromConnectionString( - `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/abc`, - 'abc', - ); - - // special characters - testDatabaseNameFromConnectionString( - `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/def-ghi_jkl`, - 'def-ghi_jkl', - ); - testDatabaseNameFromConnectionString( - `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/Icantlikespaces`, - 'Icantlikespaces', - ); - - // emulator: mongodb://localhost:C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==@localhost:10255?ssl=true - testDatabaseNameFromConnectionString( - `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/admin?ssl=true`, - 'admin', - ); - testDatabaseNameFromConnectionString( - `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/admin-master?ssl=true`, - 'admin-master', - ); - // test characters mentioned in : https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Database-Names-for-Windows - testDatabaseNameFromConnectionString( - `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/admin!@%^()-_,[]?ssl=true`, - 'admin!@%^()-_,[]', - ); - }); - - it('addDatabaseToAccountConnectionString', () => { - function testDatabaseToAccountConnectionString( - connectionString: string, - databaseName: string, - expectedConnectionString: string | undefined, - ): void { - const databaseConnectionString = addDatabaseToAccountConnectionString(connectionString, databaseName); - expect(databaseConnectionString).toEqual(expectedConnectionString); - } - - testDatabaseToAccountConnectionString( - `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, - 'somedatabase', - 'mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/somedatabase?ssl=true&replicaSet=globaldb', - ); - testDatabaseToAccountConnectionString( - `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb`, - 'our-mongo', - 'mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb', - ); - - testDatabaseToAccountConnectionString( - `mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, - 'mydata', - 'mongodb://dbuser:dbpassword@dbname.mlab.com:14118/mydata', - ); - testDatabaseToAccountConnectionString( - `mongodb://dbuser:dbpassword@dbname.mlab.com:14118/`, - 'database', - 'mongodb://dbuser:dbpassword@dbname.mlab.com:14118/database', - ); - testDatabaseToAccountConnectionString( - `mongodb+srv://dbuser:dbpassword@dbname.mlab.com:14118/database`, - 'database', - 'mongodb+srv://dbuser:dbpassword@dbname.mlab.com:14118/database', - ); - - testDatabaseToAccountConnectionString( - `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, - 'my-database', - 'mongodb://db1.example.net:27017,db2.example.net:2500/my-database?replicaSet=test', - ); - testDatabaseToAccountConnectionString( - `mongodb://db1.example.net:27017,db2.example.net:2500/my-database?`, - 'my-database', - 'mongodb://db1.example.net:27017,db2.example.net:2500/my-database?', - ); - - testDatabaseToAccountConnectionString( - `mongodb://r1.example.net:27017,r2.example.net:27017/`, - 'undefined', - 'mongodb://r1.example.net:27017,r2.example.net:27017/undefined', - ); - testDatabaseToAccountConnectionString( - `mongodb://r1.example.net:27017,r2.example.net:27017`, - 'undefined', - 'mongodb://r1.example.net:27017,r2.example.net:27017/undefined', - ); - testDatabaseToAccountConnectionString( - `mongodb://r1.example.net:27017,r2.example.net:27017/{SQL}data`, - '(NoSQL)data', - 'mongodb://r1.example.net:27017,r2.example.net:27017/(NoSQL)data', - ); - - testDatabaseToAccountConnectionString( - `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, - 'undefined', - 'mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/undefined?replicaSet=mySet&authSource=authDB', - ); - testDatabaseToAccountConnectionString( - `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, - 'MYDB', - 'mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/MYDB?replicaSet=mySet&authSource=authDB', - ); - - testDatabaseToAccountConnectionString( - `mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB?`, - 'basetoadd', - 'mongodb+srv://server.example.com/basetoadd?connectTimeoutMS=300000&authSource=aDifferentAuthDB?', - ); - - testDatabaseToAccountConnectionString( - `mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB`, - '', - 'mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB', - ); - testDatabaseToAccountConnectionString( - `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/my_db?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB`, - 'not_mydatabase', - 'mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/not_mydatabase?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB', - ); - testDatabaseToAccountConnectionString( - `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000`, - '', - 'mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000', - ); - testDatabaseToAccountConnectionString( - `mongodb://host.example.com/hello?readPreference=secondary&maxStalenessSeconds=120`, - 'hellno', - 'mongodb://host.example.com/hellno?readPreference=secondary&maxStalenessSeconds=120', - ); - testDatabaseToAccountConnectionString(`mongodb://localhost`, '', 'mongodb://localhost/'); - testDatabaseToAccountConnectionString( - `mongodb://localhost/db`, - 'new{}db', - `mongodb://localhost/${encodeURIComponent('new{}db')}`, - ); - testDatabaseToAccountConnectionString( - `mongodb://sysop:moon@localhost/records`, - 'records', - 'mongodb://sysop:moon@localhost/records', - ); - testDatabaseToAccountConnectionString( - `mongodb://%2Ftmp%2Fmongodb-27017.sock/onemorefundatabase`, - 'notfun', - 'mongodb://%2Ftmp%2Fmongodb-27017.sock/notfun', - ); - testDatabaseToAccountConnectionString( - `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/wowsomethingnew?ssl=true`, - 'notsure', - 'mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/notsure?ssl=true', - ); - - // special characters - testDatabaseToAccountConnectionString( - `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/?`, - 'def-ghi_jkl', - 'mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/def-ghi_jkl?', - ); - testDatabaseToAccountConnectionString( - `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017`, - 'icantlikespaces', - 'mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/icantlikespaces', - ); - - // Emulator - testDatabaseToAccountConnectionString( - `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/?ssl=true`, - 'admin', - `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/admin?ssl=true`, - ); - // Collection within emulator - testDatabaseToAccountConnectionString( - `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/?ssl=true`, - 'admin-master', - `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/admin-master?ssl=true`, - ); - testDatabaseToAccountConnectionString( - `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/?ssl=true`, - 'admin!@%^()-_,[]', - `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/${encodeURIComponent('admin!@%^()-_,[]')}?ssl=true`, - ); - }); - - it('isCosmosEmulatorConnectionString', () => { - function testIsCosmosEmulatorConnectionString(connectionString: string, expected: boolean): void { - const actual: boolean = isCosmosEmulatorConnectionString(connectionString); - expect(actual).toEqual(expected); - } - - testIsCosmosEmulatorConnectionString( - `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, - false, - ); - testIsCosmosEmulatorConnectionString( - `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/our-mongo?ssl=true&replicaSet=globaldb`, - false, - ); - - testIsCosmosEmulatorConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, false); - testIsCosmosEmulatorConnectionString(`mongodb://dbuser:dbpassword@dbname.mlab.com:14118/`, false); - testIsCosmosEmulatorConnectionString(`mongodb+srv://dbuser:dbpassword@dbname.mlab.com:14118/database`, false); - - testIsCosmosEmulatorConnectionString( - `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, - false, - ); - testIsCosmosEmulatorConnectionString( - `mongodb://db1.example.net:27017,db2.example.net:2500/my-database?`, - false, - ); - - testIsCosmosEmulatorConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/`, false); - testIsCosmosEmulatorConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017`, false); - testIsCosmosEmulatorConnectionString(`mongodb://r1.example.net:27017,r2.example.net:27017/{SQL}data`, false); - - testIsCosmosEmulatorConnectionString( - `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, - false, - ); - testIsCosmosEmulatorConnectionString( - `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/?replicaSet=mySet&authSource=authDB`, - false, - ); - - testIsCosmosEmulatorConnectionString( - `mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB`, - false, - ); - testIsCosmosEmulatorConnectionString( - `mongodb://mongodb1.example.com:27317,mongodb2.example.com:27017/my_db?connectTimeoutMS=300000&replicaSet=mySet&authSource=aDifferentAuthDB`, - false, - ); - testIsCosmosEmulatorConnectionString( - `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test&connectTimeoutMS=300000`, - false, - ); - testIsCosmosEmulatorConnectionString( - `mongodb://host.example.com/hello?readPreference=secondary&maxStalenessSeconds=120`, - false, - ); - testIsCosmosEmulatorConnectionString(`mongodb://localhost`, false); - testIsCosmosEmulatorConnectionString(`mongodb://localhost/db`, false); - testIsCosmosEmulatorConnectionString(`mongodb://sysop:moon@localhost/records`, false); - testIsCosmosEmulatorConnectionString(`mongodb://%2Ftmp%2Fmongodb-27017.sock/onemorefundatabase`, false); - testIsCosmosEmulatorConnectionString( - `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/wowsomethingnew?ssl=true`, - false, - ); - - testIsCosmosEmulatorConnectionString( - `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/abc...`, - false, - ); - testIsCosmosEmulatorConnectionString( - `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/?`, - false, - ); - testIsCosmosEmulatorConnectionString( - `mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017`, - false, - ); - - // Emulator - testIsCosmosEmulatorConnectionString( - `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/?ssl=true`, - true, - ); - testIsCosmosEmulatorConnectionString( - `mongodb://127.0.0.1:${encodeURIComponent(wellKnownEmulatorPassword)}@127.0.0.1:10255/?ssl=true`, - true, - ); - testIsCosmosEmulatorConnectionString( - `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/database?ssl=true`, - true, - ); - }); - - it('encodeMongoConnectionString', () => { - function testEncodeMongoConnectionString(connectionString: string, expectedConnectionString: string): void { - connectionString = encodeMongoConnectionString(connectionString); - expect(connectionString).toEqual(expectedConnectionString); - } - testEncodeMongoConnectionString( - `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg==@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, - `mongodb://my-mongo:ayO83FFfUoHE97Jm7WbfnpNCqiF0Yq0za2YmvuLAKYJKf7h7hQaRKWfZfsv8Ux41H66Gls7lVPEKlKm0ueSozg%3D%3D@your-mongo.documents.azure.com:10255/?ssl=true&replicaSet=globaldb`, - ); - testEncodeMongoConnectionString( - `mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, - `mongodb://dbuser:dbpassword@dbname.mlab.com:14118`, - ); - testEncodeMongoConnectionString( - `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, - `mongodb://db1.example.net:27017,db2.example.net:2500/?replicaSet=test`, - ); - testEncodeMongoConnectionString( - `mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB?`, - `mongodb+srv://server.example.com/?connectTimeoutMS=300000&authSource=aDifferentAuthDB?`, - ); - testEncodeMongoConnectionString(`mongodb://localhost`, `mongodb://localhost`); - testEncodeMongoConnectionString( - `mongodb://localhost:${encodeURIComponent(wellKnownEmulatorPassword)}@localhost:10255/?ssl=true`, - `mongodb://localhost:${encodeURIComponent(encodeURIComponent(wellKnownEmulatorPassword))}@localhost:10255/?ssl=true`, - ); - testEncodeMongoConnectionString( - `mongodb://username@example.com:password@localhost/`, - `mongodb://username%40example.com:password@localhost/`, - ); - testEncodeMongoConnectionString( - `mongodb://crazy@:/%username:even@crazier%/password@localhost/`, - `mongodb://crazy%40%3A%2F%25username:even%40crazier%25%2Fpassword@localhost/`, - ); - }); -}); diff --git a/src/documentdb/scrapbook/mongoConnectionStrings.ts b/src/documentdb/scrapbook/mongoConnectionStrings.ts deleted file mode 100644 index 26166f8e0..000000000 --- a/src/documentdb/scrapbook/mongoConnectionStrings.ts +++ /dev/null @@ -1,101 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { appendExtensionUserAgent, parseError, type IParsedError } from '@microsoft/vscode-azext-utils'; -import { type MongoClient } from 'mongodb'; -import { ParsedConnectionString } from '../../ParsedConnectionString'; -import { nonNullValue } from '../../utils/nonNull'; -import { connectToClient } from './connectToClient'; - -// Connection strings follow the following format (https://docs.mongodb.com/manual/reference/connection-string/): -// mongodb[+srv]://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]] -// Some example connection strings: -// mongodb://dbuser:dbpassword@dbname.mlab.com:14118 -// mongodb+srv://db1.example.net:27017,db2.example.net:2500/?replicaSet=test -// mongodb://router1.example.com:27017,router2.example2.com:27017,router3.example3.com:27017/database?ssh=true -// Regex splits into three parts: -// Full match -// mongodb[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]] -// [database] - -const parsePrefix = '([a-zA-Z]+://[^/]*)'; -const parseDatabaseName = '/?([^/?]+)?'; -const mongoConnectionStringRegExp = new RegExp(parsePrefix + parseDatabaseName); - -export function getDatabaseNameFromConnectionString(connectionString: string): string | undefined { - try { - const [, , databaseName] = nonNullValue( - connectionString.match(mongoConnectionStringRegExp), - 'connectionString.match(mongoConnectionStringRegExp)', - 'mongoConnectionStrings.ts', - ); - return databaseName; - } catch { - // Shouldn't happen, but ignore if does - } - - return undefined; -} - -export function addDatabaseToAccountConnectionString(connectionString: string, databaseName: string): string { - try { - return connectionString.replace(mongoConnectionStringRegExp, `$1/${encodeURIComponent(databaseName)}`); - } catch { - // Shouldn't happen, but ignore if does. Original connection string could be in a format we don't expect, but might already have the db name or might still work without it - return connectionString; - } -} - -export async function parseMongoConnectionString(connectionString: string): Promise { - let mongoClient: MongoClient; - try { - mongoClient = await connectToClient(connectionString, appendExtensionUserAgent()); - } catch (error) { - const parsedError: IParsedError = parseError(error); - if (parsedError.message.match(/unescaped/i)) { - // Prevents https://github.com/microsoft/vscode-cosmosdb/issues/1209 - connectionString = encodeMongoConnectionString(connectionString); - mongoClient = await connectToClient(connectionString, appendExtensionUserAgent()); - } else { - throw error; - } - } - - const { host, port } = mongoClient.options.hosts[0]; - - return new ParsedMongoConnectionString( - connectionString, - host as string, - (port as number).toString(), - getDatabaseNameFromConnectionString(connectionString), - ); -} - -export class ParsedMongoConnectionString extends ParsedConnectionString { - public readonly hostName: string; - public readonly port: string; - - constructor(connectionString: string, hostName: string, port: string, databaseName: string | undefined) { - super(connectionString, databaseName); - this.hostName = hostName; - this.port = port; - } -} - -/** - * Encodes the username and password in the given Mongo DB connection string. - */ -export function encodeMongoConnectionString(connectionString: string): string { - const matches: RegExpMatchArray | null = connectionString.match(/^(.*):\/\/(.*):(.*)@(.*)/); - if (matches) { - const prefix: string = matches[1]; - const username: string = matches[2]; - const password: string = matches[3]; - const hostAndQuery: string = matches[4]; - connectionString = `${prefix}://${encodeURIComponent(username)}:${encodeURIComponent(password)}@${hostAndQuery}`; - } - - return connectionString; -} diff --git a/src/documentdb/scrapbook/registerScrapbookCommands.ts b/src/documentdb/scrapbook/registerScrapbookCommands.ts deleted file mode 100644 index c985fa817..000000000 --- a/src/documentdb/scrapbook/registerScrapbookCommands.ts +++ /dev/null @@ -1,116 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { - callWithTelemetryAndErrorHandling, - registerCommandWithTreeNodeUnwrapping, - registerErrorHandler, - registerEvent, - type IActionContext, - type IErrorHandlerContext, -} from '@microsoft/vscode-azext-utils'; -import * as vscode from 'vscode'; -import { connectCluster } from '../../commands/scrapbook-commands/connectCluster'; -import { createScrapbook } from '../../commands/scrapbook-commands/createScrapbook'; -import { executeAllCommand } from '../../commands/scrapbook-commands/executeAllCommand'; -import { executeCommand } from '../../commands/scrapbook-commands/executeCommand'; -import { ext } from '../../extensionVariables'; -import { withTreeNodeCommandCorrelation } from '../../utils/commandTelemetry'; -import { MongoConnectError } from './connectToClient'; -import { MongoDBLanguageClient } from './languageClient'; -import { getAllErrorsFromTextDocument } from './ScrapbookHelpers'; -import { ScrapbookService } from './ScrapbookService'; - -let diagnosticsCollection: vscode.DiagnosticCollection; -const scrapbookLanguageId: string = 'vscode-documentdb-scrapbook-language'; - -export function registerScrapbookCommands(): void { - ext.mongoLanguageClient = new MongoDBLanguageClient(); - - ext.context.subscriptions.push( - vscode.languages.registerCodeLensProvider(scrapbookLanguageId, ScrapbookService.getCodeLensProvider()), - ); - - diagnosticsCollection = vscode.languages.createDiagnosticCollection('documentDB.vscode-documentdb-scrapbook'); - ext.context.subscriptions.push(diagnosticsCollection); - - setUpErrorReporting(); - - registerCommandWithTreeNodeUnwrapping( - 'vscode-documentdb.command.scrapbook.new', - withTreeNodeCommandCorrelation(createScrapbook), - ); - registerCommandWithTreeNodeUnwrapping( - 'vscode-documentdb.command.scrapbook.executeCommand', - withTreeNodeCommandCorrelation(executeCommand), - ); - registerCommandWithTreeNodeUnwrapping( - 'vscode-documentdb.command.scrapbook.executeAllCommands', - withTreeNodeCommandCorrelation(executeAllCommand), - ); - - // #region Database command - - registerCommandWithTreeNodeUnwrapping( - 'vscode-documentdb.command.scrapbook.connect', - withTreeNodeCommandCorrelation(connectCluster), - ); - - // #endregion -} - -function setUpErrorReporting(): void { - // Update errors immediately in case a scrapbook is already open - void callWithTelemetryAndErrorHandling( - 'scrapbook.initialUpdateErrorsInActiveDocument', - async (context: IActionContext) => { - updateErrorsInScrapbook(context, vscode.window.activeTextEditor?.document); - }, - ); - - // Update errors when document opened/changed - registerEvent( - 'vscode.workspace.onDidOpenTextDocument', - vscode.workspace.onDidOpenTextDocument, - updateErrorsInScrapbook, - ); - registerEvent( - 'vscode.workspace.onDidChangeTextDocument', - vscode.workspace.onDidChangeTextDocument, - async (context: IActionContext, event: vscode.TextDocumentChangeEvent) => { - // Always suppress success telemetry - event happens on every keystroke - context.telemetry.suppressIfSuccessful = true; - - updateErrorsInScrapbook(context, event.document); - }, - ); - registerEvent( - 'vscode.workspace.onDidCloseTextDocument', - vscode.workspace.onDidCloseTextDocument, - async (context: IActionContext, document: vscode.TextDocument) => { - // Remove errors when closed - if (document?.languageId === scrapbookLanguageId) { - diagnosticsCollection.set(document.uri, []); - } else { - context.telemetry.suppressIfSuccessful = true; - } - }, - ); - - registerErrorHandler((context: IErrorHandlerContext) => { - if (context.error instanceof MongoConnectError) { - context.errorHandling.suppressReportIssue = true; - } - }); -} - -function updateErrorsInScrapbook(context: IActionContext, document: vscode.TextDocument | undefined): void { - if (document?.languageId === scrapbookLanguageId) { - const errors = getAllErrorsFromTextDocument(document); - diagnosticsCollection.set(document.uri, errors); - } else { - context.telemetry.suppressIfSuccessful = true; - } -} diff --git a/src/documentdb/scrapbook/services/IConnectionParams.ts b/src/documentdb/scrapbook/services/IConnectionParams.ts deleted file mode 100644 index 51ed0c778..000000000 --- a/src/documentdb/scrapbook/services/IConnectionParams.ts +++ /dev/null @@ -1,13 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { type EmulatorConfiguration } from '../../../utils/emulatorConfiguration'; - -export interface IConnectionParams { - connectionString: string; - databaseName: string; - extensionUserAgent: string; - emulatorConfiguration?: EmulatorConfiguration; -} diff --git a/src/documentdb/scrapbook/services/MongoCodeLensProvider.ts b/src/documentdb/scrapbook/services/MongoCodeLensProvider.ts deleted file mode 100644 index 0372c23e9..000000000 --- a/src/documentdb/scrapbook/services/MongoCodeLensProvider.ts +++ /dev/null @@ -1,112 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { callWithTelemetryAndErrorHandling, type IActionContext } from '@microsoft/vscode-azext-utils'; -import * as l10n from '@vscode/l10n'; -import * as vscode from 'vscode'; -import { getAllCommandsFromText } from '../ScrapbookHelpers'; -import { ScrapbookService } from '../ScrapbookService'; - -/** - * Provides Code Lens functionality for the Mongo Scrapbook editor. - * - * @remarks - * This provider enables several helpful actions directly within the editor: - * - * 1. **Connection Status Lens**: - * - Displays the current database connection state (e.g., connecting, connected). - * - Offers the ability to connect to a MongoDB database if one is not yet connected. - * - * 2. **Execute All Commands Lens**: - * - Runs all detected MongoDB commands in the scrapbook document at once when triggered. - * - * 3. **Execute Single Command Lens**: - * - Appears for each individual MongoDB command found in the scrapbook. - * - Invokes execution of the command located at the specified range in the document. - */ -export class MongoCodeLensProvider implements vscode.CodeLensProvider { - private _onDidChangeEmitter: vscode.EventEmitter = new vscode.EventEmitter(); - - /** - * An event to signal that the code lenses from this provider have changed. - */ - public get onDidChangeCodeLenses(): vscode.Event { - return this._onDidChangeEmitter.event; - } - - public updateCodeLens(): void { - this._onDidChangeEmitter.fire(); - } - public provideCodeLenses( - document: vscode.TextDocument, - _token: vscode.CancellationToken, - ): vscode.ProviderResult { - return callWithTelemetryAndErrorHandling('scrapbook.provideCodeLenses', (context: IActionContext) => { - context.telemetry.suppressIfSuccessful = true; - - const lenses: vscode.CodeLens[] = []; - - // Create connection status lens - lenses.push(this.createConnectionStatusLens()); - - // Create run-all lens - lenses.push(this.createRunAllCommandsLens()); - - // Create lenses for each individual command - const commands = getAllCommandsFromText(document.getText()); - lenses.push(...this.createIndividualCommandLenses(commands)); - - return lenses; - }); - } - - private createConnectionStatusLens(): vscode.CodeLens { - const title = ScrapbookService.isConnected() - ? l10n.t('Connected to "{name}"', { name: ScrapbookService.getDisplayName() ?? '' }) - : l10n.t('Connect to a database'); - - const shortenedTitle = - title.length > 64 ? title.slice(0, 64 / 2) + '…' + title.slice(-(64 - 3 - 64 / 2)) : title; - - return { - command: { - title: '🌐 ' + shortenedTitle, - tooltip: title, - command: 'vscode-documentdb.command.scrapbook.connect', - }, - range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)), - }; - } - - private createRunAllCommandsLens(): vscode.CodeLens { - const title = ScrapbookService.isExecutingAllCommands() ? l10n.t('⏳ Running All…') : l10n.t('⏩ Run All'); - - return { - command: { - title, - command: 'vscode-documentdb.command.scrapbook.executeAllCommands', - }, - range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)), - }; - } - - private createIndividualCommandLenses(commands: { range: vscode.Range }[]): vscode.CodeLens[] { - const currentCommandInExectution = ScrapbookService.getSingleCommandInExecution(); - - return commands.map((cmd) => { - const running = currentCommandInExectution && cmd.range.isEqual(currentCommandInExectution.range); - const title = running ? l10n.t('⏳ Running Command…') : l10n.t('▶️ Run Command'); - - return { - command: { - title, - command: 'vscode-documentdb.command.scrapbook.executeCommand', - arguments: [cmd.range.start], - }, - range: cmd.range, - }; - }); - } -} diff --git a/src/documentdb/scrapbook/services/completionItemProvider.ts b/src/documentdb/scrapbook/services/completionItemProvider.ts deleted file mode 100644 index ad94fe2ff..000000000 --- a/src/documentdb/scrapbook/services/completionItemProvider.ts +++ /dev/null @@ -1,507 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -/* eslint-disable @typescript-eslint/no-non-null-assertion */ - -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { ErrorNode } from 'antlr4ts/tree/ErrorNode'; -import { type ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { type Db } from 'mongodb'; -import { type LanguageService as JsonLanguageService } from 'vscode-json-languageservice'; -import { CompletionItemKind, Position, Range, type CompletionItem } from 'vscode-languageserver'; -import { TextDocument } from 'vscode-languageserver-textdocument'; -import { mongoLexer } from '../../grammar/mongoLexer'; -import * as mongoParser from '../../grammar/mongoParser'; -import { MongoVisitor } from '../../grammar/visitors'; -import { type SchemaService } from './schemaService'; - -export class CompletionItemsVisitor extends MongoVisitor> { - private at: Position; - - constructor( - private textDocument: TextDocument, - private db: Db, - private offset: number, - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService, - ) { - super(); - this.at = this.textDocument.positionAt(this.offset); - } - - public visitCommands(ctx: mongoParser.CommandsContext): Promise { - return this.thenable(this.createDbKeywordCompletion(this.createRange(ctx))); - } - - public visitEmptyCommand(ctx: mongoParser.EmptyCommandContext): Promise { - return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(ctx))); - } - - public visitCommand(ctx: mongoParser.CommandContext): Promise { - if (ctx.childCount === 0) { - return this.thenable(this.createDbKeywordCompletion(this.createRange(ctx))); - } - - const lastTerminalNode = this.getLastTerminalNode(ctx); - if (lastTerminalNode) { - return this.getCompletionItemsFromTerminalNode(lastTerminalNode); - } - return this.thenable(); - } - - public visitCollection(ctx: mongoParser.CollectionContext): Promise { - return Promise.all([ - this.createCollectionCompletions(this.createRange(ctx)), - this.createDbFunctionCompletions(this.createRange(ctx)), - ]).then(([collectionCompletions, dbFunctionCompletions]) => [ - ...collectionCompletions, - ...dbFunctionCompletions, - ]); - } - - public visitFunctionCall(ctx: mongoParser.FunctionCallContext): Promise { - const previousNode = this.getPreviousNode(ctx); - if (previousNode instanceof TerminalNode) { - return this.getCompletionItemsFromTerminalNode(previousNode); - } - return this.thenable(); - } - - public visitArguments(ctx: mongoParser.ArgumentsContext): Promise { - const terminalNode = this.getLastTerminalNode(ctx); - if (terminalNode && terminalNode.symbol === ctx._CLOSED_PARENTHESIS) { - return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(terminalNode))); - } - return this.thenable(); - } - - public visitArgument(ctx: mongoParser.ArgumentContext): Promise { - return ctx.parent!.accept(this); - } - - public visitObjectLiteral(ctx: mongoParser.ObjectLiteralContext): Thenable { - const functionName = this.getFunctionName(ctx); - const collectionName = this.getCollectionName(ctx); - if (collectionName && functionName) { - if ( - [ - 'find', - 'findOne', - 'findOneAndDelete', - 'findOneAndUpdate', - 'findOneAndReplace', - 'deleteOne', - 'deleteMany', - 'remove', - ].indexOf(functionName) !== -1 - ) { - return this.getArgumentCompletionItems( - this.schemaService.queryDocumentUri(collectionName), - collectionName, - ctx, - ); - } - } - return ctx.parent!.accept(this); - } - - public visitArrayLiteral(ctx: mongoParser.ArrayLiteralContext): Thenable { - const functionName = this.getFunctionName(ctx); - const collectionName = this.getCollectionName(ctx); - if (collectionName && functionName) { - if (['aggregate'].indexOf(functionName) !== -1) { - return this.getArgumentCompletionItems( - this.schemaService.aggregateDocumentUri(collectionName), - collectionName, - ctx, - ); - } - } - return ctx.parent!.accept(this); - } - - public visitElementList(ctx: mongoParser.ElementListContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyNameAndValueList(ctx: mongoParser.PropertyNameAndValueListContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyAssignment(ctx: mongoParser.PropertyAssignmentContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyValue(ctx: mongoParser.PropertyValueContext): Promise { - return ctx.parent!.accept(this); - } - - public visitPropertyName(ctx: mongoParser.PropertyNameContext): Promise { - return ctx.parent!.accept(this); - } - - public visitLiteral(ctx: mongoParser.LiteralContext): Promise { - return ctx.parent!.accept(this); - } - - public visitTerminal(ctx: TerminalNode): Promise { - return ctx.parent!.accept(this); - } - - public visitErrorNode(ctx: ErrorNode): Promise { - return ctx.parent!.accept(this); - } - - private async getArgumentCompletionItems( - documentUri: string, - _collectionName: string, - ctx: ParserRuleContext, - ): Promise { - const text = this.textDocument.getText(); - const document = TextDocument.create( - documentUri, - 'json', - 1, - text.substring(ctx.start.startIndex, ctx.stop!.stopIndex + 1), - ); - const positionOffset = this.textDocument.offsetAt(this.at); - const contextOffset = ctx.start.startIndex; - const position = document.positionAt(positionOffset - contextOffset); - const list = await this.jsonLanguageService.doComplete( - document, - position, - this.jsonLanguageService.parseJSONDocument(document), - ); - - if (!list) { - return []; - } - - return list.items.map((item: CompletionItem) => { - if (!item.textEdit) return item; - - const range = 'range' in item.textEdit ? item.textEdit.range : item.textEdit.replace; - const startPositionOffset = document.offsetAt(range.start); - const endPositionOffset = document.offsetAt(range.end); - const newRange = Range.create( - this.textDocument.positionAt(startPositionOffset + contextOffset), - this.textDocument.positionAt(contextOffset + endPositionOffset), - ); - - if ('range' in item.textEdit) { - item.textEdit.range = newRange; - } else { - item.textEdit.replace = newRange; - } - - return item; - }); - } - - private getFunctionName(ctx: ParseTree): string { - let parent = ctx.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { - return null!; - } - return (parent)._FUNCTION_NAME.text!; - } - - private getCollectionName(ctx: ParseTree): string { - let parent = ctx.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.ArgumentsContext)) { - return null!; - } - parent = parent.parent!; - if (!(parent && parent instanceof mongoParser.FunctionCallContext)) { - return null!; - } - let previousNode = this.getPreviousNode(parent); - if (previousNode && previousNode instanceof TerminalNode && previousNode.symbol.type === mongoLexer.DOT) { - previousNode = this.getPreviousNode(previousNode); - if (previousNode && previousNode instanceof mongoParser.CollectionContext) { - return previousNode.text; - } - } - return null!; - } - - private getCompletionItemsFromTerminalNode(node: TerminalNode): Promise { - if (node._symbol.type === mongoParser.mongoParser.DB) { - return this.thenable(this.createDbKeywordCompletion(this.createRange(node))); - } - if (node._symbol.type === mongoParser.mongoParser.SEMICOLON) { - return this.thenable(this.createDbKeywordCompletion(this.createRangeAfter(node))); - } - if (node._symbol.type === mongoParser.mongoParser.DOT) { - const previousNode = this.getPreviousNode(node); - if (previousNode && previousNode instanceof TerminalNode) { - if (previousNode._symbol.type === mongoParser.mongoParser.DB) { - return Promise.all([ - this.createCollectionCompletions(this.createRangeAfter(node)), - this.createDbFunctionCompletions(this.createRangeAfter(node)), - ]).then(([collectionCompletions, dbFunctionCompletions]) => [ - ...collectionCompletions, - ...dbFunctionCompletions, - ]); - } - } - if (previousNode instanceof mongoParser.CollectionContext) { - return this.createCollectionFunctionsCompletions(this.createRangeAfter(node)); - } - } - if (node instanceof ErrorNode) { - const previousNode = this.getPreviousNode(node); - if (previousNode) { - if (previousNode instanceof TerminalNode) { - return this.getCompletionItemsFromTerminalNode(previousNode); - } - return previousNode.accept(this); - } - } - return this.thenable(); - } - - private getLastTerminalNode(ctx: ParserRuleContext): TerminalNode { - return ctx.children ? ctx.children - .slice() - .reverse() - .filter( - (node) => - node instanceof TerminalNode && - node.symbol.stopIndex > -1 && - node.symbol.stopIndex < this.offset, - )[0] : null!; - } - - private getPreviousNode(node: ParseTree): ParseTree { - let previousNode: ParseTree = null!; - const parentNode = node.parent!; - for (let i = 0; i < parentNode.childCount; i++) { - const currentNode = parentNode.getChild(i); - if (currentNode === node) { - break; - } - previousNode = currentNode; - } - return previousNode; - } - - private createDbKeywordCompletion(range: Range): CompletionItem { - return { - textEdit: { - newText: 'db', - range, - }, - kind: CompletionItemKind.Keyword, - label: 'db', - }; - } - - private createDbFunctionCompletions(range: Range): Promise { - return this.thenable( - this.createFunctionCompletion('adminCommand', range), - this.createFunctionCompletion('auth', range), - this.createFunctionCompletion('cloneDatabase', range), - this.createFunctionCompletion('commandHelp', range), - this.createFunctionCompletion('copyDatabase', range), - this.createFunctionCompletion('createCollection', range), - this.createFunctionCompletion('createView', range), - this.createFunctionCompletion('createUser', range), - this.createFunctionCompletion('currentOp', range), - this.createFunctionCompletion('dropDatabase', range), - this.createFunctionCompletion('eval', range), - this.createFunctionCompletion('fsyncLock', range), - this.createFunctionCompletion('fsyncUnLock', range), - this.createFunctionCompletion('getCollection', range), - this.createFunctionCompletion('getCollectionInfos', range), - this.createFunctionCompletion('getCollectionNames', range), - this.createFunctionCompletion('getLastError', range), - this.createFunctionCompletion('getLastErrorObj', range), - this.createFunctionCompletion('getLogComponents', range), - this.createFunctionCompletion('getMongo', range), - this.createFunctionCompletion('getName', range), - this.createFunctionCompletion('getPrevError', range), - this.createFunctionCompletion('getProfilingLevel', range), - this.createFunctionCompletion('getProfilingStatus', range), - this.createFunctionCompletion('getReplicationInfo', range), - this.createFunctionCompletion('getSiblingDB', range), - this.createFunctionCompletion('getWriteConcern', range), - this.createFunctionCompletion('hostInfo', range), - this.createFunctionCompletion('isMaster', range), - this.createFunctionCompletion('killOp', range), - this.createFunctionCompletion('listCommands', range), - this.createFunctionCompletion('loadServerScripts', range), - this.createFunctionCompletion('logout', range), - this.createFunctionCompletion('printCollectionStats', range), - this.createFunctionCompletion('printReplicationInfo', range), - this.createFunctionCompletion('printShardingStatus', range), - this.createFunctionCompletion('printSlaveReplicationInfo', range), - this.createFunctionCompletion('dropUser', range), - this.createFunctionCompletion('repairDatabase', range), - this.createFunctionCompletion('runCommand', range), - this.createFunctionCompletion('serverStatus', range), - this.createFunctionCompletion('setLogLevel', range), - this.createFunctionCompletion('setProfilingLevel', range), - this.createFunctionCompletion('setWriteConcern', range), - this.createFunctionCompletion('unsetWriteConcern', range), - this.createFunctionCompletion('setVerboseShell', range), - this.createFunctionCompletion('shotdownServer', range), - this.createFunctionCompletion('stats', range), - this.createFunctionCompletion('version', range), - ); - } - - private createCollectionCompletions(range: Range): Promise { - if (this.db) { - return >this.db.collections().then((collections) => { - return collections.map( - (collection) => - { - textEdit: { - newText: collection.collectionName, - range, - }, - label: collection.collectionName, - kind: CompletionItemKind.Property, - filterText: collection.collectionName, - sortText: `1:${collection.collectionName}`, - }, - ); - }); - } - return Promise.resolve([]); - } - - private createCollectionFunctionsCompletions(range: Range): Promise { - return this.thenable( - this.createFunctionCompletion('bulkWrite', range), - this.createFunctionCompletion('count', range), - this.createFunctionCompletion('copyTo', range), - this.createFunctionCompletion('convertToCapped', range), - this.createFunctionCompletion('createIndex', range), - this.createFunctionCompletion('createIndexes', range), - this.createFunctionCompletion('dataSize', range), - this.createFunctionCompletion('deleteOne', range), - this.createFunctionCompletion('deleteMany', range), - this.createFunctionCompletion('distinct', range), - this.createFunctionCompletion('drop', range), - this.createFunctionCompletion('dropIndex', range), - this.createFunctionCompletion('dropIndexes', range), - this.createFunctionCompletion('ensureIndex', range), - this.createFunctionCompletion('explain', range), - this.createFunctionCompletion('reIndex', range), - this.createFunctionCompletion('find', range), - this.createFunctionCompletion('findOne', range), - this.createFunctionCompletion('findOneAndDelete', range), - this.createFunctionCompletion('findOneAndReplace', range), - this.createFunctionCompletion('findOneAndUpdate', range), - this.createFunctionCompletion('getDB', range), - this.createFunctionCompletion('getPlanCache', range), - this.createFunctionCompletion('getIndexes', range), - this.createFunctionCompletion('group', range), - this.createFunctionCompletion('insert', range), - this.createFunctionCompletion('insertOne', range), - this.createFunctionCompletion('insertMany', range), - this.createFunctionCompletion('mapReduce', range), - this.createFunctionCompletion('aggregate', range), - this.createFunctionCompletion('remove', range), - this.createFunctionCompletion('replaceOne', range), - this.createFunctionCompletion('renameCollection', range), - this.createFunctionCompletion('runCommand', range), - this.createFunctionCompletion('save', range), - this.createFunctionCompletion('stats', range), - this.createFunctionCompletion('storageSize', range), - this.createFunctionCompletion('totalIndexSize', range), - this.createFunctionCompletion('update', range), - this.createFunctionCompletion('updateOne', range), - this.createFunctionCompletion('updateMany', range), - this.createFunctionCompletion('validate', range), - this.createFunctionCompletion('getShardVersion', range), - this.createFunctionCompletion('getShardDistribution', range), - this.createFunctionCompletion('getSplitKeysForChunks', range), - this.createFunctionCompletion('getWriteConcern', range), - this.createFunctionCompletion('setWriteConcern', range), - this.createFunctionCompletion('unsetWriteConcern', range), - this.createFunctionCompletion('latencyStats', range), - ); - } - - private createFunctionCompletion(label: string, range: Range): CompletionItem { - return { - textEdit: { - newText: label, - range, - }, - kind: CompletionItemKind.Function, - label, - sortText: `2:${label}`, - }; - } - - private createRange(parserRuleContext: ParseTree): Range { - if (parserRuleContext instanceof ParserRuleContext) { - const startToken = parserRuleContext.start; - let stopToken = parserRuleContext.stop; - if (!stopToken || startToken.type === mongoParser.mongoParser.EOF) { - stopToken = startToken; - } - - const stop = stopToken.stopIndex; - return this._createRange(startToken.startIndex, stop); - } - - if (parserRuleContext instanceof TerminalNode) { - return this._createRange(parserRuleContext.symbol.startIndex, parserRuleContext.symbol.stopIndex); - } - - return null!; - } - - private createRangeAfter(parserRuleContext: ParseTree): Range { - if (parserRuleContext instanceof ParserRuleContext) { - let stopToken = parserRuleContext.stop; - if (!stopToken) { - stopToken = parserRuleContext.start; - } - - const stop = stopToken.stopIndex; - return this._createRange(stop + 1, stop + 1); - } - - if (parserRuleContext instanceof TerminalNode) { - return this._createRange(parserRuleContext.symbol.stopIndex + 1, parserRuleContext.symbol.stopIndex + 1); - } - - //currently returning an null for the sake of linting. Would prefer to throw an error, but don't want - // to introduce a regression bug. - return null!; - } - - private _createRange(start: number, end: number): Range { - const endPosition = this.textDocument.positionAt(end); - if (endPosition.line < this.at.line) { - return Range.create(Position.create(this.at.line, 0), this.at); - } - const startPosition = this.textDocument.positionAt(start); - return Range.create(startPosition, endPosition); - } - - private thenable(...completionItems: CompletionItem[]): Promise { - return Promise.resolve(completionItems || []); - } -} diff --git a/src/documentdb/scrapbook/services/languageService.ts b/src/documentdb/scrapbook/services/languageService.ts deleted file mode 100644 index 24efe7083..000000000 --- a/src/documentdb/scrapbook/services/languageService.ts +++ /dev/null @@ -1,121 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -/* eslint-disable import/no-internal-modules */ - -// NOTE: This file may not take a dependency on vscode or anything that takes a dependency on it (such as @microsoft/vscode-azext-utils) - -import { type Db } from 'mongodb'; -import { - getLanguageService, - type LanguageService as JsonLanguageService, - type SchemaConfiguration, -} from 'vscode-json-languageservice'; -import { TextDocument } from 'vscode-languageserver-textdocument'; -import { - createConnection, - ProposedFeatures, - TextDocuments, - TextDocumentSyncKind, - type CompletionItem, - type InitializeParams, - type InitializeResult, - type TextDocumentPositionParams, -} from 'vscode-languageserver/node'; -import { connectToClient } from '../connectToClient'; -import { type IConnectionParams } from './IConnectionParams'; -import { MongoScriptDocumentManager } from './mongoScript'; -import { SchemaService } from './schemaService'; - -export class LanguageService { - private textDocuments: TextDocuments = new TextDocuments(TextDocument); - private readonly mongoDocumentsManager: MongoScriptDocumentManager; - private db: Db | null = null; - - private readonly jsonLanguageService: JsonLanguageService; - private readonly schemaService: SchemaService; - private schemas: SchemaConfiguration[]; - - constructor() { - // Create a connection for the server - const connection = createConnection(ProposedFeatures.all); - - // eslint-disable-next-line - console.log = connection.console.log.bind(connection.console); - - // eslint-disable-next-line - console.error = connection.console.error.bind(connection.console); - this.schemaService = new SchemaService(); - - // Make the text document manager listen on the connection - // for open, change and close text document events - this.textDocuments.listen(connection); - - // Listen on the connection - connection.listen(); - // After the server has started the client sends an initialize request. The server receives - // in the passed params the rootPath of the workspace plus the client capabilities. - connection.onInitialize((_params: InitializeParams): InitializeResult => { - return { - capabilities: { - textDocumentSync: TextDocumentSyncKind.Full, // Tell the client that the server works in FULL text document sync mode - completionProvider: { triggerCharacters: ['.'] }, - }, - }; - }); - - connection.onCompletion((textDocumentPosition) => { - return this.provideCompletionItems(textDocumentPosition); - }); - - connection.onRequest('connect', (connectionParams: IConnectionParams) => { - void connectToClient( - connectionParams.connectionString, - connectionParams.extensionUserAgent, - connectionParams.emulatorConfiguration, - ).then((account) => { - this.db = account.db(connectionParams.databaseName); - void this.schemaService.registerSchemas(this.db).then((schemas) => { - this.configureSchemas(schemas); - }); - }); - }); - - connection.onRequest('disconnect', () => { - this.db = null; - for (const schema of this.schemas) { - this.jsonLanguageService.resetSchema(schema.uri); - } - }); - - this.jsonLanguageService = getLanguageService({ - schemaRequestService: (uri) => this.schemaService.resolveSchema(uri), - contributions: [], - }); - - this.mongoDocumentsManager = new MongoScriptDocumentManager(this.schemaService, this.jsonLanguageService); - } - - public provideCompletionItems(positionParams: TextDocumentPositionParams): Promise { - const textDocument = this.textDocuments.get(positionParams.textDocument.uri); - - if (!textDocument || !this.db) { - return Promise.resolve([]); - } - - const mongoScriptDocument = this.mongoDocumentsManager.getDocument(textDocument, this.db); - return mongoScriptDocument.provideCompletionItemsAt(positionParams.position); - } - - public resetSchema(uri: string): void { - this.jsonLanguageService.resetSchema(uri); - } - - public configureSchemas(schemas: SchemaConfiguration[]): void { - this.jsonLanguageService.configure({ - schemas, - }); - } -} diff --git a/src/documentdb/scrapbook/services/mongoScript.ts b/src/documentdb/scrapbook/services/mongoScript.ts deleted file mode 100644 index c1102d99c..000000000 --- a/src/documentdb/scrapbook/services/mongoScript.ts +++ /dev/null @@ -1,120 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ANTLRInputStream as InputStream } from 'antlr4ts/ANTLRInputStream'; -import { CommonTokenStream } from 'antlr4ts/CommonTokenStream'; -import { Interval } from 'antlr4ts/misc/Interval'; -import { ParserRuleContext } from 'antlr4ts/ParserRuleContext'; -import { type ParseTree } from 'antlr4ts/tree/ParseTree'; -import { TerminalNode } from 'antlr4ts/tree/TerminalNode'; -import { type Db } from 'mongodb'; -import { type LanguageService as JsonLanguageService } from 'vscode-json-languageservice'; -import { type CompletionItem, type Position } from 'vscode-languageserver'; -import { type TextDocument } from 'vscode-languageserver-textdocument'; -import { mongoLexer } from '../../grammar/mongoLexer'; -import * as mongoParser from '../../grammar/mongoParser'; -import { MongoVisitor } from '../../grammar/visitors'; -import { CompletionItemsVisitor } from './completionItemProvider'; -import { type SchemaService } from './schemaService'; - -export class MongoScriptDocumentManager { - constructor( - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService, - ) {} - - public getDocument(textDocument: TextDocument, db: Db): MongoScriptDocument { - return new MongoScriptDocument(textDocument, db, this.schemaService, this.jsonLanguageService); - } -} - -export class MongoScriptDocument { - private readonly _lexer: mongoLexer; - - constructor( - private textDocument: TextDocument, - private db: Db, - private schemaService: SchemaService, - private jsonLanguageService: JsonLanguageService, - ) { - this._lexer = new mongoLexer(new InputStream(textDocument.getText())); - this._lexer.removeErrorListeners(); - } - - public provideCompletionItemsAt(position: Position): Promise { - const parser = new mongoParser.mongoParser(new CommonTokenStream(this._lexer)); - parser.removeErrorListeners(); - - const offset = this.textDocument.offsetAt(position); - const lastNode = new NodeFinder(offset).visit(parser.commands()); - if (lastNode) { - return new CompletionItemsVisitor( - this.textDocument, - this.db, - offset, - this.schemaService, - this.jsonLanguageService, - ).visit(lastNode); - } - return Promise.resolve([]); - } -} - -class NodeFinder extends MongoVisitor { - constructor(private offset: number) { - super(); - } - - protected defaultResult(ctx: ParseTree): ParseTree | null { - if (ctx instanceof ParserRuleContext) { - const stop = ctx.stop ? ctx.stop.stopIndex : ctx.start.stopIndex; - if (stop < this.offset) { - return ctx; - } - - return null; - } - if (ctx instanceof TerminalNode) { - if (ctx.symbol.stopIndex < this.offset) { - return ctx; - } - - return null; - } - - return null; - } - - protected aggregateResult(aggregate: ParseTree, nextResult: ParseTree): ParseTree { - if (aggregate && nextResult) { - const aggregateStart = - aggregate instanceof ParserRuleContext - ? aggregate.start.startIndex - : (aggregate).symbol.startIndex; - const aggregateStop = - aggregate instanceof ParserRuleContext - ? aggregate.start.stopIndex - : (aggregate).symbol.stopIndex; - const nextResultStart = - nextResult instanceof ParserRuleContext - ? nextResult.start.startIndex - : (nextResult).symbol.startIndex; - const nextResultStop = - nextResult instanceof ParserRuleContext - ? nextResult.start.stopIndex - : (nextResult).symbol.stopIndex; - - if ( - Interval.of(aggregateStart, aggregateStop).properlyContains( - Interval.of(nextResultStart, nextResultStop), - ) - ) { - return aggregate; - } - return nextResult; - } - return nextResult ? nextResult : aggregate; - } -} diff --git a/src/documentdb/scrapbook/services/schemaService.ts b/src/documentdb/scrapbook/services/schemaService.ts deleted file mode 100644 index bd300365d..000000000 --- a/src/documentdb/scrapbook/services/schemaService.ts +++ /dev/null @@ -1,666 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */ - -import { type Db, type FindCursor } from 'mongodb'; -import { type JSONSchema, type SchemaConfiguration } from 'vscode-json-languageservice'; - -export class SchemaService { - private _db: Db; - private _schemasCache: Map = new Map(); - - public registerSchemas(db: Db): Thenable { - this._db = db; - this._schemasCache.clear(); - return this._db.collections().then((collections) => { - const schemas: SchemaConfiguration[] = []; - for (const collection of collections) { - schemas.push( - ...[ - { - uri: this.queryCollectionSchema(collection.collectionName), - fileMatch: [this.queryDocumentUri(collection.collectionName)], - }, - { - uri: this.aggregateCollectionSchema(collection.collectionName), - fileMatch: [this.aggregateDocumentUri(collection.collectionName)], - }, - ], - ); - } - return schemas; - }); - } - - public queryCollectionSchema(collectionName: string): string { - return 'mongo://query/' + collectionName + '.schema'; - } - - public aggregateCollectionSchema(collectionName: string): string { - return 'mongo://aggregate/' + collectionName + '.schema'; - } - - public queryDocumentUri(collectionName: string): string { - return 'mongo://query/' + collectionName + '.json'; - } - - public aggregateDocumentUri(collectionName: string): string { - return 'mongo://aggregate/' + collectionName + '.json'; - } - - public resolveSchema(uri: string): Thenable { - const schema = this._schemasCache.get(uri); - if (schema) { - return Promise.resolve(schema); - } - if (uri.startsWith('mongo://query/')) { - return this._resolveQueryCollectionSchema( - uri.substring('mongo://query/'.length, uri.length - '.schema'.length), - uri, - ).then((sch) => { - this._schemasCache.set(uri, sch); - return sch; - }); - } - if (uri.startsWith('mongo://aggregate/')) { - return this._resolveAggregateCollectionSchema( - uri.substring('mongo://aggregate/'.length, uri.length - '.schema'.length), - ).then((sch) => { - this._schemasCache.set(uri, sch); - return sch; - }); - } - return Promise.resolve(''); - } - - private _resolveQueryCollectionSchema(collectionName: string, schemaUri: string): Thenable { - const collection = this._db.collection(collectionName); - const cursor = collection.find(); - return new Promise((resolve, _reject) => { - this.readNext([], cursor, 10, (result) => { - const schema: JSONSchema = { - type: 'object', - properties: {}, - }; - for (const document of result) { - this.setSchemaForDocument(null!, document, schema); - } - this.setGlobalOperatorProperties(schema); - this.setLogicalOperatorProperties(schema, schemaUri); - resolve(JSON.stringify(schema)); - }); - }); - } - - private _resolveAggregateCollectionSchema(collectionName: string): Thenable { - const collection = this._db.collection(collectionName); - const cursor = collection.find(); - return new Promise((resolve, _reject) => { - this.readNext([], cursor, 10, (_result) => { - const schema: JSONSchema = { - type: 'array', - items: this.getAggregateStagePropertiesSchema(this.queryCollectionSchema(collectionName)), - }; - resolve(JSON.stringify(schema)); - }); - }); - } - - private getMongoDocumentType(document: any): string { - return Array.isArray(document) ? 'array' : document === null ? 'null' : typeof document; - } - - private setSchemaForDocument(parent: string, document: any, schema: JSONSchema): void { - if (this.getMongoDocumentType(document) === 'object') { - //eslint-disable-next-line @typescript-eslint/no-unsafe-argument - for (const property of Object.keys(document)) { - if (!parent && ['_id'].indexOf(property) !== -1) { - continue; - } - this.setSchemaForDocumentProperty(parent, property, document, schema); - } - } - } - - private setSchemaForDocumentProperty(parent: string, property: string, document: any, schema: JSONSchema): void { - const scopedProperty = parent ? `${parent}.${property}` : property; - // eslint-disable-next-line , @typescript-eslint/no-unsafe-assignment - const value = document[property]; - const type = this.getMongoDocumentType(value); - - const propertySchema: JSONSchema = { - type: [type, 'object'], - }; - this.setOperatorProperties(type, propertySchema); - schema.properties![scopedProperty] = propertySchema; - - if (type === 'object') { - this.setSchemaForDocument(scopedProperty, value, schema); - } - - if (type === 'array') { - for (const v of value) { - this.setSchemaForDocument(scopedProperty, v, schema); - } - } - } - - private setGlobalOperatorProperties(schema: JSONSchema): void { - schema.properties!.$text = { - type: 'object', - description: 'Performs text search', - properties: { - $search: { - type: 'string', - description: - 'A string of terms that MongoDB parses and uses to query the text index. MongoDB performs a logical OR search of the terms unless specified as a phrase', - }, - $language: { - type: 'string', - description: - 'Optional. The language that determines the list of stop words for the search and the rules for the stemmer and tokenizer. If not specified, the search uses the default language of the index.\nIf you specify a language value of "none", then the text search uses simple tokenization with no list of stop words and no stemming', - }, - $caseSensitive: { - type: 'boolean', - description: - 'Optional. A boolean flag to enable or disable case sensitive search. Defaults to false; i.e. the search defers to the case insensitivity of the text index', - }, - $diacriticSensitive: { - type: 'boolean', - description: `Optional. A boolean flag to enable or disable diacritic sensitive search against version 3 text indexes.Defaults to false; i.e.the search defers to the diacritic insensitivity of the text index -Text searches against earlier versions of the text index are inherently diacritic sensitive and cannot be diacritic insensitive. As such, the $diacriticSensitive option has no effect with earlier versions of the text index`, - }, - }, - required: ['$search'], - }; - - schema.properties!.$where = { - type: 'string', - description: `Matches documents that satisfy a JavaScript expression. -Use the $where operator to pass either a string containing a JavaScript expression or a full JavaScript function to the query system`, - }; - schema.properties!.$comment = { - type: 'string', - description: 'Adds a comment to a query predicate', - }; - } - - private setLogicalOperatorProperties(schema: JSONSchema, schemaUri: string): void { - schema.properties!.$or = { - type: 'array', - description: - 'Joins query clauses with a logical OR returns all documents that match the conditions of either clause', - items: { - $ref: schemaUri, - }, - }; - schema.properties!.$and = { - type: 'array', - description: - 'Joins query clauses with a logical AND returns all documents that match the conditions of both clauses', - items: { - $ref: schemaUri, - }, - }; - schema.properties!.$nor = { - type: 'array', - description: 'Joins query clauses with a logical NOR returns all documents that fail to match both clauses', - items: { - $ref: schemaUri, - }, - }; - } - - private setOperatorProperties(type: string, schema: JSONSchema): void { - if (!schema.properties) { - schema.properties = {}; - } - - const expressionSchema = { - // eslint-disable-next-line - properties: {}, - }; - // Comparison operators - expressionSchema.properties.$eq = { - type: type, - description: 'Matches values that are equal to a specified value', - }; - expressionSchema.properties.$gt = { - type: type, - description: 'Matches values that are greater than a specified value', - }; - expressionSchema.properties.$gte = { - type: type, - description: 'Matches values that are greater than or equal to a specified value', - }; - expressionSchema.properties.$lt = { - type: type, - description: 'Matches values that are less than a specified value', - }; - expressionSchema.properties.$lte = { - type: type, - description: 'Matches values that are less than or equal to a specified value', - }; - expressionSchema.properties.$ne = { - type: type, - description: 'Matches all values that are not equal to a specified value', - }; - expressionSchema.properties.$in = { - type: 'array', - description: 'Matches any of the values specified in an array', - }; - expressionSchema.properties.$nin = { - type: 'array', - description: 'Matches none of the values specified in an array', - }; - - // Element operators - expressionSchema.properties.$exists = { - type: 'boolean', - description: 'Matches documents that have the specified field', - }; - expressionSchema.properties.$type = { - type: 'string', - description: 'Selects documents if a field is of the specified type', - }; - - // Evaluation operators - expressionSchema.properties.$mod = { - type: 'array', - description: - 'Performs a modulo operation on the value of a field and selects documents with a specified result', - maxItems: 2, - default: [2, 0], - }; - expressionSchema.properties.$regex = { - type: 'string', - description: 'Selects documents where values match a specified regular expression', - }; - - // Geospatial - const geometryPropertySchema: JSONSchema = { - type: 'object', - properties: { - type: { - type: 'string', - default: 'GeoJSON object type', - }, - coordinates: { - type: 'array', - }, - crs: { - type: 'object', - properties: { - type: { - type: 'string', - }, - properties: { - type: 'object', - }, - }, - }, - }, - }; - expressionSchema.properties.$geoWithin = { - type: 'object', - description: - 'Selects geometries within a bounding GeoJSON geometry. The 2dsphere and 2d indexes support $geoWithin', - properties: { - $geometry: geometryPropertySchema, - $box: { - type: 'array', - }, - $polygon: { - type: 'array', - }, - $center: { - type: 'array', - }, - $centerSphere: { - type: 'array', - }, - }, - }; - expressionSchema.properties.$geoIntersects = { - type: 'object', - description: - 'Selects geometries that intersect with a GeoJSON geometry. The 2dsphere index supports $geoIntersects', - properties: { - $geometry: geometryPropertySchema, - }, - }; - expressionSchema.properties.$near = { - type: 'object', - description: - 'Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near', - properties: { - $geometry: geometryPropertySchema, - $maxDistance: { - type: 'number', - }, - $minDistance: { - type: 'number', - }, - }, - }; - expressionSchema.properties.$nearSphere = { - type: 'object', - description: - 'Returns geospatial objects in proximity to a point. Requires a geospatial index. The 2dsphere and 2d indexes support $near', - properties: { - $geometry: geometryPropertySchema, - $maxDistance: { - type: 'number', - }, - $minDistance: { - type: 'number', - }, - }, - }; - - // Array operatos - if (type === 'array') { - expressionSchema.properties.$all = { - type: 'array', - description: 'Matches arrays that contain all elements specified in the query', - }; - expressionSchema.properties.$size = { - type: 'number', - description: 'Selects documents if the array field is a specified size', - }; - } - - // Bit operators - expressionSchema.properties.$bitsAllSet = { - type: 'array', - description: 'Matches numeric or binary values in which a set of bit positions all have a value of 1', - }; - expressionSchema.properties.$bitsAnySet = { - type: 'array', - description: - 'Matches numeric or binary values in which any bit from a set of bit positions has a value of 1', - }; - expressionSchema.properties.$bitsAllClear = { - type: 'array', - description: 'Matches numeric or binary values in which a set of bit positions all have a value of 0', - }; - expressionSchema.properties.$bitsAnyClear = { - type: 'array', - description: - 'Matches numeric or binary values in which any bit from a set of bit positions has a value of 0', - }; - - // eslint-disable-next-line - schema.properties = { ...expressionSchema.properties }; - schema.properties!.$not = { - type: 'object', - description: - 'Inverts the effect of a query expression and returns documents that do not match the query expression', - // eslint-disable-next-line - properties: { ...expressionSchema.properties }, - }; - schema.properties!.$elemMatch = { - type: 'object', - }; - } - - private getAggregateStagePropertiesSchema(querySchemaUri: string): JSONSchema { - const schemas: JSONSchema[] = []; - schemas.push({ - type: 'object', - properties: { - $collStats: { - type: 'object', - description: 'Returns statistics regarding a collection or view', - }, - }, - }); - schemas.push({ - type: 'object', - properties: { - $project: { - type: 'object', - description: - 'Reshapes each document in the stream, such as by adding new fields or removing existing fields. For each input document, outputs one document', - }, - }, - }); - schemas.push({ - type: 'object', - properties: { - $match: { - type: 'object', - description: - 'Filters the document stream to allow only matching documents to pass unmodified into the next pipeline stage. $match uses standard MongoDB queries. For each input document, outputs either one document (a match) or zero documents (no match)', - $ref: querySchemaUri, - }, - }, - }); - schemas.push({ - type: 'object', - properties: { - $redact: { - type: 'object', - description: - 'Reshapes each document in the stream by restricting the content for each document based on information stored in the documents themselves. Incorporates the functionality of $project and $match. Can be used to implement field level redaction. For each input document, outputs either one or zero documents', - }, - }, - }); - schemas.push({ - type: 'object', - properties: { - $limit: { - type: 'object', - description: - 'Passes the first n documents unmodified to the pipeline where n is the specified limit. For each input document, outputs either one document (for the first n documents) or zero documents (after the first n documents).', - }, - }, - }); - schemas.push({ - type: 'object', - properties: { - $skip: { - type: 'object', - description: - 'Skips the first n documents where n is the specified skip number and passes the remaining documents unmodified to the pipeline. For each input document, outputs either zero documents (for the first n documents) or one document (if after the first n documents)', - }, - }, - }); - schemas.push({ - type: 'object', - properties: { - $unwind: { - type: 'object', - description: - 'Deconstructs an array field from the input documents to output a document for each element. Each output document replaces the array with an element value. For each input document, outputs n documents where n is the number of array elements and can be zero for an empty array', - }, - }, - }); - schemas.push({ - type: 'object', - properties: { - $group: { - type: 'object', - description: - 'Groups input documents by a specified identifier expression and applies the accumulator expression(s), if specified, to each group. Consumes all input documents and outputs one document per each distinct group. The output documents only contain the identifier field and, if specified, accumulated fields.', - properties: { - _id: { - type: ['string', 'object'], - }, - }, - additionalProperties: { - type: 'object', - }, - }, - }, - }); - schemas.push({ - type: 'object', - properties: { - $sample: { - type: 'object', - description: 'Randomly selects the specified number of documents from its input', - }, - }, - }); - schemas.push({ - type: 'object', - properties: { - $sort: { - type: 'object', - description: - 'Reorders the document stream by a specified sort key. Only the order changes; the documents remain unmodified. For each input document, outputs one document.', - }, - }, - }); - schemas.push({ - type: 'object', - properties: { - $geoNear: { - type: 'object', - description: - 'Returns an ordered stream of documents based on the proximity to a geospatial point. Incorporates the functionality of $match, $sort, and $limit for geospatial data. The output documents include an additional distance field and can include a location identifier field.', - }, - }, - }); - schemas.push({ - type: 'object', - properties: { - $lookup: { - type: 'object', - description: - 'Performs a left outer join to another collection in the same database to filter in documents from the “joined” collection for processing', - }, - }, - }); - schemas.push({ - type: 'object', - properties: { - $out: { - type: 'object', - description: - 'Writes the resulting documents of the aggregation pipeline to a collection. To use the $out stage, it must be the last stage in the pipeline', - }, - }, - }); - schemas.push({ - type: 'object', - properties: { - $indexStats: { - type: 'object', - description: 'Returns statistics regarding the use of each index for the collection', - }, - }, - }); - schemas.push({ - type: 'object', - properties: { - $facet: { - type: 'object', - description: - 'Processes multiple aggregation pipelines within a single stage on the same set of input documents. Enables the creation of multi-faceted aggregations capable of characterizing data across multiple dimensions, or facets, in a single stage', - }, - }, - }); - schemas.push({ - type: 'object', - properties: { - $bucket: { - type: 'object', - description: - 'Categorizes incoming documents into groups, called buckets, based on a specified expression and bucket boundaries', - }, - }, - }); - schemas.push({ - type: 'object', - properties: { - $bucketAuto: { - type: 'object', - description: - 'Categorizes incoming documents into a specific number of groups, called buckets, based on a specified expression. Bucket boundaries are automatically determined in an attempt to evenly distribute the documents into the specified number of buckets', - }, - }, - }); - schemas.push({ - type: 'object', - properties: { - $sortByCount: { - type: 'object', - description: - 'Groups incoming documents based on the value of a specified expression, then computes the count of documents in each distinct group', - }, - }, - }); - schemas.push({ - type: 'object', - properties: { - $addFields: { - type: 'object', - description: - 'Adds new fields to documents. Outputs documents that contain all existing fields from the input documents and newly added fields', - }, - }, - }); - schemas.push({ - type: 'object', - properties: { - $replaceRoot: { - type: 'object', - description: - 'Replaces a document with the specified embedded document. The operation replaces all existing fields in the input document, including the _id field. Specify a document embedded in the input document to promote the embedded document to the top level', - }, - }, - }); - schemas.push({ - type: 'object', - properties: { - $count: { - type: 'object', - description: 'Returns a count of the number of documents at this stage of the aggregation pipeline', - }, - }, - }); - schemas.push({ - type: 'object', - properties: { - $graphLookup: { - type: 'object', - description: - 'Performs a recursive search on a collection. To each output document, adds a new array field that contains the traversal results of the recursive search for that document', - }, - }, - }); - return { - type: 'object', - oneOf: schemas, - }; - } - - private readNext( - result: any[], - cursor: FindCursor, - batchSize: number, - callback: (result: any[]) => void, - ): void { - if (result.length === batchSize) { - callback(result); - return; - } - - void cursor.hasNext().then((hasNext) => { - if (!hasNext) { - callback(result); - return; - } - - void cursor.next().then((doc) => { - result.push(doc); - this.readNext(result, cursor, batchSize, callback); - }); - }); - } -} From f82330e313a6b5d89c39e2c1a61b6cebb29fa5bc Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Fri, 20 Mar 2026 10:06:34 +0000 Subject: [PATCH 121/128] Step 5, Task 3: Remove scrapbook references from extension infrastructure - ClustersExtension.ts: remove registerScrapbookCommands import and call - extensionVariables.ts: remove MongoDBLanguageClient import and export - extension.bundle.ts: remove scrapbook exports (MongoCommand, MongoShell, ScrapbookHelpers, registerScrapbookCommands) - webpack.config.ext.js: remove language server entry point --- extension.bundle.ts | 4 ---- src/documentdb/ClustersExtension.ts | 3 --- src/extensionVariables.ts | 2 -- webpack.config.ext.js | 3 --- 4 files changed, 12 deletions(-) diff --git a/extension.bundle.ts b/extension.bundle.ts index 2c4f5314f..bae945823 100644 --- a/extension.bundle.ts +++ b/extension.bundle.ts @@ -23,15 +23,11 @@ export { AzureAccountTreeItemBase, createAzureClient } from '@microsoft/vscode-a export * from '@microsoft/vscode-azext-utils'; export { isWindows, wellKnownEmulatorPassword } from './src/constants'; export { connectToClient, isCosmosEmulatorConnectionString } from './src/documentdb/connectToClient'; -export { MongoCommand } from './src/documentdb/scrapbook/MongoCommand'; export { addDatabaseToAccountConnectionString, encodeMongoConnectionString, getDatabaseNameFromConnectionString, } from './src/documentdb/mongoConnectionStrings'; -export * from './src/documentdb/scrapbook/registerScrapbookCommands'; -export { findCommandAtPosition, getAllCommandsFromText } from './src/documentdb/scrapbook/ScrapbookHelpers'; -export { ShellScriptRunner as MongoShell } from './src/documentdb/scrapbook/ShellScriptRunner'; export { activateInternal, deactivateInternal } from './src/extension'; export { ext } from './src/extensionVariables'; export { SettingUtils } from './src/services/SettingsService'; diff --git a/src/documentdb/ClustersExtension.ts b/src/documentdb/ClustersExtension.ts index 59f9422e8..e423c4417 100644 --- a/src/documentdb/ClustersExtension.ts +++ b/src/documentdb/ClustersExtension.ts @@ -79,7 +79,6 @@ import { registerCommandWithTreeNodeUnwrappingAndModalErrors, } from '../utils/commandErrorHandling'; import { withCommandCorrelation, withTreeNodeCommandCorrelation } from '../utils/commandTelemetry'; -import { registerScrapbookCommands } from './scrapbook/registerScrapbookCommands'; import { Views } from './Views'; export class ClustersExtension implements vscode.Disposable { @@ -415,8 +414,6 @@ export class ClustersExtension implements vscode.Disposable { withTreeNodeCommandCorrelation(importDocuments), ); - registerScrapbookCommands(); - /** * Here, exporting documents is done in two ways: one is accessible from the tree view * via a context menu, and the other is accessible programmatically. Both of them diff --git a/src/extensionVariables.ts b/src/extensionVariables.ts index b4becfa62..0fdda593b 100644 --- a/src/extensionVariables.ts +++ b/src/extensionVariables.ts @@ -7,7 +7,6 @@ import { type IAzExtLogOutputChannel, type TreeElementStateManager } from '@micr import { type AzureResourcesExtensionApiWithActivity } from '@microsoft/vscode-azext-utils/activity'; import type * as vscode from 'vscode'; import { type DatabasesFileSystem } from './DatabasesFileSystem'; -import { type MongoDBLanguageClient } from './documentdb/scrapbook/languageClient'; import { type VCoreBranchDataProvider } from './tree/azure-resources-view/documentdb/VCoreBranchDataProvider'; import { type RUBranchDataProvider } from './tree/azure-resources-view/mongo-ru/RUBranchDataProvider'; import { type ClustersWorkspaceBranchDataProvider } from './tree/azure-workspace-view/ClustersWorkbenchBranchDataProvider'; @@ -28,7 +27,6 @@ export namespace ext { export let secretStorage: vscode.SecretStorage; export const prefix: string = 'documentDB'; export let fileSystem: DatabasesFileSystem; - export let mongoLanguageClient: MongoDBLanguageClient; // TODO: TN improve this: This is a temporary solution to get going. export let copiedCollectionNode: CollectionItem | undefined; diff --git a/webpack.config.ext.js b/webpack.config.ext.js index d1937b067..45c6d98eb 100644 --- a/webpack.config.ext.js +++ b/webpack.config.ext.js @@ -21,9 +21,6 @@ module.exports = (env, { mode }) => { mode: mode || 'none', node: { __filename: false, __dirname: false }, entry: { - // 'extension.bundle.ts': './src/extension.ts', // Is still necessary? - './vscode-documentdb-scrapbook-language-languageServer.bundle': - './src/documentdb/scrapbook/languageServer.ts', main: './main.ts', }, output: { From 72889bb6db468527ea29a9f5baaafaf98c78ed69 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Fri, 20 Mar 2026 10:07:03 +0000 Subject: [PATCH 122/128] Step 5, Task 4: Remove scrapbook test files Delete test/mongoShell.test.ts (ShellScriptRunner tests) and test/mongoGetCommand.test.ts (scrapbook parsing tests). --- test/mongoGetCommand.test.ts | 1170 ---------------------------------- test/mongoShell.test.ts | 308 --------- 2 files changed, 1478 deletions(-) delete mode 100644 test/mongoGetCommand.test.ts delete mode 100644 test/mongoShell.test.ts diff --git a/test/mongoGetCommand.test.ts b/test/mongoGetCommand.test.ts deleted file mode 100644 index bf34fa867..000000000 --- a/test/mongoGetCommand.test.ts +++ /dev/null @@ -1,1170 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { nonNullProp, parseError } from '@microsoft/vscode-azext-utils'; -import assert from 'assert'; -import { ObjectId } from 'bson'; -import { Position } from 'vscode'; -import { findCommandAtPosition, getAllCommandsFromText, type MongoCommand } from '../extension.bundle'; - -function expectSingleCommand(text: string): MongoCommand { - const commands = getAllCommandsFromText(text); - if (commands.length > 1) { - assert.ok(false, 'Too many commands found'); - } - - return commands[0]; -} - -function testParse( - text: string, - expectedCommand: - | { collection: string | undefined; name: string | undefined; args: any[] | undefined; firstErrorText?: string } - | undefined, -): void { - function testCore(coreText: string): void { - const command = expectSingleCommand(coreText); - if (expectedCommand) { - assert.ok(command, 'Expected a command, but found none'); - - assert.equal( - command.collection || '', - expectedCommand.collection || '', - 'Parsed collection name is not correct', - ); - assert.equal(command.name || '', expectedCommand.name || '', 'Parsed command name is not correct'); - - const actualArgs = (command.arguments || []).map((arg) => JSON.parse(arg)); - assert.deepEqual(actualArgs, expectedCommand.args || [], 'Parsed arguments are not correct'); - } else { - assert.ok(!command, 'Found a command, but expecting to find none'); - return; - } - - if (expectedCommand && expectedCommand.firstErrorText) { - assert.equal((command.errors || []).length > 0, true, 'Expected at least one error'); - assert.equal( - nonNullProp(command, 'errors')[0].message, - expectedCommand.firstErrorText, - 'First error text was incorrect', - ); - } else { - assert.equal((command.errors || []).length, 0, 'Expected no errors'); - } - } - - testCore(text); - - // Test again with LF changed to CR/LF - const crlfText = text.replace(/\n/g, '\r\n'); - testCore(crlfText); - - // Test again with LF changed to multiple CR/LF - const crlf2Text = text.replace(/\n/g, '\r\n\r\n'); - testCore(crlf2Text); - - // Test again with LF changed to CR - const lfText = text.replace(/\n/g, '\r'); - testCore(lfText); - - // Test again with LF changed to tab - const tabText = text.replace(/\n/g, '\t'); - testCore(tabText); - - // Test again with LF changed to space - const spaceText = text.replace(/\n/g, ' '); - testCore(spaceText); -} - -function wrapInQuotes(word: string, numQuotes: number): string { - //0 to do nothing, 1 for single quotes, 2 for double quotes - let result: string; - if (numQuotes === 1) { - result = `'${word}'`; - } else if (numQuotes === 2) { - result = `"${word}"`; - } else { - result = word; - } - return result; -} - -suite('scrapbook parsing Tests', () => { - test('find', () => { - const text = 'db.find()'; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.equal(command.text, text); - }); - - test('find with semicolon', () => { - const text = 'db.find();'; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.equal(command.text, text); - }); - - test('first of two commands, Mac/Linux', () => { - const line1 = 'db.find()'; - const line2 = "db.insertOne({'a': 'b'})"; - const text = `${line1}\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.equal(command.text, line1); - }); - - test('second of two commands, Mac/Linux', () => { - const line1 = 'db.find()'; - for (let q = 0; q <= 2; q++) { - const line2 = `db.insertOne({${wrapInQuotes('a', q)}:'b'})`; - const text = `${line1}\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(2, 0)); - assert.equal(command.text, line2); - } - }); - - test('second of two commands, Mac/Linux, semicolon', () => { - const line1 = 'db.find();'; - for (let q = 0; q <= 2; q++) { - const line2 = `db.insertOne({${wrapInQuotes('a', q)}:'b'})`; - const text = `${line1}\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(2, 0)); - assert.equal(command.text, line2); - } - }); - - test('first of two commands, Windows', () => { - const line1 = 'db.find()'; - const line2 = "db.insertOne({'a': 'b'})"; - const text = `${line1}\r\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.equal(command.text, line1); - }); - - test('second of two commands, Windows', () => { - const line1 = 'db.find()'; - const line2 = "db.insertOne({'a':'b'})"; - const text = `${line1}\r\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(2, 0)); - assert.equal(command.text, line2); - }); - - test('second of two commands, lots of blank lines, Windows', () => { - const line1 = 'db.find()'; - const line2 = "db.insertOne({'a':'b'})"; - const text = `\r\n\r\n\r\n\r\n\r\n\r\n${line1}\r\n\r\n\r\n\r\n\r\n\r\n${line2}\r\n\r\n\r\n\r\n\r\n\r\n`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(5, 0)); - assert.equal(command.text, line2); - }); - - test('first of two commands, Windows, on blank line before second command', () => { - const line1 = 'db.find()'; - for (let q = 0; q <= 2; q++) { - const line2 = `db.insertOne({${wrapInQuotes('a', q)}:1})`; - const text = `${line1}\r\n\r\n\r\n${line2}`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(2, 0)); - assert.equal(command.text, line1); - } - }); - - test('drop', () => { - testParse(`db.test.drop()`, { collection: 'test', name: 'drop', args: [] }); - }); - - test('find, with empty object argument', () => { - testParse(`db.test.find({})`, { collection: 'test', name: 'find', args: [{}] }); - }); - - test('end-of-line comment', () => { - testParse(`db.test.drop() // Ignore error "ns not found", it means "test" does not exist yet`, { - collection: 'test', - name: 'drop', - args: [], - }); - }); - - test('multi-line insert from #214', () => { - for (let q = 0; q <= 2; q++) { - testParse( - `db.heroes.insert({\n${wrapInQuotes('id', q)}: 2,\r\n${wrapInQuotes('name', q)}: "Batman",\r\n\r\n${wrapInQuotes('saying', q)}: "I'm Batman"\r})`, - { - collection: 'heroes', - name: 'insert', - args: [ - { - id: 2, - name: 'Batman', - saying: "I'm Batman", - }, - ], - }, - ); - } - }); - - test('find/project from #214', () => { - testParse(`db.heroes.find({ "id": 2 }, { "saying": 1 })`, { - collection: 'heroes', - name: 'find', - args: [ - { - id: 2, - }, - { - saying: 1, - }, - ], - }); - }); - - test('extraneous input', () => { - testParse( - `db.heros.find(); - hello there`, - { - collection: 'heros', - name: 'find', - args: [], - firstErrorText: - "mismatched input 'hello' expecting {, SingleLineComment, MultiLineComment, ';', 'db'}", - }, - ); - }); - - test('empty', () => { - testParse('// hello there', undefined); - }); - - test('no command found, errors (will be tacked on to a blank command)', () => { - testParse('hello there', { - collection: undefined, - name: undefined, - args: undefined, - firstErrorText: - "mismatched input 'hello' expecting {, SingleLineComment, MultiLineComment, ';', 'db'}", - }); - }); - - test('expect error: missing comma in arguments', () => { - testParse(`db.heroes.find({ "id": 2 } { "saying": 1 })`, { - collection: 'heroes', - name: 'find', - args: [ - { - id: 2, - }, - ], - firstErrorText: "mismatched input '{' expecting {',', ')'}", - }); - - testParse(`db.c.find({"a":[1,2,3]"b":1});`, { - collection: 'c', - name: 'find', - args: [{ a: [1, 2, 3] }], - firstErrorText: "mismatched input '\"b\"' expecting {',', '}'}", - }); - }); - - //https://github.com/Microsoft/vscode-cosmosdb/issues/467 - test('single quoted property names', () => { - testParse(`db.heroes.find({ 'id': 2 }, { 'saying': 1 })`, { - collection: 'heroes', - name: 'find', - args: [ - { - id: 2, - }, - { - saying: 1, - }, - ], - }); - }); - test('expect error: missing function name', () => { - // From https://github.com/Microsoft/vscode-cosmosdb/issues/659 - testParse(`db.c1.`, { - collection: 'c1', - name: '', - args: [], - firstErrorText: "mismatched input '' expecting IDENTIFIER", - }); - - testParse(`db.c1.;`, { - collection: 'c1', - name: '', - args: [], - firstErrorText: "mismatched input ';' expecting IDENTIFIER", - }); - - testParse(`db.c1.(1, "a");`, { - collection: 'c1', - name: '', - args: [1, 'a'], - firstErrorText: "missing IDENTIFIER at '('", - }); - - testParse(`..(1, "a");`, { - collection: undefined, - name: undefined, - args: undefined, - firstErrorText: "mismatched input '.' expecting {, SingleLineComment, MultiLineComment, ';', 'db'}", - }); - - // Just make sure doesn't throw - expectSingleCommand(`db..(1, "a");`); - expectSingleCommand(`..c1(1, "a");`); - }); - - test('multi-line insert from #214', () => { - testParse(`db.heroes.insert({\n"id": 2,\r\n"name": "Batman",\r\n\r\n"saying": "I'm Batman"\r})`, { - collection: 'heroes', - name: 'insert', - args: [ - { - id: 2, - name: 'Batman', - saying: "I'm Batman", - }, - ], - }); - }); - - test('Array followed by } on separate line, from #73', () => { - testParse( - `db.createUser({ - "user": "buddhi", - "pwd": "123", - "roles": ["readWrite", "dbAdmin"] - } - )`, - { - collection: undefined, - name: 'createUser', - args: [ - { - user: 'buddhi', - pwd: '123', - roles: ['readWrite', 'dbAdmin'], - }, - ], - }, - ); - }); - - test('Multiple line arrays, from #489', () => { - testParse( - ` - db.c2.insertMany([ - {"name": "Stephen", "age": 38, "male": true}, - {"name": "Stephen", "age": 38, "male": true} - ]) - `, - { - collection: 'c2', - name: 'insertMany', - args: [ - [ - { - name: 'Stephen', - age: 38, - male: true, - }, - { - name: 'Stephen', - age: 38, - male: true, - }, - ], - ], - }, - ); - }); - - test('test function call that has 2 arguments', () => { - const arg0 = `{"Age": 31}`; - const arg1 = `{"Name": true}`; - const text = `db.find(${arg0}\r\n,\r\n\r\n${arg1})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(JSON.parse(command.arguments![0]), JSON.parse(arg0)); - assert.deepEqual(JSON.parse(command.arguments![1]), JSON.parse(arg1)); - }); - test('test function call with nested parameters - documents in an array', () => { - const arg0 = `[{"name": "a"}, {"name": "b"}, {"name": "c"}]`; - const arg1 = `{"ordered": true}`; - const text = `db.test1.insertMany(${arg0},\r\n\r\n\r\n${arg1})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(JSON.parse(command.arguments![0]), JSON.parse(arg0)); - assert.deepEqual(JSON.parse(command.arguments![1]), JSON.parse(arg1)); - }); - test('test function call that has a nested parameter', () => { - const arg0 = `{"name": {"First" : "a", "Last":"b"} }`; - const text = `db.test1.insertMany(${arg0})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(JSON.parse(command.arguments![0]), JSON.parse(arg0)); - }); - test('test function call with erroneous syntax: missing comma', () => { - const arg0 = `{"name": {"First" : "a", "Last":"b"} }`; - const arg1 = `{"ordered": true}`; - const text = `db.test1.insertMany(${arg0} ${arg1})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const err = nonNullProp(command, 'errors')[0]; - assert.deepEqual(err.message, "mismatched input '{' expecting {',', ')'}"); - assert.deepEqual(err.range.start.line, 0); - assert.deepEqual(err.range.start.character, 61); - }); - test('test function call with erroneous syntax: missing comma, parameters separated with newline', () => { - const arg0 = `{"name": {"First" : "a", "Last":"b"} }`; - const arg1 = `{"ordered": \ntrue}`; - const text = `db.test1.insertMany(${arg0} \n ${arg1})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const err = nonNullProp(command, 'errors')[0]; - assert.deepEqual(err.message, "mismatched input '{' expecting {',', ')'}"); - assert.deepEqual(err.range.start.line, 1); - assert.deepEqual(err.range.start.character, 2); - }); - test('test function call with erroneous syntax: missing double quote', () => { - const text = `db.test1.insertMany({name": {"First" : "a", "Last":"b"} })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const err = nonNullProp(command, 'errors')[0]; - assert.deepEqual(err.message, "missing ':' at '\": {\"'"); - assert.deepEqual(err.range.start.line, 0); - assert.deepEqual(err.range.start.character, 25); - }); - test('test function call with erroneous syntax: missing opening brace', () => { - const text = `db.test1.insertMany("name": {"First" : "a", "Last":"b"} })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const err = nonNullProp(command, 'errors')[0]; - assert.deepEqual(err.message, "mismatched input ':' expecting {',', ')'}"); - assert.deepEqual(err.range.start.line, 0); - assert.deepEqual(err.range.start.character, 26); - }); - - test('Chained command: to use pretty()', () => { - testParse('db.timesheets.find().pretty();', { - collection: 'timesheets', - name: 'pretty', - args: [], - }); - }); - - test('ISODate with standard date string', () => { - testParse( - 'db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": ISODate("2018-05-01T00:00:00Z") });', - { - collection: 'c1', - name: 'insertOne', - args: [ - { - _id: { - $oid: '5aecf1a63d8af732f07e4275', - }, - date: { - $date: '2018-05-01T00:00:00.000Z', - }, - name: 'Stephen', - }, - ], - }, - ); - }); - - test('ISODate without Z in date string', () => { - testParse( - 'db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": ISODate("2018-05-01T00:00:00") });', - { - collection: 'c1', - name: 'insertOne', - args: [ - { - _id: { - $oid: '5aecf1a63d8af732f07e4275', - }, - date: { - $date: '2018-05-01T00:00:00.000Z', - }, - name: 'Stephen', - }, - ], - }, - ); - }); - - test('Invalid ISODate', () => { - testParse( - 'db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": ISODate("2018-05-01T00:00:00z") });', - { - collection: 'c1', - name: 'insertOne', - args: [], - firstErrorText: 'Invalid time value', - }, - ); - }); - - test('Date', () => { - const date: Date = new Date('2018-05-01T00:00:00'); - testParse( - `db.c1.insertOne({ "_id": ObjectId("5aecf1a63d8af732f07e4275"), "name": "Stephen", "date": Date("${date.toUTCString()}") });`, - { - collection: 'c1', - name: 'insertOne', - args: [ - { - _id: { - $oid: '5aecf1a63d8af732f07e4275', - }, - date: { - $date: date.toString(), - }, - name: 'Stephen', - }, - ], - }, - ); - }); - - test('Keys with periods', () => { - testParse( - `db.timesheets.update( { - "year":"2018", - "month":"06" - },{ - "$set":{ - "workers.0.days.0.something":"yupy!" - } - }); - `, - { - collection: 'timesheets', - name: 'update', - args: [ - { - year: 2018, - month: '06', - }, - { - $set: { - 'workers.0.days.0.something': 'yupy!', - }, - }, - ], - }, - ); - }); - - test('nested objects', () => { - testParse( - `db.users.update({},{ - "$pull":{ - "proposals":{ - "$elemMatch":{"_id":"4qsBHLDCb755c3vPH"} - } - } - })`, - { - collection: 'users', - name: 'update', - args: [ - {}, - { - $pull: { - proposals: { - $elemMatch: { - _id: '4qsBHLDCb755c3vPH', - }, - }, - }, - }, - ], - }, - ); - }); - test('test function call with and without quotes', () => { - for (let q = 0; q <= 2; q++) { - const text = `db.test1.insertMany({${wrapInQuotes('name', q)}: 'First' })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: 'First' }]); - } - }); - test('test function call with numbers', () => { - const text = `db.test1.insertMany({'name': 1010101})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: 1010101 }]); - }); - test('test function call boolean', () => { - const text = `db.test1.insertMany({'name': false})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: false }]); - }); - test('test function call token inside quotes', () => { - const text = `db.test1.insertMany({'name': 'false'})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: 'false' }]); - }); - test('test function call with an empty string property value', () => { - const text = `db.test1.insertMany({'name': ''})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: '' }]); - }); - test('test function call with array and multiple arguments', () => { - const text = `db.test1.find({'roles': ['readWrite', 'dbAdmin']}, {'resources': ['secondary', 'primary']})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [ - { roles: ['readWrite', 'dbAdmin'] }, - { resources: ['secondary', 'primary'] }, - ]); - }); - test('test function call with nested objects', () => { - const text = `db.test1.find({'roles': [{'optional': 'yes'}]}, {'resources': ['secondary', 'primary']})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [ - { roles: [{ optional: 'yes' }] }, - { resources: ['secondary', 'primary'] }, - ]); - }); - - test('test incomplete function call - replicate user typing - no function call yet', () => { - const text = `db.test1.`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, []); - assert.deepEqual(command.collection, 'test1'); - }); - - test('test incomplete function call - replicate user typing - missing propertyValue', () => { - const text = `db.test1.find({"name": {"First" : } })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: { First: {} } }]); - }); - - test('test incomplete function call - replicate user typing - missing colon & propertyValue', () => { - const text = `db.test1.find({"name": {"First" } })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ name: { First: {} } }]); - }); - - test('test incomplete function call - replicate user typing - empty array as argument', () => { - const text = `db.heroes.aggregate([\n])`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [[]]); - }); - - test('test quotes inside a string - 1', () => { - const text = `db.test1.find("That's all")`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, ["That's all"]); - }); - - test('test quotes inside a string - 2', () => { - const text = `db.test1.find('That"s all')`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, ['That"s all']); - }); - - // Note: when escaping a character, escape it twice. - test('test quotes inside a string - 3', () => { - const text = `db.test1.find("Hello \\"there\\"")`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, ['Hello \\"there\\"']); - }); - - test('test quotes inside a string - 4', () => { - const text = `db.test1.find('Hello \\'there\\'')`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, ["Hello \\'there\\'"]); - }); - - test('test nested property names (has dots in the name)', () => { - const text = `db.test1.find({"name.FirstName": 1})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.argumentObjects, [{ 'name.FirstName': 1 }]); - }); - - test('test managed namespace collection names (has dots in the name)', () => { - const text = `db.test1.beep.find({})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, 'test1.beep'); - }); - - test('test aggregate query', () => { - for (let q = 0; q <= 2; q++) { - const text = `db.orders.aggregate([ - { ${wrapInQuotes('$match', q)}: { ${wrapInQuotes('status', q)} : "A" } }, - { ${wrapInQuotes('$group', q)}: { ${wrapInQuotes('_id', q)}: "$cust_id", ${wrapInQuotes('total', q)}: { ${wrapInQuotes('$sum', q)}: "$amount" } } }, - { ${wrapInQuotes('$sort', q)}: { ${wrapInQuotes('total', q)}: -1 } } - ], - { - ${wrapInQuotes('cursor', q)}: { ${wrapInQuotes('batchSize', q)}: 0 } - })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, 'orders'); - assert.deepEqual(command.argumentObjects, [ - [ - { $match: { status: 'A' } }, - { $group: { _id: '$cust_id', total: { $sum: '$amount' } } }, - { $sort: { total: -1 } }, - ], - { - cursor: { batchSize: 0 }, - }, - ]); - } - }); - - test('test ObjectID - no parameter', () => { - const text = `db.c1.insert({"name": ObjectId()})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, 'c1'); - assert.ok((nonNullProp(command, 'argumentObjects')[0]).name instanceof ObjectId); - }); - - test('test ObjectID - hex', () => { - const idParam = 'abcdef123456789012345678'; - const text = `db.c1.insert({"name": ObjectId("${idParam}")})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, 'c1'); - const id = new ObjectId(idParam); - assert.deepEqual(command.argumentObjects, [{ name: id }]); - }); - - test('test faulty ObjectID - hex - extra characters', () => { - const idParam = 'abcdef12345678901234567890'; - const text = `db.c1.insert({"name": ObjectId("${idParam}")})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, 'c1'); - assert.deepEqual(command.argumentObjects, [{ name: {} }]); - assert.notStrictEqual(nonNullProp(command, 'errors')[0]?.message, undefined); - }); - - test('test faulty ObjectID - hex - fewer characters', () => { - const idParam = 'abcdef123456789012345'; - for (let i = 1; i < 3; i++) { - const text = `db.c1.insert({"name": ObjectId(${wrapInQuotes(idParam, i)})})`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, 'c1'); - assert.deepEqual(command.argumentObjects, [{ name: {} }]); - assert.notStrictEqual(nonNullProp(command, 'errors')[0]?.message, undefined); - } - }); - //Examples inspired from https://docs.mongodb.com/manual/reference/operator/query/regex/ - test('test regular expressions - only pattern, no flags', () => { - const text = `db.test1.beep.find({ sku: /789$/ })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.options, ''); - assert.deepEqual(generatedRegExp.pattern, '789$'); - }); - - test('test regular expressions - pattern and flags', () => { - const text = `db.test1.beep.find({ sku: /789$/i } )`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.options, 'i'); - assert.deepEqual(generatedRegExp.pattern, '789$'); - }); - - test('test regular expressions - Intellisense - flag contains unsupported option', () => { - const text = `db.test1.beep.find({ sku: /789$/g })`; - try { - const commands: MongoCommand[] = getAllCommandsFromText(text); - findCommandAtPosition(commands, new Position(0, 0)); - } catch (error) { - const err = parseError(error); - assert.deepEqual('Unexpected node encountered', err.message); - } - }); - - test('test regular expressions - Intellisense - flag contains invalid option', () => { - const text = `db.test1.beep.find({ sku: /789$/q })`; - try { - const commands: MongoCommand[] = getAllCommandsFromText(text); - findCommandAtPosition(commands, new Position(0, 0)); - } catch (error) { - const err = parseError(error); - assert.deepEqual('Unexpected node encountered', err.message); - } - }); - - test('test regular expressions - wrong escape - throw error', () => { - const text = `db.test1.beep.find({ sku: /789$\\/b\\/q })`; - try { - const commands: MongoCommand[] = getAllCommandsFromText(text); - findCommandAtPosition(commands, new Position(0, 0)); - } catch (error) { - assert.equal(error.message, 'Invalid regular expression: /789$\\/b\\/: \\ at end of pattern'); - } - }); - - //Passing the following test should imply the rest of the tests pass too. - // The regex parsing tests following this test should help zero-in on which case isn't handled properly. - test('test regular expression parsing - with many special cases', () => { - const text = `db.test1.beep.find({ sku: /^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$/ })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.options, ''); - assert.deepEqual(generatedRegExp.pattern, '^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$'); - }); - - test('test regular expression parsing EJSON syntax - with many special cases', () => { - const text = `db.test1.beep.find({ sku: {$regex: "^(hello?= world).*[^0-9]+|(world\\\\b\\\\*){0,2}$"} })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.options, ''); - assert.deepEqual(generatedRegExp.pattern, '^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$'); - }); - - test('test regular expression parsing interoperability', () => { - const text1 = `db.test1.beep.find({ sku: /^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$/ })`; - const commands1: MongoCommand[] = getAllCommandsFromText(text1); - const command1: MongoCommand = findCommandAtPosition(commands1, new Position(0, 0)); - const generatedRegExp1 = (nonNullProp(command1, 'argumentObjects')[0]).sku; - const text2 = `db.test1.beep.find({ sku: {$regex: "^(hello?= world).*[^0-9]+|(world\\\\b\\\\*){0,2}$"} })`; - const commands2: MongoCommand[] = getAllCommandsFromText(text2); - const command2: MongoCommand = findCommandAtPosition(commands2, new Position(0, 0)); - const generatedRegExp2 = (nonNullProp(command2, 'argumentObjects')[0]).sku; - assert.deepEqual( - [generatedRegExp1.options, generatedRegExp1.pattern], - ['', '^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$'], - ); - assert.deepEqual( - [generatedRegExp2.options, generatedRegExp2.pattern], - ['', '^(hello?= world).*[^0-9]+|(world\\b\\*){0,2}$'], - ); - }); - - test('test regular expression parsing interoperability - word break', () => { - const text1 = `db.test1.beep.find({ sku: /ker\\b/ })`; // equivalent to user typing out /ker\b/ - const commands1: MongoCommand[] = getAllCommandsFromText(text1); - const command1: MongoCommand = findCommandAtPosition(commands1, new Position(0, 0)); - const generatedRegExp1 = (nonNullProp(command1, 'argumentObjects')[0]).sku; - const text2 = `db.test1.beep.find({ sku: {$regex: "ker\\\\b"} })`; - const commands2: MongoCommand[] = getAllCommandsFromText(text2); - const command2: MongoCommand = findCommandAtPosition(commands2, new Position(0, 0)); - const generatedRegExp2 = (nonNullProp(command2, 'argumentObjects')[0]).sku; - assert.deepEqual([generatedRegExp1.options, generatedRegExp1.pattern], ['', 'ker\\b']); - assert.deepEqual([generatedRegExp2.options, generatedRegExp2.pattern], ['', 'ker\\b']); - }); - - test('test regular expression parsing interoperability - newline', () => { - const text1 = `db.test1.beep.find({ sku: /ker\\n/ })`; // equivalent to user typing out /ker\n/ - const commands1: MongoCommand[] = getAllCommandsFromText(text1); - const command1: MongoCommand = findCommandAtPosition(commands1, new Position(0, 0)); - const generatedRegExp1 = (nonNullProp(command1, 'argumentObjects')[0]).sku; - const text2 = `db.test1.beep.find({ sku: {$regex: "ker\\\\n"} })`; - const commands2: MongoCommand[] = getAllCommandsFromText(text2); - const command2: MongoCommand = findCommandAtPosition(commands2, new Position(0, 0)); - const generatedRegExp2 = (nonNullProp(command2, 'argumentObjects')[0]).sku; - assert.deepEqual([generatedRegExp2.options, generatedRegExp2.pattern], ['', 'ker\\n']); - assert.deepEqual([generatedRegExp1.options, generatedRegExp1.pattern], ['', 'ker\\n']); - }); - test('test regular expression parsing interoperability - carriage return', () => { - const text1 = `db.test1.beep.find({ sku: /ker\\r/ })`; // equivalent to user typing out /ker\r/ - const commands1: MongoCommand[] = getAllCommandsFromText(text1); - const command1: MongoCommand = findCommandAtPosition(commands1, new Position(0, 0)); - const generatedRegExp1 = (nonNullProp(command1, 'argumentObjects')[0]).sku; - const text2 = `db.test1.beep.find({ sku: {$regex: "ker\\\\r"} })`; - const commands2: MongoCommand[] = getAllCommandsFromText(text2); - const command2: MongoCommand = findCommandAtPosition(commands2, new Position(0, 0)); - const generatedRegExp2 = (nonNullProp(command2, 'argumentObjects')[0]).sku; - assert.deepEqual([generatedRegExp1.options, generatedRegExp1.pattern], ['', 'ker\\r']); - assert.deepEqual([generatedRegExp2.options, generatedRegExp2.pattern], ['', 'ker\\r']); - }); - - test('test regular expressions - only pattern, no flags', () => { - const text = `db.test1.beep.find({ sku: { $regex: "789$" } })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.options, ''); - assert.deepEqual(generatedRegExp.pattern, '789$'); - }); - - test('test regular expressions - pattern and flags', () => { - const text = `db.test1.beep.find({ sku: { $regex: "789$", $options:"i" } })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.options, 'i'); - assert.deepEqual(generatedRegExp.pattern, '789$'); - }); - - test('test regular expressions - Intellisense - flag contains invalid option', () => { - const text = `db.test1.beep.find({ sku: { $regex: "789$", $options:"q" } })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.notStrictEqual(nonNullProp(command, 'errors')[0]?.message, undefined); - assert.deepEqual(nonNullProp(command, 'errors')[0].range.start.character, 19); - }); - - test('test regular expression parsing - with groupings', () => { - const text = `db.test1.beep.find({ sku: /(?:hello)\\3/ })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.options, ''); - assert.deepEqual(generatedRegExp.pattern, '(?:hello)\\3'); - }); - - test('test regular expression parsing - with special characters', () => { - const text = `db.test1.beep.find({ sku: /(hello)*(world)?(name)+./ })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.options, ''); - assert.deepEqual(generatedRegExp.pattern, '(hello)*(world)?(name)+.'); - }); - - test('test regular expression parsing - with boundaries', () => { - const text = `db.test1.beep.find({ sku: /^(hello world)[^0-9]|(world\\b)$/ })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.options, ''); - assert.deepEqual(generatedRegExp.pattern, '^(hello world)[^0-9]|(world\\b)$'); - }); - - test('test regular expression parsing - with quantifiers', () => { - const text = `db.test1.beep.find({ sku: /(hello)*[^0-9]+|(world){0,2}./ })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.options, ''); - assert.deepEqual(generatedRegExp.pattern, '(hello)*[^0-9]+|(world){0,2}.'); - }); - - test('test regular expression parsing - with conditional', () => { - const text = `db.test1.beep.find({ sku: /(hello?= world)|(world)/ })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.options, ''); - assert.deepEqual(generatedRegExp.pattern, '(hello?= world)|(world)'); - }); - - test('test regular expression parsing - with escaped special characters', () => { - const text = `db.test1.beep.find({ sku: /world\\*\\.\\?\\+/ })`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - const generatedRegExp = (nonNullProp(command, 'argumentObjects')[0]).sku; - assert.deepEqual(generatedRegExp.options, ''); - assert.deepEqual(generatedRegExp.pattern, 'world\\*\\.\\?\\+'); - }); - - test('test chained command: argument aggregation', () => { - testParse('db.timesheets.find({name: "Andy", surname: "Jackson"}).pretty();', { - collection: 'timesheets', - name: 'pretty', - args: [{ name: 'Andy', surname: 'Jackson' }], - }); - }); - - test('Chained command - order of parsed arguments', () => { - testParse('db.timesheets.find({name:"Andy"}).sort({age: 1}).skip(40);', { - collection: 'timesheets', - name: 'skip', - args: [{ name: 'Andy' }, { age: 1 }, 40], - }); - }); - - test('Chained command - missing period', () => { - testParse('db.timesheets.find({name:"Andy"}).sort({age: 1})skip(40);', { - collection: 'timesheets', - name: 'sort', - args: [{ name: 'Andy' }, { age: 1 }], - firstErrorText: - "mismatched input 'skip' expecting {, SingleLineComment, MultiLineComment, ';', '.', 'db'}", - }); - }); - - test('Chained command - mid-type - missing bracket', () => { - testParse('db.timesheets.find({name:"Andy"}).sort', { - collection: 'timesheets', - name: 'sort', - args: [{ name: 'Andy' }], - firstErrorText: "mismatched input '' expecting '('", - }); - }); - - test('Chained command - mid-type - typed the dot, but not the function call', () => { - testParse('db.timesheets.find({name:"Andy"}).', { - collection: 'timesheets', - name: '', - args: [{ name: 'Andy' }], - firstErrorText: "mismatched input '' expecting IDENTIFIER", - }); - }); - - //TODO: Tests to simulate cases where the user hasn't completed typing - - test('test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/688', () => { - for (let q = 0; q <= 2; q++) { - const text = `db.hdr.aggregate([ - { ${wrapInQuotes('$match', q)}: { "CURRENCY_ID": "USD" } }, - ])`; //Note the trailing comma. There should be 1 argument object returned, an array, that has 2 elements - //one expected, and another empty object. - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, 'hdr'); - assert.deepEqual(command.argumentObjects, [[{ $match: { CURRENCY_ID: 'USD' } }, {}]]); - } - }); - - test('Chained command- test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/785', () => { - testParse('db.timesheets.find({name:"Andy"}).count();', { - collection: 'timesheets', - name: 'count', - args: [{ name: 'Andy' }], - }); - }); - - test('Chained command- test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/795', () => { - testParse('db.timesheets.find({}).limit(10);', { - collection: 'timesheets', - name: 'limit', - args: [{}, 10], - }); - }); - - test('Chained command alternative for rs.slaveOk()- test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/565', () => { - testParse('db.getMongo().setSlaveOk();', { - collection: '', - name: 'setSlaveOk', - args: [], - }); - }); - - test('Multiple line command, from #489', () => { - testParse( - ` - db.finalists.find({name: "Jefferson"}) - . - limit - (10); - `, - { - collection: 'finalists', - name: 'limit', - args: [ - { - name: 'Jefferson', - }, - 10, - ], - }, - ); - }); - - test('test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/703', () => { - for (let q = 0; q <= 2; q++) { - const text = `db.Users.find({ ${wrapInQuotes('user', q)}: { ${wrapInQuotes('$in', q)}: [ "A80", "HPA" ] } },{ ${wrapInQuotes('_id', q)}: false });`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, 'Users'); - assert.deepEqual(command.argumentObjects, [{ user: { $in: ['A80', 'HPA'] } }, { _id: false }]); - } - }); - - test('test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/691', () => { - for (let q = 0; q <= 2; q++) { - const text = `db.users.aggregate([ - { ${wrapInQuotes('$match', q)}: {${wrapInQuotes('_id', q)}: {"$oid" :"5b23d2ba92b52cf794bdeb9c")}}}, - { ${wrapInQuotes('$project', q)}: { - ${wrapInQuotes('scores', q)}: {${wrapInQuotes('$filter', q)}: { - ${wrapInQuotes('input', q)}: '$scores', - ${wrapInQuotes('as', q)}: 'score', - ${wrapInQuotes('cond', q)}: {${wrapInQuotes('$gt', q)}: ['$$score', 3]} - }} - }} - ])`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, 'users'); - assert.deepEqual(nonNullProp(command, 'argumentObjects')[0][0], { - $match: { _id: new ObjectId('5b23d2ba92b52cf794bdeb9c') }, - }); - assert.deepEqual(nonNullProp(command, 'argumentObjects')[0][1], { - $project: { - scores: { - $filter: { - input: '$scores', - as: 'score', - cond: { $gt: ['$$score', 3] }, - }, - }, - }, - }); - } - }); - - test('test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/717', () => { - for (let q = 0; q <= 2; q++) { - const text = `db.Users.find({${wrapInQuotes('age', q)} : { ${wrapInQuotes('$in', q)} : [19, 20, 22, 25]}});`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, 'Users'); - assert.deepEqual(command.argumentObjects, [{ age: { $in: [19, 20, 22, 25] } }]); - } - }); - - test('test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/737', () => { - const text = `db.c1.insert({},f)`; - const commands: MongoCommand[] = getAllCommandsFromText(text); - const command: MongoCommand = findCommandAtPosition(commands, new Position(0, 0)); - assert.deepEqual(command.collection, 'c1'); - assert.deepEqual(command.argumentObjects, [{}, {}]); - assert.deepEqual( - nonNullProp(command, 'errors')[0].message, - "mismatched input 'f' expecting {'{', '[', RegexLiteral, StringLiteral, 'null', BooleanLiteral, NumericLiteral}", - ); - }); - - test('test user issues: https://github.com/Microsoft/vscode-cosmosdb/issues/899 - multi-line comment, not regex', () => { - for (const escape of ['\n', '\r', '\n\r', '\r\n']) { - const text = `db.heroes.count()${escape}/*db.c2.insertMany([${escape}{"name": "Stephen", "age": 38, "male": true},${escape}{"name": "Stephen", "age": 38, "male": true}${escape}]);${escape}*/${escape}${escape}db.heroes.find();`; - const commands = getAllCommandsFromText(text); - assert.equal(commands.length, 2, `Error in parsing ${text}`); - assert.equal(commands[0].name, 'count'); - assert.equal(commands[1].name, 'find'); - } - }); -}); diff --git a/test/mongoShell.test.ts b/test/mongoShell.test.ts deleted file mode 100644 index 4f258e14c..000000000 --- a/test/mongoShell.test.ts +++ /dev/null @@ -1,308 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -// CONSIDER: Run in pipeline -import { AzExtFsExtra, parseError } from '@microsoft/vscode-azext-utils'; -import assert from 'assert'; -import * as cp from 'child_process'; -import * as os from 'os'; -import * as path from 'path'; -import type * as vscode from 'vscode'; -import { ext, isWindows, type IDisposable } from '../extension.bundle'; -import { ShellScriptRunner } from '../src/documentdb/scrapbook/ShellScriptRunner'; -import { runWithSetting } from './runWithSetting'; -import { setEnvironmentVariables } from './util/setEnvironmentVariables'; - -const VERBOSE = false; // If true, the output from the Mongo server and shell will be sent to the console for debugging purposes - -let testsSupported: boolean = true; - -if (!isWindows) { - // CONSIDER: Non-Windows - console.warn(`Not running in Windows - skipping MongoShell tests`); - testsSupported = false; -} - -suite('MongoShell', async function (this: Mocha.Suite): Promise { - // https://github.com/mochajs/mocha/issues/2025 - this.timeout(10000); - - async function testIfSupported(title: string, fn?: Mocha.Func | Mocha.AsyncFunc): Promise { - await runWithSetting(ext.settingsKeys.shellTimeout, '60', async () => { - if (testsSupported) { - test(title, fn); - } else { - test(title); - } - }); - } - - // CONSIDER: Make more generic - let mongodCP: cp.ChildProcess; - const mongodPath = 'c:\\Program Files\\MongoDB\\Server\\4.2\\bin\\mongod.exe'; - const mongoPath = 'c:\\Program Files\\MongoDB\\Server\\4.2\\bin\\mongo.exe'; - let mongoDOutput = ''; - let mongoDErrors = ''; - let isClosed = false; - - if (!(await AzExtFsExtra.pathExists(mongodPath))) { - console.log(`Couldn't find mongod.exe at ${mongodPath} - skipping MongoShell tests`); - testsSupported = false; - } else if (!(await AzExtFsExtra.pathExists(mongodPath))) { - console.log(`Couldn't find mongo.exe at ${mongoPath} - skipping MongoShell tests`); - testsSupported = false; - } else { - // Prevent code 100 error: https://stackoverflow.com/questions/41420466/mongodb-shuts-down-with-code-100 - await AzExtFsExtra.ensureDir('D:\\data\\db\\'); - } - - class FakeOutputChannel implements vscode.OutputChannel { - public name: string; - public output: string; - - public append(value: string): void { - assert(value !== undefined); - assert(!value.includes('undefined')); - this.output = this.output ? this.output + os.EOL + value : value; - log(value, 'Output channel: '); - } - public appendLine(value: string): void { - assert(value !== undefined); - this.append(value + os.EOL); - } - public clear(): void {} - public show(preserveFocus?: boolean): void; - public show(column?: vscode.ViewColumn, preserveFocus?: boolean): void; - public show(_column?: any, _preserveFocus?: any): void {} - public hide(): void {} - public dispose(): void {} - public replace(_value: string): void {} - } - - function log(text: string, linePrefix: string): void { - text = text.replace(/(^|[\r\n]+)/g, '$1' + linePrefix); - if (VERBOSE) { - console.log(text); - } - } - - async function delay(milliseconds: number): Promise { - return new Promise((resolve) => { - setTimeout(resolve, milliseconds); - }); - } - - function executeInShell(command: string): string { - return cp.execSync(command, {}).toString(); - } - - suiteSetup(async () => { - if (testsSupported) { - assert(await AzExtFsExtra.pathExists(mongodPath), "Couldn't find mongod.exe at " + mongodPath); - assert(await AzExtFsExtra.pathExists(mongoPath), "Couldn't find mongo.exe at " + mongoPath); - - // Shut down any still-running mongo server - try { - executeInShell('taskkill /f /im mongod.exe'); - } catch (error) { - assert( - /The process .* not found/.test(parseError(error).message), - `Error killing mongod: ${parseError(error).message}`, - ); - } - - mongodCP = cp.spawn(mongodPath, ['--quiet']); - - mongodCP.stdout?.on('data', (buffer: Buffer) => { - log(buffer.toString(), 'mongo server: '); - mongoDOutput += buffer.toString(); - }); - mongodCP.stderr?.on('data', (buffer: Buffer) => { - log(buffer.toString(), 'mongo server STDERR: '); - mongoDErrors += buffer.toString(); - }); - mongodCP.on('error', (error: unknown) => { - log(parseError(error).message, 'mongo server Error: '); - mongoDErrors += parseError(error).message + os.EOL; - }); - mongodCP.on('close', (code?: number) => { - console.log(`mongo server: Close code=${code}`); - isClosed = true; - if (typeof code === 'number' && code !== 0) { - mongoDErrors += `mongo server: Closed with code "${code}"${os.EOL}`; - } - }); - } - }); - - suiteTeardown(() => { - if (mongodCP) { - mongodCP.kill(); - } - }); - - await testIfSupported('Verify mongod running', async () => { - while (!mongoDOutput.includes('waiting for connections on port 27017')) { - assert.equal(mongoDErrors, '', 'Expected no errors'); - assert(!isClosed); - await delay(50); - } - }); - - async function testShellCommand(options: { - script: string; - expectedResult?: string; - expectedError?: string | RegExp; - expectedOutput?: RegExp; - title?: string; // Defaults to script - args?: string[]; // Defaults to [] - mongoPath?: string; // Defaults to the correct mongo path - env?: { [key: string]: string }; // Add to environment - timeoutSeconds?: number; - }): Promise { - await testIfSupported(options.title || options.script, async () => { - assert(!isClosed); - assert(mongoDErrors === ''); - - let previousEnv: IDisposable | undefined; - let shell: ShellScriptRunner | undefined; - const outputChannel = new FakeOutputChannel(); - - try { - previousEnv = setEnvironmentVariables(options.env || {}); - shell = await ShellScriptRunner.createShellProcessHelper( - options.mongoPath || mongoPath, - options.args || [], - '', - outputChannel, - options.timeoutSeconds || 5, - { isEmulator: false, disableEmulatorSecurity: false }, - ); - const result = await shell.executeScript(options.script); - if (options.expectedError) { - assert(false, `Expected error did not occur: '${options.expectedError}'`); - } - if (options.expectedResult !== undefined) { - assert.equal(result, options.expectedResult); - } - } catch (error) { - const message = parseError(error).message; - - if (options.expectedError instanceof RegExp) { - assert( - options.expectedError.test(message), - `Actual error did not match expected error regex. Actual error: ${message}`, - ); - } else if (typeof options.expectedError === 'string') { - assert.equal(message, options.expectedError); - } else { - assert(false, `Unexpected error during the test: ${message}`); - } - - if (options.expectedOutput instanceof RegExp) { - assert( - options.expectedOutput.test(outputChannel.output), - `Actual contents written to output channel did not match expected regex. Actual output channel contents: ${outputChannel.output}`, - ); - } - } finally { - if (shell) { - shell.dispose(); - } - if (previousEnv) { - previousEnv.dispose(); - } - } - }); - } - - await testShellCommand({ - script: 'use abc', - expectedResult: 'switched to db abc', - }); - - await testShellCommand({ - title: 'Incorrect path', - script: 'use abc', - mongoPath: '/notfound/mongo.exe', - expectedError: /Could not find .*notfound.*mongo.exe/, - }); - - await testShellCommand({ - title: 'Find mongo through PATH', - script: 'use abc', - mongoPath: 'mongo', - expectedResult: 'switched to db abc', - env: { - PATH: process.env.path! + ';' + path.dirname(mongoPath), - }, - }); - - await testShellCommand({ - title: 'With valid argument', - script: 'use abc', - args: ['--quiet'], - expectedResult: 'switched to db abc', - }); - - await testShellCommand({ - title: 'With invalid argument', - script: '', - args: ['--hey-man-how-are-you'], - expectedError: /Error parsing command line: unrecognised option/, - }); - - await testShellCommand({ - title: 'Output window may contain additional information', - script: '', - args: ['-u', 'baduser', '-p', 'badpassword'], - expectedError: /The output window may contain additional information/, - }); - - await testShellCommand({ - title: 'With bad credentials', - script: '', - args: ['-u', 'baduser', '-p', 'badpassword'], - expectedError: /The process exited with code 1/, - expectedOutput: /Authentication failed/, - }); - - await testShellCommand({ - title: 'Process exits immediately', - script: '', - args: ['--version'], - expectedError: /The process exited prematurely/, - }); - - await testShellCommand({ - title: 'Javascript', - script: 'for (var i = 0; i < 123; ++i) { }; i', - expectedResult: '123', - }); - - await testShellCommand({ - title: 'Actual timeout', - script: 'for (var i = 0; i < 10000000; ++i) { }; i', - expectedError: - /Timed out trying to execute the Mongo script. To use a longer timeout, modify the VS Code 'mongo.shell.timeout' setting./, - timeoutSeconds: 2, - }); - - await testIfSupported("More results than displayed (type 'it' for more -> (More))", async () => { - const shell = await ShellScriptRunner.createShellProcessHelper(mongoPath, [], '', new FakeOutputChannel(), 5, { - disableEmulatorSecurity: false, - isEmulator: false, - }); - await shell.executeScript('db.mongoShellTest.drop()'); - await shell.executeScript('for (var i = 0; i < 50; ++i) { db.mongoShellTest.insert({a:i}); }'); - - const result = await shell.executeScript('db.mongoShellTest.find().pretty()'); - - assert(!result.includes('Type "it" for more')); - assert(result.includes('(More)')); - - shell.dispose(); - }); -}); From 2a3a931e2325c250c93ddd07631180023b717589 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Fri, 20 Mar 2026 10:08:38 +0000 Subject: [PATCH 123/128] Step 5, Task 5: Remove scrapbook contributions from package.json Remove language registration, grammar registration, 4 scrapbook commands, 2 submenus, submenu menu entries, editor/context entries, command palette hiding entries, and 2 keybindings. --- package.json | 139 ++------------------------------------------------- 1 file changed, 5 insertions(+), 134 deletions(-) diff --git a/package.json b/package.json index 2577d0f69..87b224c39 100644 --- a/package.json +++ b/package.json @@ -246,29 +246,8 @@ "contents": "Discover DocumentDB clusters across your cloud providers. Activate discovery to explore and manage your databases.\n[$(search) Activate Service Discovery](command:vscode-documentdb.command.discoveryView.addRegistry)\nClick the button above to get started and to start discovering your databases." } ], - "languages": [ - { - "id": "vscode-documentdb-scrapbook-language", - "aliases": [ - "DocumentDB Scrapbook" - ], - "extensions": [ - ".vscode-documentdb-scrapbook" - ], - "configuration": "./grammar/configuration.json" - } - ], - "grammars": [ - { - "language": "vscode-documentdb-scrapbook-language", - "scopeName": "source.mongo.js", - "path": "./grammar/JavaScript.tmLanguage.json" - }, - { - "scopeName": "source.mongo.js.regexp", - "path": "./grammar/Regular Expressions (JavaScript).tmLanguage" - } - ], + "languages": [], + "grammars": [], "commands": [ { "//": "[ConnectionsView] New Connection", @@ -436,31 +415,6 @@ "command": "vscode-documentdb.command.createDatabase", "title": "Create Database…" }, - { - "//": "Scrapbook: Connect Database", - "category": "DocumentDB", - "command": "vscode-documentdb.command.scrapbook.connect", - "title": "Connect to this database" - }, - { - "//": "Scrapbook: Execute All Commands", - "category": "DocumentDB", - "command": "vscode-documentdb.command.scrapbook.executeAllCommands", - "title": "Execute All Commands" - }, - { - "//": "Scrapbook: Execute Command", - "category": "DocumentDB", - "command": "vscode-documentdb.command.scrapbook.executeCommand", - "title": "Execute Command" - }, - { - "//": "Scrapbook: New Scrapbook", - "category": "DocumentDB", - "command": "vscode-documentdb.command.scrapbook.new", - "title": "New DocumentDB Scrapbook", - "icon": "$(new-file)" - }, { "//": "Delete Collection", "category": "DocumentDB", @@ -546,41 +500,8 @@ "title": "Paste Collection…" } ], - "submenus": [ - { - "id": "documentDB.submenus.mongo.database.scrapbook", - "label": "DocumentDB Scrapbook" - }, - { - "id": "documentDB.submenus.mongo.collection.scrapbook", - "label": "DocumentDB Scrapbook" - } - ], + "submenus": [], "menus": { - "documentDB.submenus.mongo.database.scrapbook": [ - { - "//": "[Database] Scrapbook: New Scrapbook", - "command": "vscode-documentdb.command.scrapbook.new", - "group": "1@1" - }, - { - "//": "[Database] Scrapbook: Connect", - "command": "vscode-documentdb.command.scrapbook.connect", - "group": "1@2" - } - ], - "documentDB.submenus.mongo.collection.scrapbook": [ - { - "//": "[Collection] Mongo DB|Cluster Scrapbook New", - "command": "vscode-documentdb.command.scrapbook.new", - "group": "1@1" - }, - { - "//": "[Collection] Scrapbook / Connect", - "command": "vscode-documentdb.command.scrapbook.connect", - "group": "1@2" - } - ], "view/title": [ { "command": "vscode-documentdb.command.connectionsView.refresh", @@ -608,16 +529,7 @@ "group": "navigation@5" } ], - "editor/context": [ - { - "command": "vscode-documentdb.command.scrapbook.executeAllCommands", - "when": "resourceLangId==mongo" - }, - { - "command": "vscode-documentdb.command.scrapbook.executeCommand", - "when": "resourceLangId==mongo" - } - ], + "editor/context": [], "editor/title": [], "view/item/context": [ { @@ -774,12 +686,6 @@ "when": "view =~ /connectionsView|discoveryView|azure(ResourceGroups|FocusView)/ && viewItem =~ /\\btreeitem_database\\b/i && viewItem =~ /\\bexperience_(documentDB|mongoRU)\\b/i", "group": "3@1" }, - { - "//": "[Database] Mongo DB|Cluster Scrapbook Submenu", - "submenu": "documentDB.submenus.mongo.database.scrapbook", - "when": "view =~ /connectionsView|discoveryView|azure(ResourceGroups|FocusView)/ && viewItem =~ /\\btreeitem_database\\b/i && viewItem =~ /\\bexperience_(documentDB|mongoRU)\\b/i", - "group": "3@2" - }, { "//": "[Collection] Mongo DB|Cluster Open collection", "command": "vscode-documentdb.command.containerView.open", @@ -840,12 +746,6 @@ "when": "view =~ /connectionsView|discoveryView|azure(ResourceGroups|FocusView)/ && viewItem =~ /\\btreeitem_collection\\b/i && viewItem =~ /\\bexperience_(documentDB|mongoRU)\\b/i", "group": "5@1" }, - { - "//": "[Collection] Mongo DB|Cluster Scrapbook Submenu", - "submenu": "documentDB.submenus.mongo.collection.scrapbook", - "when": "view =~ /connectionsView|discoveryView|azure(ResourceGroups|FocusView)/ && viewItem =~ /\\btreeitem_collection\\b/i && viewItem =~ /\\bexperience_(documentDB|mongoRU)\\b/i", - "group": "5@2" - }, { "//": "[Collection/Documents] Mongo DB|Cluster Open collection", "command": "vscode-documentdb.command.containerView.open", @@ -994,39 +894,10 @@ { "command": "vscode-documentdb.command.containerView.open", "when": "never" - }, - { - "command": "vscode-documentdb.command.scrapbook.new", - "when": "never" - }, - { - "command": "vscode-documentdb.command.scrapbook.connect", - "when": "never" - }, - { - "command": "vscode-documentdb.command.scrapbook.executeAllCommands", - "when": "never" - }, - { - "command": "vscode-documentdb.command.scrapbook.executeCommand", - "when": "never" } ] }, - "keybindings": [ - { - "command": "vscode-documentdb.command.scrapbook.executeCommand", - "key": "ctrl+shift+'", - "mac": "cmd+shift+'", - "when": "editorLangId == 'vscode-documentdb-scrapbook-language' && editorTextFocus" - }, - { - "command": "vscode-documentdb.command.scrapbook.executeAllCommands", - "key": "ctrl+shift+;", - "mac": "cmd+shift+;", - "when": "editorLangId == 'vscode-documentdb-scrapbook-language' && editorTextFocus" - } - ], + "keybindings": [], "configuration": [ { "title": "DocumentDB for VS Code", From c6bd7044af492f41b3f179eb0e2b950b6290d80a Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Fri, 20 Mar 2026 10:09:35 +0000 Subject: [PATCH 124/128] Step 5, Task 6: Remove scrapbook-only npm dependencies Remove antlr4ts, antlr4ts-cli, vscode-json-languageservice, vscode-languageclient, vscode-languageserver, and vscode-languageserver-textdocument. Also remove the update-grammar npm script. --- package.json | 7 ------- 1 file changed, 7 deletions(-) diff --git a/package.json b/package.json index 87b224c39..a2d687e35 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,6 @@ "test": "vscode-test", "prejesttest": "npm run build --workspaces --if-present", "jesttest": "jest", - "update-grammar": "antlr4ts -visitor ./grammar/mongo.g4 -o src/documentdb/grammar", "webpack-dev": "rimraf ./dist && npm run webpack-dev-ext && npm run webpack-dev-wv", "webpack-prod": "rimraf ./dist && npm run webpack-prod-ext && npm run webpack-prod-wv", "webpack-dev-ext": "webpack --mode development --config ./webpack.config.ext.js", @@ -113,7 +112,6 @@ "@vscode/test-cli": "~0.0.12", "@vscode/test-electron": "~2.5.2", "@vscode/vsce": "~3.7.0", - "antlr4ts-cli": "^0.5.0-alpha.4", "copy-webpack-plugin": "~13.0.1", "cross-env": "~7.0.3", "css-loader": "~7.1.2", @@ -175,7 +173,6 @@ "@vscode/l10n": "~0.0.18", "acorn": "^8.16.0", "acorn-walk": "^8.3.5", - "antlr4ts": "^0.5.0-alpha.4", "bson": "~7.0.0", "denque": "~2.1.0", "es-toolkit": "~1.42.0", @@ -187,10 +184,6 @@ "regenerator-runtime": "^0.14.1", "semver": "~7.7.3", "slickgrid-react": "~9.9.0", - "vscode-json-languageservice": "~5.6.2", - "vscode-languageclient": "~9.0.1", - "vscode-languageserver": "~9.0.1", - "vscode-languageserver-textdocument": "~1.0.12", "vscode-uri": "~3.1.0", "zod": "~4.1.12" }, From c00bd365b96e7661c8fb5b71b1ee03e27d017fb7 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Fri, 20 Mar 2026 10:12:30 +0000 Subject: [PATCH 125/128] Step 5, Tasks 7-8: Regenerate l10n, update lockfile, verify build - Regenerate l10n bundle (37 scrapbook strings removed) - Update package-lock.json (11 packages removed) - Build, lint, prettier, and all 57 test suites pass --- l10n/bundle.l10n.json | 37 -------------- package-lock.json | 115 +----------------------------------------- 2 files changed, 2 insertions(+), 150 deletions(-) diff --git a/l10n/bundle.l10n.json b/l10n/bundle.l10n.json index 59a69f54b..8ea852199 100644 --- a/l10n/bundle.l10n.json +++ b/l10n/bundle.l10n.json @@ -111,11 +111,7 @@ "{experienceName} Emulator": "{experienceName} Emulator", "**No public IP or FQDN available for direct connection.**": "**No public IP or FQDN available for direct connection.**", "/ (Root)": "/ (Root)", - "⏩ Run All": "⏩ Run All", - "⏳ Running All…": "⏳ Running All…", - "⏳ Running Command…": "⏳ Running Command…", "■ Task '{taskName}' was stopped. {message}": "■ Task '{taskName}' was stopped. {message}", - "▶️ Run Command": "▶️ Run Command", "► Task '{taskName}' starting...": "► Task '{taskName}' starting...", "○ Task '{taskName}' initializing...": "○ Task '{taskName}' initializing...", "⚠️ **Security:** TLS/SSL Disabled": "⚠️ **Security:** TLS/SSL Disabled", @@ -142,10 +138,6 @@ "$(warning) Some storage accounts were filtered because of their network configurations.": "$(warning) Some storage accounts were filtered because of their network configurations.", "1 tenant available (0 signed in)": "1 tenant available (0 signed in)", "1 tenant available (1 signed in)": "1 tenant available (1 signed in)", - "1. Locating the one you'd like from the DocumentDB side panel,": "1. Locating the one you'd like from the DocumentDB side panel,", - "2. Selecting a database or a collection,": "2. Selecting a database or a collection,", - "3. Right-clicking and then choosing the \"Mongo Scrapbook\" submenu,": "3. Right-clicking and then choosing the \"Mongo Scrapbook\" submenu,", - "4. Selecting the \"Connect to this database\" command.": "4. Selecting the \"Connect to this database\" command.", "A collection with the name \"{0}\" already exists": "A collection with the name \"{0}\" already exists", "A connection name is required.": "A connection name is required.", "A connection with the same username and host already exists.": "A connection with the same username and host already exists.", @@ -217,7 +209,6 @@ "Back": "Back", "Back to account selection": "Back to account selection", "Back to tenant selection": "Back to tenant selection", - "Browse to {mongoExecutableFileName}": "Browse to {mongoExecutableFileName}", "Bulk write error during import into \"{0}.{1}\": {2} document(s) inserted.": "Bulk write error during import into \"{0}.{1}\": {2} document(s) inserted.", "Cancel": "Cancel", "Cancel this operation": "Cancel this operation", @@ -266,8 +257,6 @@ "Configuring subscription filtering…": "Configuring subscription filtering…", "Configuring tenant filtering…": "Configuring tenant filtering…", "Conflict Resolution: {strategyName}": "Conflict Resolution: {strategyName}", - "Connect to a database": "Connect to a database", - "Connected to \"{name}\"": "Connected to \"{name}\"", "Connected to the cluster \"{cluster}\".": "Connected to the cluster \"{cluster}\".", "Connecting to the cluster as \"{username}\"…": "Connecting to the cluster as \"{username}\"…", "Connecting to the cluster using Entra ID…": "Connecting to the cluster using Entra ID…", @@ -425,18 +414,14 @@ "Examined-to-Returned Ratio": "Examined-to-Returned Ratio", "Excellent": "Excellent", "Execute the find query": "Execute the find query", - "Executing all commands in shell…": "Executing all commands in shell…", "Executing explain(aggregate) for collection: {collection}, pipeline stages: {stageCount}": "Executing explain(aggregate) for collection: {collection}, pipeline stages: {stageCount}", "Executing explain(count) for collection: {collection}": "Executing explain(count) for collection: {collection}", "Executing explain(find) for collection: {collection}": "Executing explain(find) for collection: {collection}", - "Executing the command in shell…": "Executing the command in shell…", "Execution Strategy": "Execution Strategy", "Execution Time": "Execution Time", "Execution timed out": "Execution timed out", "Execution timed out.": "Execution timed out.", "Exit": "Exit", - "Expected a file name \"{0}\", but the selected filename is \"{1}\"": "Expected a file name \"{0}\", but the selected filename is \"{1}\"", - "Expecting parentheses or quotes at \"{text}\"": "Expecting parentheses or quotes at \"{text}\"", "Explain(aggregate) completed [{durationMs}ms]": "Explain(aggregate) completed [{durationMs}ms]", "Explain(count) completed [{durationMs}ms]": "Explain(count) completed [{durationMs}ms]", "Explain(find) completed [{durationMs}ms]": "Explain(find) completed [{durationMs}ms]", @@ -680,8 +665,6 @@ "Modify index?": "Modify index?", "Modify Index…": "Modify Index…", "Modifying index visibility ({action}) for \"{indexName}\" on collection: {collection}": "Modifying index visibility ({action}) for \"{indexName}\" on collection: {collection}", - "Mongo Shell connected.": "Mongo Shell connected.", - "Mongo Shell Error: {error}": "Mongo Shell Error: {error}", "MongoDB Emulator": "MongoDB Emulator", "Monitor Index Usage": "Monitor Index Usage", "Move": "Move", @@ -709,7 +692,6 @@ "No Azure VMs found with tag \"{tagName}\" in subscription \"{subscriptionName}\".": "No Azure VMs found with tag \"{tagName}\" in subscription \"{subscriptionName}\".", "No collection has been marked for copy. Please use \"Copy Collection...\" first to select a source collection.": "No collection has been marked for copy. Please use \"Copy Collection...\" first to select a source collection.", "No collection selected.": "No collection selected.", - "No commands found in this document.": "No commands found in this document.", "No Connectivity": "No Connectivity", "No credentials found for id {clusterId}": "No credentials found for id {clusterId}", "No credentials found for the selected cluster.": "No credentials found for the selected cluster.", @@ -721,7 +703,6 @@ "No node selected.": "No node selected.", "No parent folder selected.": "No parent folder selected.", "No public connectivity": "No public connectivity", - "No result returned from the MongoDB shell.": "No result returned from the MongoDB shell.", "No results found": "No results found", "No scope was provided for the role assignment.": "No scope was provided for the role assignment.", "No session found for id {sessionId}": "No session found for id {sessionId}", @@ -734,7 +715,6 @@ "No tenants selected. Tenant filtering disabled (all tenants will be shown).": "No tenants selected. Tenant filtering disabled (all tenants will be shown).", "No, only copy documents": "No, only copy documents", "None": "None", - "Not connected to any MongoDB database.": "Not connected to any MongoDB database.", "Note: This confirmation type can be configured in the extension settings.": "Note: This confirmation type can be configured in the extension settings.", "Note: You can disable these URL handling confirmations in the extension settings.": "Note: You can disable these URL handling confirmations in the extension settings.", "Number of documents returned by the query": "Number of documents returned by the query", @@ -742,7 +722,6 @@ "Number of index keys scanned during query execution. Lower is better.": "Number of index keys scanned during query execution. Lower is better.", "OK": "OK", "Open Collection": "Open Collection", - "Open installation page": "Open installation page", "Open the VS Code Marketplace to learn more about \"{0}\"": "Open the VS Code Marketplace to learn more about \"{0}\"", "Opening DocumentDB connection…": "Opening DocumentDB connection…", "Operation cancelled.": "Operation cancelled.", @@ -761,7 +740,6 @@ "Pick \"{number}\" to confirm and continue.": "Pick \"{number}\" to confirm and continue.", "Please authenticate first by expanding the tree item of the selected cluster.": "Please authenticate first by expanding the tree item of the selected cluster.", "Please confirm by re-entering the previous value.": "Please confirm by re-entering the previous value.", - "Please connect to a MongoDB database before running a Scrapbook command.": "Please connect to a MongoDB database before running a Scrapbook command.", "Please edit the connection string.": "Please edit the connection string.", "Please enter a new connection name.": "Please enter a new connection name.", "Please enter a valid tenant ID in GUID format (e.g., 12345678-1234-1234-1234-123456789012 or 12345678123412341234123456789012)": "Please enter a valid tenant ID in GUID format (e.g., 12345678-1234-1234-1234-123456789012 or 12345678123412341234123456789012)", @@ -843,7 +821,6 @@ "Saving credentials for \"{clusterName}\"…": "Saving credentials for \"{clusterName}\"…", "See output for more details.": "See output for more details.", "Select {0}": "Select {0}", - "Select {mongoExecutableFileName}": "Select {mongoExecutableFileName}", "Select a location for new resources.": "Select a location for new resources.", "Select a tenant for Microsoft Entra ID authentication": "Select a tenant for Microsoft Entra ID authentication", "Select a workspace folder": "Select a workspace folder", @@ -979,8 +956,6 @@ "The name can only contain lowercase letters and numbers.": "The name can only contain lowercase letters and numbers.", "The name cannot end in a period.": "The name cannot end in a period.", "The name must be between {0} and {1} characters.": "The name must be between {0} and {1} characters.", - "The output window may contain additional information.": "The output window may contain additional information.", - "The process exited prematurely.": "The process exited prematurely.", "The selected authentication method is not supported.": "The selected authentication method is not supported.", "The selected connection has been removed.": "The selected connection has been removed.", "The selected folder has been removed.": "The selected folder has been removed.", @@ -995,7 +970,6 @@ "This cannot be undone.": "This cannot be undone.", "This field is not set": "This field is not set", "This functionality requires installing the Azure Account extension.": "This functionality requires installing the Azure Account extension.", - "This functionality requires the Mongo DB shell, but we could not find it in the path or using the documentDB.mongoShell.path setting.": "This functionality requires the Mongo DB shell, but we could not find it in the path or using the documentDB.mongoShell.path setting.", "This functionality requires updating the Azure Account extension to at least version \"{0}\".": "This functionality requires updating the Azure Account extension to at least version \"{0}\".", "This index on {0} is not being used and adds unnecessary overhead to write operations.": "This index on {0} is not being used and adds unnecessary overhead to write operations.", "This operation is not supported as it would create a circular dependency and never terminate. Please select a different target collection or database.": "This operation is not supported as it would create a circular dependency and never terminate. Please select a different target collection or database.", @@ -1008,19 +982,14 @@ "This will allow the query planner to use this index again.": "This will allow the query planner to use this index again.", "This will also delete {0}.": "This will also delete {0}.", "This will prevent the query planner from using this index.": "This will prevent the query planner from using this index.", - "Timed out trying to execute the Mongo script. To use a longer timeout, modify the VS Code 'mongo.shell.timeout' setting.": "Timed out trying to execute the Mongo script. To use a longer timeout, modify the VS Code 'mongo.shell.timeout' setting.", "To connect to Azure resources, you need to sign in to Azure accounts.": "To connect to Azure resources, you need to sign in to Azure accounts.", "TODO: Share the steps needed to reliably reproduce the problem. Please include actual and expected results.": "TODO: Share the steps needed to reliably reproduce the problem. Please include actual and expected results.", - "Too many arguments. Expecting 0 or 1 argument(s) to {constructorCall}": "Too many arguments. Expecting 0 or 1 argument(s) to {constructorCall}", "Total documents to import: {0}": "Total documents to import: {0}", "Total time taken to execute the query on the server": "Total time taken to execute the query on the server", "Transforming Stage 2 response to UI format": "Transforming Stage 2 response to UI format", "Tree View": "Tree View", - "Try again": "Try again", - "Type \"it\" for more": "Type \"it\" for more", "Unable to connect to the local database instance. Make sure it is started correctly. See {link} for tips.": "Unable to connect to the local database instance. Make sure it is started correctly. See {link} for tips.", "Unable to connect to the local instance. Make sure it is started correctly. See {link} for tips.": "Unable to connect to the local instance. Make sure it is started correctly. See {link} for tips.", - "Unable to parse syntax near line {line}, col {column}: {message}": "Unable to parse syntax near line {line}, col {column}: {message}", "Unable to retrieve credentials for cluster \"{cluster}\".": "Unable to retrieve credentials for cluster \"{cluster}\".", "Unable to retrieve credentials for the selected cluster.": "Unable to retrieve credentials for the selected cluster.", "Understanding Your Query Execution Plan": "Understanding Your Query Execution Plan", @@ -1038,9 +1007,6 @@ "Unknown query generation type: {type}": "Unknown query generation type: {type}", "Unknown strategy": "Unknown strategy", "Unknown tenant": "Unknown tenant", - "Unrecognized node type encountered. Could not parse {constructorCall} as part of {functionCall}": "Unrecognized node type encountered. Could not parse {constructorCall} as part of {functionCall}", - "Unrecognized node type encountered. We could not parse {text}": "Unrecognized node type encountered. We could not parse {text}", - "Unrecognized token. Token text: {text}": "Unrecognized token. Token text: {text}", "Unsupported authentication mechanism. Only \"Username and Password\" (SCRAM-SHA-256) is supported.": "Unsupported authentication mechanism. Only \"Username and Password\" (SCRAM-SHA-256) is supported.", "Unsupported authentication mechanism. Only SCRAM-SHA-256 (username/password) is supported.": "Unsupported authentication mechanism. Only SCRAM-SHA-256 (username/password) is supported.", "Unsupported authentication method: {0}": "Unsupported authentication method: {0}", @@ -1057,7 +1023,6 @@ "Updated entity \"{name}\".": "Updated entity \"{name}\".", "Upload": "Upload", "URL handling aborted. Connection was unsuccessful or the specified database/collection does not exist.": "URL handling aborted. Connection was unsuccessful or the specified database/collection does not exist.", - "Use anyway": "Use anyway", "Use projection to return only necessary fields. This reduces network transfer and memory usage, especially important for documents with large embedded arrays or binary data.": "Use projection to return only necessary fields. This reduces network transfer and memory usage, especially important for documents with large embedded arrays or binary data.", "Username and Password": "Username and Password", "Username cannot be empty": "Username cannot be empty", @@ -1103,11 +1068,9 @@ "You are already signed in to tenant \"{0}\"": "You are already signed in to tenant \"{0}\"", "You are not signed in to an Azure account. Please sign in.": "You are not signed in to an Azure account. Please sign in.", "You are not signed in to the MongoDB Cluster. Please sign in (by expanding the node \"{0}\") and try again.": "You are not signed in to the MongoDB Cluster. Please sign in (by expanding the node \"{0}\") and try again.", - "You can connect to a different DocumentDB by:": "You can connect to a different DocumentDB by:", "You clicked a link that wants to open a DocumentDB connection in VS Code.": "You clicked a link that wants to open a DocumentDB connection in VS Code.", "You do not have permission to create a resource group in subscription \"{0}\".": "You do not have permission to create a resource group in subscription \"{0}\".", "You might be asked for credentials to establish the connection.\nDo you want to continue?\n\nNote: You can disable these URL handling confirmations in the extension settings.": "You might be asked for credentials to establish the connection.\nDo you want to continue?\n\nNote: You can disable these URL handling confirmations in the extension settings.", - "You must open a *.vscode-documentdb-scrapbook file to run commands.": "You must open a *.vscode-documentdb-scrapbook file to run commands.", "You need to provide the password for \"{username}\" in order to continue. Your password will not be stored.": "You need to provide the password for \"{username}\" in order to continue. Your password will not be stored.", "You're attempting to copy a large number of documents. This process can be slow because it downloads all documents from the source to your computer and then uploads them to the destination, which can take a significant amount of time and bandwidth.\n\nFor larger data migrations, we recommend using a dedicated migration tool for a faster experience.\n\nNote: You can disable this warning or adjust the document count threshold in the extension settings.": "You're attempting to copy a large number of documents. This process can be slow because it downloads all documents from the source to your computer and then uploads them to the destination, which can take a significant amount of time and bandwidth.\n\nFor larger data migrations, we recommend using a dedicated migration tool for a faster experience.\n\nNote: You can disable this warning or adjust the document count threshold in the extension settings.", "Your Cluster": "Your Cluster", diff --git a/package-lock.json b/package-lock.json index 8a951e8fb..89b9b6cc7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,7 +35,6 @@ "@vscode/l10n": "~0.0.18", "acorn": "^8.16.0", "acorn-walk": "^8.3.5", - "antlr4ts": "^0.5.0-alpha.4", "bson": "~7.0.0", "denque": "~2.1.0", "es-toolkit": "~1.42.0", @@ -47,10 +46,6 @@ "regenerator-runtime": "^0.14.1", "semver": "~7.7.3", "slickgrid-react": "~9.9.0", - "vscode-json-languageservice": "~5.6.2", - "vscode-languageclient": "~9.0.1", - "vscode-languageserver": "~9.0.1", - "vscode-languageserver-textdocument": "~1.0.12", "vscode-uri": "~3.1.0", "zod": "~4.1.12" }, @@ -74,7 +69,6 @@ "@vscode/test-cli": "~0.0.12", "@vscode/test-electron": "~2.5.2", "@vscode/vsce": "~3.7.0", - "antlr4ts-cli": "^0.5.0-alpha.4", "copy-webpack-plugin": "~13.0.1", "cross-env": "~7.0.3", "css-loader": "~7.1.2", @@ -8223,22 +8217,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/antlr4ts": { - "version": "0.5.0-alpha.4", - "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz", - "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==", - "license": "BSD-3-Clause" - }, - "node_modules/antlr4ts-cli": { - "version": "0.5.0-alpha.4", - "resolved": "https://registry.npmjs.org/antlr4ts-cli/-/antlr4ts-cli-0.5.0-alpha.4.tgz", - "integrity": "sha512-lVPVBTA2CVHRYILSKilL6Jd4hAumhSZZWA7UbQNQrmaSSj7dPmmYaN4bOmZG79cOy0lS00i4LY68JZZjZMWVrw==", - "dev": true, - "license": "BSD-3-Clause", - "bin": { - "antlr4ts": "antlr4ts" - } - }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -8608,6 +8586,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, "license": "MIT" }, "node_modules/bare-events": { @@ -8877,15 +8856,6 @@ "dev": true, "license": "BSD-2-Clause" }, - "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", @@ -14444,6 +14414,7 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, "license": "MIT" }, "node_modules/jsonfile": { @@ -21160,88 +21131,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/vscode-json-languageservice": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-5.6.3.tgz", - "integrity": "sha512-UDF7sJF5t7mzUzXL6dsClkvnHS4xnDL/gOMKGQiizRHmswlk/xSPGZxEvAtszWQF0ImNcJ0j9l+rHuefGzit1w==", - "license": "MIT", - "dependencies": { - "@vscode/l10n": "^0.0.18", - "jsonc-parser": "^3.3.1", - "vscode-languageserver-textdocument": "^1.0.12", - "vscode-languageserver-types": "^3.17.5", - "vscode-uri": "^3.1.0" - } - }, - "node_modules/vscode-jsonrpc": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", - "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/vscode-languageclient": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz", - "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==", - "license": "MIT", - "dependencies": { - "minimatch": "^5.1.0", - "semver": "^7.3.7", - "vscode-languageserver-protocol": "3.17.5" - }, - "engines": { - "vscode": "^1.82.0" - } - }, - "node_modules/vscode-languageclient/node_modules/minimatch": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.8.tgz", - "integrity": "sha512-7RN35vit8DeBclkofOVmBY0eDAZZQd1HzmukRdSyz95CRh8FT54eqnbj0krQr3mrHR6sfRyYkyhwBWjoV5uqlQ==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/vscode-languageserver": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", - "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", - "license": "MIT", - "dependencies": { - "vscode-languageserver-protocol": "3.17.5" - }, - "bin": { - "installServerIntoExtension": "bin/installServerIntoExtension" - } - }, - "node_modules/vscode-languageserver-protocol": { - "version": "3.17.5", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", - "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", - "license": "MIT", - "dependencies": { - "vscode-jsonrpc": "8.2.0", - "vscode-languageserver-types": "3.17.5" - } - }, - "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", - "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", - "license": "MIT" - }, - "node_modules/vscode-languageserver-types": { - "version": "3.17.5", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", - "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", - "license": "MIT" - }, "node_modules/vscode-tas-client": { "version": "0.1.84", "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.84.tgz", From 804d03cdd87380c8c66eaa653d175d5730f636df Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Fri, 20 Mar 2026 12:20:23 +0000 Subject: [PATCH 126/128] fix: remove stale grammar copy pattern and dangling resolve alias from webpack config Remove CopyWebpackPlugin pattern copying deleted grammar/ directory (caused webpack-prod-ext to fail). Also remove unused vscode-languageserver-types resolve alias (package no longer in deps). --- webpack.config.ext.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/webpack.config.ext.js b/webpack.config.ext.js index 45c6d98eb..d2dad889e 100644 --- a/webpack.config.ext.js +++ b/webpack.config.ext.js @@ -65,12 +65,6 @@ module.exports = (env, { mode }) => { // conditionNames: ['import', 'require', 'node'], // Uncomment when we will use VSCode what supports modules mainFields: ['module', 'main'], extensions: ['.js', '.ts'], - alias: { - 'vscode-languageserver-types': path.resolve( - __dirname, - 'node_modules/vscode-languageserver-types/lib/esm/main.js', - ), - }, }, module: { rules: [ @@ -113,10 +107,6 @@ module.exports = (env, { mode }) => { // - The dist folder should be ready to be published to the marketplace and be only one working folder new CopyWebpackPlugin({ patterns: [ - { - from: 'grammar', - to: 'grammar', - }, { from: 'l10n', to: 'l10n', From 71954fa162900a1511caa14d172e3c4a566825f6 Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Fri, 20 Mar 2026 12:21:09 +0000 Subject: [PATCH 127/128] fix: update CredScan suppression paths after scrapbook removal - Remove deleted test/mongoGetCommand.test.ts entry - Update src/documentdb/scrapbook/mongoConnectionStrings.test.ts to src/documentdb/mongoConnectionStrings.test.ts (relocated) --- .azure-pipelines/compliance/CredScanSuppressions.json | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.azure-pipelines/compliance/CredScanSuppressions.json b/.azure-pipelines/compliance/CredScanSuppressions.json index 4408537b4..ca021f1e5 100644 --- a/.azure-pipelines/compliance/CredScanSuppressions.json +++ b/.azure-pipelines/compliance/CredScanSuppressions.json @@ -6,11 +6,7 @@ "_justification": "No need to scan external node modules." }, { - "file": "test\\mongoGetCommand.test.ts", - "_justification": "Fake credentials used for unit tests." - }, - { - "file": "src\\documentdb\\scrapbook\\mongoConnectionStrings.test.ts", + "file": "src\\documentdb\\mongoConnectionStrings.test.ts", "_justification": "Fake credentials used for unit tests." }, { From d5c78f365a29c3ba56f0d357a9d1aea6e3fbb83d Mon Sep 17 00:00:00 2001 From: Tomasz Naumowicz Date: Fri, 20 Mar 2026 12:22:09 +0000 Subject: [PATCH 128/128] fix: remove stale scrapbook references from README and settings - README: remove scrapbook prerequisite link and escaped chars known issue; update shell requirement to reference mongosh - package.json: update documentDB.mongoShell.path description to remove 'DocumentDB Scrapbook commands' reference --- README.md | 4 +--- package.json | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a3210a85d..69fdfc50f 100644 --- a/README.md +++ b/README.md @@ -44,14 +44,12 @@ Your feedback, contributions, and ideas shape the future of the extension. # Prerequisites -- **Mongo Shell Requirement (Optional)**: Some advanced commands in the Mongo [scrapbook](#mongo-scrapbooks), as well as use of the MongoDB shell, require installing [MongoDB shell](https://docs.mongodb.com/manual/installation/). +- **Shell Requirement (Optional)**: Use of the DocumentDB shell requires installing [mongosh](https://www.mongodb.com/docs/mongodb-shell/install/). ## Known Issues Here are some known issues and limitations to be aware of when using the DocumentDB VS Code extension: -- **Escaped Characters in Scrapbooks**: Scrapbook support for escaped characters is preliminary. Use double escaping for newlines (`\\n` instead of `\n`). - #### References diff --git a/package.json b/package.json index a2d687e35..1d8d07245 100644 --- a/package.json +++ b/package.json @@ -952,7 +952,7 @@ "string", "null" ], - "description": "Full path to folder and executable to start the Mongo shell, needed by some DocumentDB Scrapbook commands. The default is to search in the system path for 'mongosh'.", + "description": "Full path to folder and executable to start the Mongo shell. The default is to search in the system path for 'mongosh'.", "default": null }, "documentDB.mongoShell.args": {