@sdk-it/core 0.22.1 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/deriver.test.js +4 -10
- package/dist/lib/deriver.test.js.map +2 -2
- package/dist/lib/program.test.js +9 -13
- package/dist/lib/program.test.js.map +2 -2
- package/dist/lib/ref.d.ts +1 -1
- package/dist/lib/ref.d.ts.map +1 -1
- package/dist/lib/ref.js.map +2 -2
- package/dist/lib/utils.d.ts +1 -0
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +5 -2
- package/dist/lib/utils.js.map +3 -3
- package/package.json +1 -1
package/dist/lib/deriver.test.js
CHANGED
|
@@ -267,11 +267,8 @@ describe("serializeNode: Interface Declarations (`interface ...`) and Collector
|
|
|
267
267
|
() => {
|
|
268
268
|
}
|
|
269
269
|
);
|
|
270
|
-
it.todo(
|
|
271
|
-
|
|
272
|
-
() => {
|
|
273
|
-
}
|
|
274
|
-
);
|
|
270
|
+
it.todo("throws an error for an interface declaration without a name", () => {
|
|
271
|
+
});
|
|
275
272
|
it.todo(
|
|
276
273
|
"handles interfaces with no members correctly (adds empty object to collector)",
|
|
277
274
|
() => {
|
|
@@ -379,10 +376,7 @@ describe("serializeNode: Other Node Types", () => {
|
|
|
379
376
|
() => {
|
|
380
377
|
}
|
|
381
378
|
);
|
|
382
|
-
it.todo(
|
|
383
|
-
|
|
384
|
-
() => {
|
|
385
|
-
}
|
|
386
|
-
);
|
|
379
|
+
it.todo("handles an unhandled node kind by returning `any` and warns", () => {
|
|
380
|
+
});
|
|
387
381
|
});
|
|
388
382
|
//# sourceMappingURL=deriver.test.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/deriver.test.ts"],
|
|
4
|
-
"sourcesContent": ["import { describe, it } from 'node:test';\n\n// --- serializeType Functionality ---\n\ndescribe('serializeType: Basic Primitive and Special Types', () => {\n it.todo('serializes `any` type to an empty type list', () => {\n // Input: ts.Type with TypeFlags.Any\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [] }\n });\n it.todo('serializes `unknown` type to an empty type list', () => {\n // Input: ts.Type with TypeFlags.Unknown\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [] }\n });\n it.todo('serializes `string` type', () => {\n // Input: ts.Type with TypeFlags.String\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['string'] }\n });\n it.todo('serializes `number` type', () => {\n // Input: ts.Type with TypeFlags.Number\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['number'] }\n });\n it.todo('serializes `boolean` type', () => {\n // Input: ts.Type with TypeFlags.Boolean\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['boolean'] }\n });\n it.todo('serializes `null` type as optional', () => {\n // Input: ts.Type with TypeFlags.Null\n // Output: { [deriveSymbol]: true, optional: true, [$types]: ['null'] }\n });\n it.todo(\n 'serializes `void` type (likely falls back to Any/Unknown or unhandled)',\n () => {\n // Input: ts.Type with TypeFlags.Void (or VoidLike)\n // Determine expected output based on how TS checker presents this type and how the unhandled path works. Likely results in `[$types]: []` or `[$types]: ['void']`.\n },\n );\n it.todo(\n 'serializes `never` type (likely falls back to Any/Unknown or unhandled)',\n () => {\n // Input: ts.Type with TypeFlags.Never\n // Determine expected output. Likely results in `[$types]: []` or `[$types]: ['never']`.\n },\n );\n it.todo(\n 'serializes `undefined` type implicitly via union/intersection optional flag',\n () => {\n // Note: Undefined itself isn't directly serialized as a standalone type by this logic.\n // Its presence in unions/intersections correctly sets the `optional` flag. Tests are under Union/Intersection sections.\n },\n );\n});\n\ndescribe('serializeType: Literal Types', () => {\n it.todo('serializes string literal types with their value', () => {\n // Input: ts.StringLiteralType (e.g., type of \"constant\")\n // Output: { [deriveSymbol]: true, optional: false, kind: 'literal', value: 'constant', [$types]: ['string'] }\n });\n it.todo('serializes numeric literal types with their value', () => {\n // Input: ts.NumberLiteralType (e.g., type of 123)\n // Output: { [deriveSymbol]: true, optional: false, kind: 'literal', value: 123, [$types]: ['number'] }\n });\n it.todo('serializes boolean literal `true` type', () => {\n // Input: ts.BooleanLiteralType (true) checked via TypeFlags.BooleanLiteral\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['boolean'] }\n // Note: Current code identifies it's boolean but doesn't store the literal `true` value.\n });\n it.todo('serializes boolean literal `false` type', () => {\n // Input: ts.BooleanLiteralType (false) checked via TypeFlags.BooleanLiteral\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['boolean'] }\n // Note: Current code identifies it's boolean but doesn't store the literal `false` value.\n });\n it.todo('serializes template literal types as base `string`', () => {\n // Input: ts.Type with TypeFlags.TemplateLiteral (e.g. type of `ID-${number}`)\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['string'] }\n });\n // Note: BigIntLiteral is not explicitly handled, would fall under unhandled.\n});\n\ndescribe('serializeType: Enum Types', () => {\n it.todo(\n 'serializes an Enum type (e.g., `enum Color {}`) potentially via unhandled path',\n () => {\n // Input: ts.Type with TypeFlags.Enum (representing the enum itself, e.g., `Color`)\n // Expect it to fall into the unhandled path, likely using checker.typeToString.\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['Color'] } or similar based on typeToString. Check console warning.\n },\n );\n it.todo(\n 'serializes an EnumLiteral type (e.g., `Color.Red`) potentially via unhandled path or base type',\n () => {\n // Input: ts.Type with TypeFlags.EnumLiteral (representing the enum member, e.g., `Color.Red`)\n // Check if TS resolves this to its base type (string/number) or if it falls to unhandled.\n // If number enum: Potentially { [deriveSymbol]: true, optional: false, [$types]: ['number'] }\n // If string enum: Potentially { [deriveSymbol]: true, optional: false, [$types]: ['string'] } or a literal string.\n // If unhandled: { [deriveSymbol]: true, optional: false, [$types]: ['Color.Red'] } or similar. Check console warning.\n },\n );\n});\n\ndescribe('serializeType: Union Types (`|`)', () => {\n it.todo(\n 'serializes a union of primitive types (e.g., string | number)',\n () => {\n // Input: ts.UnionType with string and number types\n // Output: { [deriveSymbol]: true, kind: 'union', optional: false, [$types]: [serializedString, serializedNumber] }\n },\n );\n it.todo(\n 'serializes a union type including `null` (e.g., string | null)',\n () => {\n // Input: ts.UnionType with string and null types\n // Output: { [deriveSymbol]: true, kind: 'union', optional: false, [$types]: [serializedString, serializedNull] }\n // Note: `optional` remains false because `null` is treated as a distinct type here.\n },\n );\n it.todo(\n 'serializes a union type including `undefined`, setting optional flag and filtering `undefined`',\n () => {\n // Input: ts.UnionType with string and undefined types\n // Output: { [deriveSymbol]: true, kind: 'union', optional: true, [$types]: [serializedString] } // undefined is filtered out, optional set to true\n },\n );\n it.todo(\n 'serializes a union type including both `null` and `undefined`',\n () => {\n // Input: ts.UnionType with string, null, and undefined types\n // Output: { [deriveSymbol]: true, kind: 'union', optional: true, [$types]: [serializedString, serializedNull] } // undefined filtered, optional true\n },\n );\n it.todo('serializes a union of literal types (e.g., \"a\" | \"b\" | 1)', () => {\n // Input: ts.UnionType with \"a\", \"b\", 1 types\n // Output: { [deriveSymbol]: true, kind: 'union', optional: false, [$types]: [serializedLiteralA, serializedLiteralB, serializedLiteral1] }\n });\n it.todo(\n 'serializes a union including complex types (e.g., string | MyInterface)',\n () => {\n // Input: ts.UnionType with string and an interface type\n // Output: { [deriveSymbol]: true, kind: 'union', optional: false, [$types]: [serializedString, serializedInterfaceRef] }\n },\n );\n it.todo('serializes a union containing only `undefined`', () => {\n // Input: ts.UnionType with only undefined type\n // Output: { [deriveSymbol]: true, kind: 'union', optional: true, [$types]: [] }\n });\n it.todo('serializes a union containing only `null`', () => {\n // Input: ts.UnionType with only null type\n // Output: { [deriveSymbol]: true, kind: 'union', optional: false, [$types]: [serializedNull] }\n });\n});\n\ndescribe('serializeType: Intersection Types (`&`)', () => {\n it.todo(\n 'serializes an intersection of object/interface types (e.g., A & B)',\n () => {\n // Input: ts.IntersectionType with two interface types A and B\n // Output: { [deriveSymbol]: true, kind: 'intersection', optional: false, [$types]: [serializedInterfaceA, serializedInterfaceB] }\n },\n );\n it.todo(\n 'serializes an intersection type including `undefined`, setting optional flag and filtering `undefined`',\n () => {\n // Input: ts.IntersectionType with an interface type A and undefined\n // Output: { [deriveSymbol]: true, kind: 'intersection', optional: true, [$types]: [serializedInterfaceA] }\n },\n );\n it.todo('serializes an intersection containing only `undefined`', () => {\n // Input: ts.IntersectionType with only undefined type\n // Output: { [deriveSymbol]: true, kind: 'intersection', optional: true, [$types]: [] }\n });\n // Note: Intersections of primitives often resolve to `never`. The serialization of `never` itself is tested separately.\n});\n\ndescribe('serializeType: Array and Tuple Types', () => {\n it.todo('serializes a simple array type (e.g., string[])', () => {\n // Input: ts.TypeReference to Array<string>\n // Mock checker.isArrayLikeType -> true, checker.getTypeArguments -> [stringType]\n // Output: { [deriveSymbol]: true, kind: 'array', optional: false, [$types]: [serializedString] }\n });\n it.todo('serializes readonly array types (e.g., readonly number[])', () => {\n // Input: ts.TypeReference to ReadonlyArray<number>\n // Mock checker.isArrayLikeType -> true, checker.getTypeArguments -> [numberType]\n // Output: { [deriveSymbol]: true, kind: 'array', optional: false, [$types]: [serializedNumber] }\n });\n it.todo(\n 'serializes an array type with object elements (e.g., MyInterface[])',\n () => {\n // Input: ts.TypeReference to Array<MyInterface>\n // Mock checker.getTypeArguments -> [interfaceType], interfaceType.symbol.valueDeclaration -> InterfaceDeclaration Node\n // Output: { [deriveSymbol]: true, kind: 'array', optional: false, [$types]: [serializedInterfaceRef] } // Relies on serializeNode call\n },\n );\n it.todo(\n 'serializes an array type with union elements (e.g., (string | number)[])',\n () => {\n // Input: ts.TypeReference to Array<string | number>\n // Mock checker.getTypeArguments -> [unionType]\n // Output: { [deriveSymbol]: true, kind: 'array', optional: false, [$types]: [serializedUnionStringNumber] }\n },\n );\n it.todo('serializes an array type where element type has no symbol', () => {\n // Input: ts.TypeReference to Array<{inline: boolean}>\n // Mock checker.getTypeArguments -> [inlineObjectType], inlineObjectType.getSymbol() -> undefined\n // Output: { [deriveSymbol]: true, kind: 'array', optional: false, [$types]: [serializedInlineObject] } // Relies on serializeType(inlineObjectType)\n });\n it.todo(\n 'serializes an array type where element symbol has no value declaration but has declarations',\n () => {\n // Input: ts.TypeReference to Array<SomeType>\n // Mock checker.getTypeArguments -> [someType], someType.symbol.valueDeclaration -> undefined, someType.symbol.declarations -> [TypeAliasDeclaration Node?]\n // Expect serializeNode to be called with declarations[0]. Verify output based on that node type.\n },\n );\n it.todo(\n 'serializes an array type with a mapped type element (e.g., MappedType[])',\n () => {\n // Input: ts.TypeReference to Array<MappedType>\n // Mock checker.getTypeArguments -> [mappedType], mappedType symbol has declarations[0] as MappedTypeNode\n // Mock checker.getPropertiesOfType for mappedType\n // Output: { kind: 'array', optional: false, [deriveSymbol]: true, [$types]: [resolvedMappedObject] }\n },\n );\n it.todo(\n 'handles array-like types with missing type arguments gracefully (e.g., Array)',\n () => {\n // Input: ts.TypeReference to Array (no <T>)\n // Mock checker.getTypeArguments -> undefined or []\n // Output: { [deriveSymbol]: true, optional: false, kind: 'array', [$types]: ['any'] } // Check console warning\n },\n );\n it.todo(\n 'serializes tuple types (e.g., [string, number]) potentially as array of union',\n () => {\n // Input: ts.TupleTypeReference for [string, number]\n // Mock checker.isArrayLikeType -> true. Check what checker.getTypeArguments returns (likely the tuple element types).\n // Current code likely serializes as Array<string | number>.\n // Expected Output (based on current code): { [deriveSymbol]: true, kind: 'array', optional: false, [$types]: [serializedUnionStringNumber] } or similar union.\n // Note: A more precise tuple serialization would require specific handling of ts.TupleTypeReference.\n },\n );\n});\n\ndescribe('serializeType: Record/Index Types', () => {\n it.todo(\n 'serializes a string index signature type (Record<string, number>)',\n () => {\n // Input: ts.Type where type.getStringIndexType() returns numberType\n // Output: { [deriveSymbol]: true, kind: 'record', optional: false, [$types]: [serializedNumber] }\n },\n );\n it.todo(\n 'serializes a string index signature type with complex value (Record<string, MyInterface>)',\n () => {\n // Input: ts.Type where type.getStringIndexType() returns interfaceType\n // Output: { [deriveSymbol]: true, kind: 'record', optional: false, [$types]: [serializedInterfaceRef] }\n },\n );\n it.todo(\n 'serializes a type with only a number index signature ([key: number]: boolean)',\n () => {\n // Input: ts.Type where type.getStringIndexType() is undefined, but type.getNumberIndexType() exists.\n // Expect this to *not* take the `getStringIndexType` path.\n // It should fall into the `TypeFlags.Object` path.\n // Mock checker.getPropertiesOfType (might be empty or special symbol).\n // Mock type.symbol.declarations to include the IndexSignature node.\n // Expected Output: Likely falls back to generic object or potentially unhandled `{ [deriveSymbol]: true, optional: false, [$types]: ['<some object representation>'] }`. Needs verification against actual TS behavior.\n },\n );\n});\n\ndescribe('serializeType: Object Types (Interfaces, Classes, Inline, Mapped)', () => {\n it.todo('serializes an inline object type literal (passed as type)', () => {\n // Input: ts.Type representing `{ a: string; b?: number }` (TypeFlags.Object)\n // Mock checker.getPropertiesOfType -> [symbolA, symbolB]\n // Mock checker.getTypeOfSymbol for 'a' (string) and 'b' (number | undefined)\n // Output: { [deriveSymbol]: true, kind: 'object', optional: false, [$types]: [{ a: serializedString, b: serializedUnionNumberUndefined }] }\n });\n it.todo(\n 'serializes a mapped type directly (e.g., type M = { [K in keyof T]: T[K] })',\n () => {\n // Input: ts.Type representing a mapped type (TypeFlags.Object, potentially others)\n // Mock checker.getPropertiesOfType to return the mapped properties.\n // Mock checker.getTypeOfSymbol for each mapped property.\n // Output: { [deriveSymbol]: true, kind: 'object', optional: false, [$types]: [{ /* serialized mapped properties */ }] }\n },\n );\n it.todo(\n 'serializes an object type using literal property assignments from declarations',\n () => {\n // Input: ts.Type representing an object like `const x = { val: 123 }`\n // Mock checker.getPropertiesOfType -> [symbolVal]\n // Mock symbolVal.getDeclarations() -> [PropertyAssignment node with literal 123]\n // Mock checker.getTypeAtLocation for the literal initializer -> numberLiteralType(123)\n // Output: { [deriveSymbol]: true, kind: 'object', optional: false, [$types]: [{ val: serializedLiteral123 }] }\n },\n );\n it.todo(\n 'serializes an object type with mixed declared types (PropertySignature) and literal assignments (PropertyAssignment)',\n () => {\n // Input: ts.Type representing `{ prop: string; literal: \"hello\" }` where `prop` comes from signature and `literal` from assignment.\n // Ensure both `isPropertyAssignment` and `isPropertySignature` paths within the loop are tested.\n // Output: { [deriveSymbol]: true, kind: 'object', optional: false, [$types]: [{ prop: serializedString, literal: serializedLiteralHello }] }\n },\n );\n it.todo(\n 'serializes an empty object type `{}` potentially falling back to name or generic',\n () => {\n // Input: ts.Type representing `{}` (TypeFlags.Object)\n // Mock checker.getPropertiesOfType -> []\n // Mock type.symbol.valueDeclaration / declarations -> undefined\n // Mock type.symbol.getName() -> 'Object' or similar\n // Expected Output: Depends on fallback logic. Potentially `{ [deriveSymbol]: true, optional: false, [$types]: ['Object'] }` or a generic object representation if name is unhelpful.\n },\n );\n it.todo(\n 'handles object types matching default overrides (e.g., DateConstructor -> string)',\n () => {\n // Input: ts.Type whose symbol name is 'DateConstructor' (present in `defaults`)\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['string'] } // Value from `defaults` map\n },\n );\n it.todo(\n 'handles known object types NOT in defaults (e.g., RegExp) by attempting standard object serialization',\n () => {\n // Input: ts.Type for RegExp (not in `defaults`)\n // Mock checker.getPropertiesOfType (likely empty or methods)\n // Mock symbol.valueDeclaration / declarations (likely points to lib.d.ts)\n // Expect standard object serialization attempt, possibly resulting in an empty object or reference if declaration is found.\n // Output: { [deriveSymbol]: true, kind: 'object', optional: false, [$types]: [{ /* properties or empty */ }] } or a reference via serializeNode.\n },\n );\n it.todo(\n 'serializes an interface type by deferring to serializeNode for reference/collection',\n () => {\n // Input: ts.InterfaceType (isInterfaceType returns true)\n // Mock type.symbol.valueDeclaration or declarations[0] -> InterfaceDeclaration node\n // Verify serializeNode is called with the declaration node.\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/MyInterface`] }\n },\n );\n it.todo(\n 'serializes a class type by deferring to serializeNode for reference/collection',\n () => {\n // Input: ts.Type representing a class (isClass returns true)\n // Mock type.symbol.valueDeclaration -> ClassDeclaration node\n // Verify serializeNode is called with the declaration node.\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/MyClass`], $ref: `#/components/schemas/MyClass` }\n },\n );\n it.todo(\n 'serializes an interface type using its name when its declaration cannot be found',\n () => {\n // Input: ts.InterfaceType where type.symbol has no valueDeclaration or declarations[0]\n // Mock type.symbol.getName() -> 'MyInterface'\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['MyInterface'] }\n },\n );\n it.todo(\n 'serializes a class type using its name when its declaration cannot be found',\n () => {\n // Input: ts.Type for a class where type.symbol has no valueDeclaration\n // Mock type.symbol.getName() -> 'MyClass'\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['MyClass'] }\n },\n );\n});\n\ndescribe('serializeType: Unhandled Types', () => {\n it.todo(\n 'handles an unhandled type flag by using checker.typeToString and warns',\n () => {\n // Input: A ts.Type with flags not explicitly handled (e.g., potentially Enum, Index, IndexedAccess if not resolved)\n // Mock checker.typeToString -> '<specific unhandled representation>'\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['<specific unhandled representation>'] } // Check console warning\n },\n );\n // Note: Complex types like ConditionalType, IndexedAccessType are expected to be resolved by the checker *before* this function sees them.\n // We serialize the *result* of the resolution, not the conditional/indexed access type itself.\n});\n\n// --- serializeNode Functionality ---\n\ndescribe('serializeNode: Object Literal Expressions (`{ ... }`)', () => {\n it.todo(\n 'serializes an object literal node with various primitive property types',\n () => {\n // Input: ts.ObjectLiteralExpression node `{ a: 1, b: \"s\", c: true, d: null, e: undefined }`\n // Mock checker.getTypeAtLocation for the node itself\n // Mock checker.getTypeOfSymbol for properties 'a', 'b', 'c', 'd', 'e'\n // Mock checker.getTypeAtLocation for literal initializers (1, \"s\", true, null, undefined)\n // Output: { a: serializedLiteral1, b: serializedLiteralS, c: serializedLiteralTrue, d: serializedNull, e: serializedUndefined } // Note: undefined serialization depends on serializeType\n },\n );\n it.todo(\n 'serializes an object literal node with nested object/array literals',\n () => {\n // Input: ts.ObjectLiteralExpression node `{ data: { values: [1, 2] } }`\n // Ensure recursive serialization via serializeType/serializeNode works.\n // Output: { data: { values: serializedArrayLiteral12 } }\n },\n );\n it.todo('serializes an empty object literal node `{}`', () => {\n // Input: ts.ObjectLiteralExpression node `{}`\n // Mock checker.getTypeAtLocation -> empty object type\n // Output: {}\n });\n});\n\ndescribe('serializeNode: Property Access/Signature/Declaration', () => {\n it.todo(\n 'serializes a PropertyAccessExpression node (e.g., `obj.prop`) by resolving its type',\n () => {\n // Input: ts.PropertyAccessExpression node `obj.prop`\n // Mock checker.getSymbolAtLocation for `prop` -> symbolProp\n // Mock checker.getTypeOfSymbol(symbolProp) -> typeProp\n // Verify serializeType is called with typeProp.\n // Output: Result of serializeType(typeProp)\n },\n );\n it.todo(\n 'serializes a PropertySignature node (e.g., `prop: string;`) by resolving its type',\n () => {\n // Input: ts.PropertySignature node `prop: string;` (within an InterfaceDeclaration or TypeLiteral)\n // Mock checker.getSymbolAtLocation for `prop` -> symbolProp\n // Mock checker.getTypeOfSymbol(symbolProp) -> stringType\n // Verify serializeType is called with stringType.\n // Output: Result of serializeType(stringType)\n },\n );\n it.todo(\n 'serializes a PropertyDeclaration node (e.g., `prop: number;`) by resolving its type',\n () => {\n // Input: ts.PropertyDeclaration node `prop: number;` (within a ClassDeclaration)\n // Mock checker.getSymbolAtLocation for `prop` -> symbolProp\n // Mock checker.getTypeOfSymbol(symbolProp) -> numberType\n // Verify serializeType is called with numberType.\n // Output: Result of serializeType(numberType)\n },\n );\n it.todo(\n 'handles property nodes where symbol cannot be found for the property name and warns',\n () => {\n // Input: A PropertySignature/Declaration/Access node where checker.getSymbolAtLocation(node.name) returns undefined\n // Output: null // Check console warning\n },\n );\n});\n\ndescribe('serializeNode: Interface Declarations (`interface ...`) and Collector Interaction', () => {\n it.todo(\n 'serializes a new interface declaration, adding its structure to the collector',\n () => {\n // Input: ts.InterfaceDeclaration node `interface MyInterface { id: number; name?: string; }`\n // Ensure collector['MyInterface'] is initially empty/undefined.\n // Mock members `id` and `name` and their serialization via serializeNode(PropertySignature).\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/MyInterface`] }\n // Verify collector['MyInterface'] now contains { id: serializedNumber, name: serializedUnionStringUndefined }\n },\n );\n it.todo(\n 'returns only a reference for an already serialized interface declaration (present in collector)',\n () => {\n // Input: ts.InterfaceDeclaration node `interface MyInterface { ... }`\n // Pre-populate collector['MyInterface'] with a placeholder or previous result.\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/MyInterface`] }\n // Verify collector['MyInterface'] was not overwritten if already fully populated.\n },\n );\n it.todo(\n 'handles interface declarations matching default overrides without adding to collector',\n () => {\n // Input: ts.InterfaceDeclaration node `interface Readable { ... }` (name is in `defaults`)\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['any'] } // Value from `defaults` map\n // Verify collector['Readable'] remains undefined or unchanged.\n },\n );\n it.todo(\n 'throws an error for an interface declaration without a name',\n () => {\n // Input: An InterfaceDeclaration node where node.name is undefined.\n // Expect the function to throw 'Interface has no name'.\n },\n );\n it.todo(\n 'handles interfaces with no members correctly (adds empty object to collector)',\n () => {\n // Input: ts.InterfaceDeclaration node `interface Empty {}`\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/Empty`] }\n // Verify collector['Empty'] is `{}`.\n },\n );\n it.todo(\n 'handles interfaces extending other interfaces (serialization includes only own properties)',\n () => {\n // Input: `interface B extends A { propB: string; }` (where A is `interface A { propA: number }`)\n // Serialize B.\n // Output: Reference `#/components/schemas/B`\n // Verify collector['B'] contains only `{ propB: serializedString }`. (Inherited props are resolved by tools consuming the schema, not duplicated here).\n // Note: Actual inheritance representation might need adjustment based on target schema format (e.g., OpenAPI `allOf`). This test verifies the *collector* content based on current code.\n },\n );\n});\n\ndescribe('serializeNode: Class Declarations (`class ...`) and Collector Interaction', () => {\n it.todo(\n 'serializes a new class declaration, adding its property structure to the collector',\n () => {\n // Input: ts.ClassDeclaration node `class MyClass { id: number; private secret: string; constructor() {} }`\n // Ensure collector['MyClass'] is initially empty/undefined.\n // Mock members `id` and `secret` and their serialization via serializeNode(PropertyDeclaration). Ignore constructor/methods.\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/MyClass`], $ref: `#/components/schemas/MyClass` }\n // Verify collector['MyClass'] now contains { id: serializedNumber, secret: serializedString } (Includes private members)\n },\n );\n it.todo(\n 'returns only a reference for an already serialized class declaration (present in collector)',\n () => {\n // Input: ts.ClassDeclaration node `class MyClass { ... }`\n // Pre-populate collector['MyClass'] with a placeholder or previous result.\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/MyClass`], $ref: `#/components/schemas/MyClass` }\n // Verify collector['MyClass'] was not overwritten if already fully populated.\n },\n );\n it.todo(\n 'handles class declarations matching default overrides without adding to collector',\n () => {\n // Input: ts.ClassDeclaration node `class Uint8Array { ... }` (name is in `defaults`)\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['any'] } // Value from `defaults` map\n // Verify collector['Uint8Array'] remains undefined or unchanged.\n },\n );\n it.todo(\n 'throws an error for a class declaration without a name (e.g., anonymous default export)',\n () => {\n // Input: A ClassDeclaration node where node.name is undefined.\n // Expect the function to throw 'Class has no name'.\n },\n );\n it.todo(\n 'handles classes with no property declarations (only methods/constructor) correctly (adds empty object to collector)',\n () => {\n // Input: ts.ClassDeclaration node `class Service { constructor() {} process() {} }`\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/Service`], $ref: `#/components/schemas/Service` }\n // Verify collector['Service'] is `{}`.\n },\n );\n it.todo(\n 'handles classes implementing interfaces (serialization includes only own properties)',\n () => {\n // Input: `class B implements A { propB: string; }` (where A is `interface A { propA: number }`)\n // Serialize B.\n // Output: Reference `#/components/schemas/B`\n // Verify collector['B'] contains only `{ propB: serializedString }`.\n },\n );\n it.todo(\n 'handles classes extending other classes (serialization includes only own properties)',\n () => {\n // Input: `class D extends C { propD: string; }` (where C is `class C { propC: number }`)\n // Serialize D.\n // Output: Reference `#/components/schemas/D`\n // Verify collector['D'] contains only `{ propD: serializedString }`.\n },\n );\n});\n\ndescribe('serializeNode: Other Node Types', () => {\n it.todo(\n 'serializes a VariableDeclaration node with an explicit type annotation',\n () => {\n // Input: ts.VariableDeclaration node `const user: IUser;`\n // Mock node.type to be a TypeReference node pointing to IUser\n // Mock checker.getTypeFromTypeNode -> interfaceType IUser\n // Verify serializeType is called with interfaceType IUser.\n // Output: Result of serializeType(interfaceType IUser) -> likely interface reference\n },\n );\n it.todo(\n 'handles VariableDeclaration node without a type annotation and warns',\n () => {\n // Input: ts.VariableDeclaration node `const count = 5;` (node.type is undefined)\n // Output: 'any' // Check console warning\n },\n );\n it.todo(\n 'handles VariableDeclaration node where symbol cannot be found for the variable name and warns',\n () => {\n // Input: ts.VariableDeclaration node where checker.getSymbolAtLocation(node.name) returns undefined\n // Output: null // Check console warning\n },\n );\n it.todo(\n 'serializes an Identifier node by resolving its type at that location',\n () => {\n // Input: ts.Identifier node `myVar` (where myVar is declared as string)\n // Mock checker.getSymbolAtLocation for the identifier -> symbolMyVar\n // Mock checker.getTypeAtLocation for the identifier node -> stringType\n // Verify serializeType is called with stringType.\n // Output: Result of serializeType(stringType)\n },\n );\n it.todo(\n 'handles Identifier node where symbol cannot be found and warns',\n () => {\n // Input: ts.Identifier node where checker.getSymbolAtLocation returns undefined\n // Output: null // Check console warning\n },\n );\n it.todo(\n 'serializes an AwaitExpression node by resolving the awaited type',\n () => {\n // Input: ts.AwaitExpression node `await getUser()` where getUser returns Promise<User>\n // Mock checker.getTypeAtLocation(node) -> User type (checker resolves the Promise)\n // Verify serializeType is called with the User type.\n // Output: Result of serializeType(User type)\n },\n );\n it.todo(\n 'serializes a CallExpression node by resolving its return type',\n () => {\n // Input: ts.CallExpression node `calculateTotal()` where calculateTotal returns number\n // Mock checker.getTypeAtLocation(node) -> numberType\n // Verify serializeType is called with numberType.\n // Output: Result of serializeType(numberType)\n },\n );\n it.todo(\n 'serializes an AsExpression node by resolving the asserted type',\n () => {\n // Input: ts.AsExpression node `data as Product`\n // Mock checker.getTypeAtLocation(node) -> Product type (the asserted type)\n // Verify serializeType is called with the Product type.\n // Output: Result of serializeType(Product type)\n },\n );\n it.todo(\n 'serializes a TypeLiteralNode (`{ ... }` used as a type) by resolving its properties',\n () => {\n // Input: ts.TypeLiteralNode node `{ id: number; value: string }`\n // Mock checker.getTypeAtLocation(node) -> objectType\n // Mock checker.getPropertiesOfType(objectType) -> [symbolId, symbolValue]\n // Mock checker.getTypeOfSymbol for each property.\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [{ id: serializedNumber, value: serializedString }] }\n },\n );\n it.todo('serializes NullKeyword node', () => {\n // Input: Node with kind ts.SyntaxKind.NullKeyword\n // Output: { [deriveSymbol]: true, optional: true, [$types]: ['null'] }\n });\n it.todo('serializes BooleanKeyword node', () => {\n // Input: Node with kind ts.SyntaxKind.BooleanKeyword\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['boolean'] }\n });\n it.todo('serializes TrueKeyword node as boolean literal', () => {\n // Input: Node with kind ts.SyntaxKind.TrueKeyword\n // Output: { [deriveSymbol]: true, optional: false, kind: 'literal', value: true, [$types]: ['boolean'] }\n });\n it.todo('serializes FalseKeyword node as boolean literal', () => {\n // Input: Node with kind ts.SyntaxKind.FalseKeyword\n // Output: { [deriveSymbol]: true, optional: false, kind: 'literal', value: false, [$types]: ['boolean'] }\n });\n it.todo(\n 'serializes an ArrayLiteralExpression node by resolving its inferred type',\n () => {\n // Input: ts.ArrayLiteralExpression node `[1, \"a\", null]`\n // Mock checker.getTypeAtLocation(node) -> inferred array type (e.g., (number | string | null)[])\n // Verify serializeType is called with the inferred type.\n // Output: Result of serializeType(inferred array type) -> likely array of union\n },\n );\n it.todo(\n 'handles an unhandled node kind by returning `any` and warns',\n () => {\n // Input: A node with a kind not explicitly handled (e.g., ts.SyntaxKind.IfStatement)\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['any'] } // Check console warning\n },\n );\n});\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import { describe, it } from 'node:test';\n\n// --- serializeType Functionality ---\n\ndescribe('serializeType: Basic Primitive and Special Types', () => {\n it.todo('serializes `any` type to an empty type list', () => {\n // Input: ts.Type with TypeFlags.Any\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [] }\n });\n it.todo('serializes `unknown` type to an empty type list', () => {\n // Input: ts.Type with TypeFlags.Unknown\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [] }\n });\n it.todo('serializes `string` type', () => {\n // Input: ts.Type with TypeFlags.String\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['string'] }\n });\n it.todo('serializes `number` type', () => {\n // Input: ts.Type with TypeFlags.Number\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['number'] }\n });\n it.todo('serializes `boolean` type', () => {\n // Input: ts.Type with TypeFlags.Boolean\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['boolean'] }\n });\n it.todo('serializes `null` type as optional', () => {\n // Input: ts.Type with TypeFlags.Null\n // Output: { [deriveSymbol]: true, optional: true, [$types]: ['null'] }\n });\n it.todo(\n 'serializes `void` type (likely falls back to Any/Unknown or unhandled)',\n () => {\n // Input: ts.Type with TypeFlags.Void (or VoidLike)\n // Determine expected output based on how TS checker presents this type and how the unhandled path works. Likely results in `[$types]: []` or `[$types]: ['void']`.\n },\n );\n it.todo(\n 'serializes `never` type (likely falls back to Any/Unknown or unhandled)',\n () => {\n // Input: ts.Type with TypeFlags.Never\n // Determine expected output. Likely results in `[$types]: []` or `[$types]: ['never']`.\n },\n );\n it.todo(\n 'serializes `undefined` type implicitly via union/intersection optional flag',\n () => {\n // Note: Undefined itself isn't directly serialized as a standalone type by this logic.\n // Its presence in unions/intersections correctly sets the `optional` flag. Tests are under Union/Intersection sections.\n },\n );\n});\n\ndescribe('serializeType: Literal Types', () => {\n it.todo('serializes string literal types with their value', () => {\n // Input: ts.StringLiteralType (e.g., type of \"constant\")\n // Output: { [deriveSymbol]: true, optional: false, kind: 'literal', value: 'constant', [$types]: ['string'] }\n });\n it.todo('serializes numeric literal types with their value', () => {\n // Input: ts.NumberLiteralType (e.g., type of 123)\n // Output: { [deriveSymbol]: true, optional: false, kind: 'literal', value: 123, [$types]: ['number'] }\n });\n it.todo('serializes boolean literal `true` type', () => {\n // Input: ts.BooleanLiteralType (true) checked via TypeFlags.BooleanLiteral\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['boolean'] }\n // Note: Current code identifies it's boolean but doesn't store the literal `true` value.\n });\n it.todo('serializes boolean literal `false` type', () => {\n // Input: ts.BooleanLiteralType (false) checked via TypeFlags.BooleanLiteral\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['boolean'] }\n // Note: Current code identifies it's boolean but doesn't store the literal `false` value.\n });\n it.todo('serializes template literal types as base `string`', () => {\n // Input: ts.Type with TypeFlags.TemplateLiteral (e.g. type of `ID-${number}`)\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['string'] }\n });\n // Note: BigIntLiteral is not explicitly handled, would fall under unhandled.\n});\n\ndescribe('serializeType: Enum Types', () => {\n it.todo(\n 'serializes an Enum type (e.g., `enum Color {}`) potentially via unhandled path',\n () => {\n // Input: ts.Type with TypeFlags.Enum (representing the enum itself, e.g., `Color`)\n // Expect it to fall into the unhandled path, likely using checker.typeToString.\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['Color'] } or similar based on typeToString. Check console warning.\n },\n );\n it.todo(\n 'serializes an EnumLiteral type (e.g., `Color.Red`) potentially via unhandled path or base type',\n () => {\n // Input: ts.Type with TypeFlags.EnumLiteral (representing the enum member, e.g., `Color.Red`)\n // Check if TS resolves this to its base type (string/number) or if it falls to unhandled.\n // If number enum: Potentially { [deriveSymbol]: true, optional: false, [$types]: ['number'] }\n // If string enum: Potentially { [deriveSymbol]: true, optional: false, [$types]: ['string'] } or a literal string.\n // If unhandled: { [deriveSymbol]: true, optional: false, [$types]: ['Color.Red'] } or similar. Check console warning.\n },\n );\n});\n\ndescribe('serializeType: Union Types (`|`)', () => {\n it.todo(\n 'serializes a union of primitive types (e.g., string | number)',\n () => {\n // Input: ts.UnionType with string and number types\n // Output: { [deriveSymbol]: true, kind: 'union', optional: false, [$types]: [serializedString, serializedNumber] }\n },\n );\n it.todo(\n 'serializes a union type including `null` (e.g., string | null)',\n () => {\n // Input: ts.UnionType with string and null types\n // Output: { [deriveSymbol]: true, kind: 'union', optional: false, [$types]: [serializedString, serializedNull] }\n // Note: `optional` remains false because `null` is treated as a distinct type here.\n },\n );\n it.todo(\n 'serializes a union type including `undefined`, setting optional flag and filtering `undefined`',\n () => {\n // Input: ts.UnionType with string and undefined types\n // Output: { [deriveSymbol]: true, kind: 'union', optional: true, [$types]: [serializedString] } // undefined is filtered out, optional set to true\n },\n );\n it.todo(\n 'serializes a union type including both `null` and `undefined`',\n () => {\n // Input: ts.UnionType with string, null, and undefined types\n // Output: { [deriveSymbol]: true, kind: 'union', optional: true, [$types]: [serializedString, serializedNull] } // undefined filtered, optional true\n },\n );\n it.todo('serializes a union of literal types (e.g., \"a\" | \"b\" | 1)', () => {\n // Input: ts.UnionType with \"a\", \"b\", 1 types\n // Output: { [deriveSymbol]: true, kind: 'union', optional: false, [$types]: [serializedLiteralA, serializedLiteralB, serializedLiteral1] }\n });\n it.todo(\n 'serializes a union including complex types (e.g., string | MyInterface)',\n () => {\n // Input: ts.UnionType with string and an interface type\n // Output: { [deriveSymbol]: true, kind: 'union', optional: false, [$types]: [serializedString, serializedInterfaceRef] }\n },\n );\n it.todo('serializes a union containing only `undefined`', () => {\n // Input: ts.UnionType with only undefined type\n // Output: { [deriveSymbol]: true, kind: 'union', optional: true, [$types]: [] }\n });\n it.todo('serializes a union containing only `null`', () => {\n // Input: ts.UnionType with only null type\n // Output: { [deriveSymbol]: true, kind: 'union', optional: false, [$types]: [serializedNull] }\n });\n});\n\ndescribe('serializeType: Intersection Types (`&`)', () => {\n it.todo(\n 'serializes an intersection of object/interface types (e.g., A & B)',\n () => {\n // Input: ts.IntersectionType with two interface types A and B\n // Output: { [deriveSymbol]: true, kind: 'intersection', optional: false, [$types]: [serializedInterfaceA, serializedInterfaceB] }\n },\n );\n it.todo(\n 'serializes an intersection type including `undefined`, setting optional flag and filtering `undefined`',\n () => {\n // Input: ts.IntersectionType with an interface type A and undefined\n // Output: { [deriveSymbol]: true, kind: 'intersection', optional: true, [$types]: [serializedInterfaceA] }\n },\n );\n it.todo('serializes an intersection containing only `undefined`', () => {\n // Input: ts.IntersectionType with only undefined type\n // Output: { [deriveSymbol]: true, kind: 'intersection', optional: true, [$types]: [] }\n });\n // Note: Intersections of primitives often resolve to `never`. The serialization of `never` itself is tested separately.\n});\n\ndescribe('serializeType: Array and Tuple Types', () => {\n it.todo('serializes a simple array type (e.g., string[])', () => {\n // Input: ts.TypeReference to Array<string>\n // Mock checker.isArrayLikeType -> true, checker.getTypeArguments -> [stringType]\n // Output: { [deriveSymbol]: true, kind: 'array', optional: false, [$types]: [serializedString] }\n });\n it.todo('serializes readonly array types (e.g., readonly number[])', () => {\n // Input: ts.TypeReference to ReadonlyArray<number>\n // Mock checker.isArrayLikeType -> true, checker.getTypeArguments -> [numberType]\n // Output: { [deriveSymbol]: true, kind: 'array', optional: false, [$types]: [serializedNumber] }\n });\n it.todo(\n 'serializes an array type with object elements (e.g., MyInterface[])',\n () => {\n // Input: ts.TypeReference to Array<MyInterface>\n // Mock checker.getTypeArguments -> [interfaceType], interfaceType.symbol.valueDeclaration -> InterfaceDeclaration Node\n // Output: { [deriveSymbol]: true, kind: 'array', optional: false, [$types]: [serializedInterfaceRef] } // Relies on serializeNode call\n },\n );\n it.todo(\n 'serializes an array type with union elements (e.g., (string | number)[])',\n () => {\n // Input: ts.TypeReference to Array<string | number>\n // Mock checker.getTypeArguments -> [unionType]\n // Output: { [deriveSymbol]: true, kind: 'array', optional: false, [$types]: [serializedUnionStringNumber] }\n },\n );\n it.todo('serializes an array type where element type has no symbol', () => {\n // Input: ts.TypeReference to Array<{inline: boolean}>\n // Mock checker.getTypeArguments -> [inlineObjectType], inlineObjectType.getSymbol() -> undefined\n // Output: { [deriveSymbol]: true, kind: 'array', optional: false, [$types]: [serializedInlineObject] } // Relies on serializeType(inlineObjectType)\n });\n it.todo(\n 'serializes an array type where element symbol has no value declaration but has declarations',\n () => {\n // Input: ts.TypeReference to Array<SomeType>\n // Mock checker.getTypeArguments -> [someType], someType.symbol.valueDeclaration -> undefined, someType.symbol.declarations -> [TypeAliasDeclaration Node?]\n // Expect serializeNode to be called with declarations[0]. Verify output based on that node type.\n },\n );\n it.todo(\n 'serializes an array type with a mapped type element (e.g., MappedType[])',\n () => {\n // Input: ts.TypeReference to Array<MappedType>\n // Mock checker.getTypeArguments -> [mappedType], mappedType symbol has declarations[0] as MappedTypeNode\n // Mock checker.getPropertiesOfType for mappedType\n // Output: { kind: 'array', optional: false, [deriveSymbol]: true, [$types]: [resolvedMappedObject] }\n },\n );\n it.todo(\n 'handles array-like types with missing type arguments gracefully (e.g., Array)',\n () => {\n // Input: ts.TypeReference to Array (no <T>)\n // Mock checker.getTypeArguments -> undefined or []\n // Output: { [deriveSymbol]: true, optional: false, kind: 'array', [$types]: ['any'] } // Check console warning\n },\n );\n it.todo(\n 'serializes tuple types (e.g., [string, number]) potentially as array of union',\n () => {\n // Input: ts.TupleTypeReference for [string, number]\n // Mock checker.isArrayLikeType -> true. Check what checker.getTypeArguments returns (likely the tuple element types).\n // Current code likely serializes as Array<string | number>.\n // Expected Output (based on current code): { [deriveSymbol]: true, kind: 'array', optional: false, [$types]: [serializedUnionStringNumber] } or similar union.\n // Note: A more precise tuple serialization would require specific handling of ts.TupleTypeReference.\n },\n );\n});\n\ndescribe('serializeType: Record/Index Types', () => {\n it.todo(\n 'serializes a string index signature type (Record<string, number>)',\n () => {\n // Input: ts.Type where type.getStringIndexType() returns numberType\n // Output: { [deriveSymbol]: true, kind: 'record', optional: false, [$types]: [serializedNumber] }\n },\n );\n it.todo(\n 'serializes a string index signature type with complex value (Record<string, MyInterface>)',\n () => {\n // Input: ts.Type where type.getStringIndexType() returns interfaceType\n // Output: { [deriveSymbol]: true, kind: 'record', optional: false, [$types]: [serializedInterfaceRef] }\n },\n );\n it.todo(\n 'serializes a type with only a number index signature ([key: number]: boolean)',\n () => {\n // Input: ts.Type where type.getStringIndexType() is undefined, but type.getNumberIndexType() exists.\n // Expect this to *not* take the `getStringIndexType` path.\n // It should fall into the `TypeFlags.Object` path.\n // Mock checker.getPropertiesOfType (might be empty or special symbol).\n // Mock type.symbol.declarations to include the IndexSignature node.\n // Expected Output: Likely falls back to generic object or potentially unhandled `{ [deriveSymbol]: true, optional: false, [$types]: ['<some object representation>'] }`. Needs verification against actual TS behavior.\n },\n );\n});\n\ndescribe('serializeType: Object Types (Interfaces, Classes, Inline, Mapped)', () => {\n it.todo('serializes an inline object type literal (passed as type)', () => {\n // Input: ts.Type representing `{ a: string; b?: number }` (TypeFlags.Object)\n // Mock checker.getPropertiesOfType -> [symbolA, symbolB]\n // Mock checker.getTypeOfSymbol for 'a' (string) and 'b' (number | undefined)\n // Output: { [deriveSymbol]: true, kind: 'object', optional: false, [$types]: [{ a: serializedString, b: serializedUnionNumberUndefined }] }\n });\n it.todo(\n 'serializes a mapped type directly (e.g., type M = { [K in keyof T]: T[K] })',\n () => {\n // Input: ts.Type representing a mapped type (TypeFlags.Object, potentially others)\n // Mock checker.getPropertiesOfType to return the mapped properties.\n // Mock checker.getTypeOfSymbol for each mapped property.\n // Output: { [deriveSymbol]: true, kind: 'object', optional: false, [$types]: [{ /* serialized mapped properties */ }] }\n },\n );\n it.todo(\n 'serializes an object type using literal property assignments from declarations',\n () => {\n // Input: ts.Type representing an object like `const x = { val: 123 }`\n // Mock checker.getPropertiesOfType -> [symbolVal]\n // Mock symbolVal.getDeclarations() -> [PropertyAssignment node with literal 123]\n // Mock checker.getTypeAtLocation for the literal initializer -> numberLiteralType(123)\n // Output: { [deriveSymbol]: true, kind: 'object', optional: false, [$types]: [{ val: serializedLiteral123 }] }\n },\n );\n it.todo(\n 'serializes an object type with mixed declared types (PropertySignature) and literal assignments (PropertyAssignment)',\n () => {\n // Input: ts.Type representing `{ prop: string; literal: \"hello\" }` where `prop` comes from signature and `literal` from assignment.\n // Ensure both `isPropertyAssignment` and `isPropertySignature` paths within the loop are tested.\n // Output: { [deriveSymbol]: true, kind: 'object', optional: false, [$types]: [{ prop: serializedString, literal: serializedLiteralHello }] }\n },\n );\n it.todo(\n 'serializes an empty object type `{}` potentially falling back to name or generic',\n () => {\n // Input: ts.Type representing `{}` (TypeFlags.Object)\n // Mock checker.getPropertiesOfType -> []\n // Mock type.symbol.valueDeclaration / declarations -> undefined\n // Mock type.symbol.getName() -> 'Object' or similar\n // Expected Output: Depends on fallback logic. Potentially `{ [deriveSymbol]: true, optional: false, [$types]: ['Object'] }` or a generic object representation if name is unhelpful.\n },\n );\n it.todo(\n 'handles object types matching default overrides (e.g., DateConstructor -> string)',\n () => {\n // Input: ts.Type whose symbol name is 'DateConstructor' (present in `defaults`)\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['string'] } // Value from `defaults` map\n },\n );\n it.todo(\n 'handles known object types NOT in defaults (e.g., RegExp) by attempting standard object serialization',\n () => {\n // Input: ts.Type for RegExp (not in `defaults`)\n // Mock checker.getPropertiesOfType (likely empty or methods)\n // Mock symbol.valueDeclaration / declarations (likely points to lib.d.ts)\n // Expect standard object serialization attempt, possibly resulting in an empty object or reference if declaration is found.\n // Output: { [deriveSymbol]: true, kind: 'object', optional: false, [$types]: [{ /* properties or empty */ }] } or a reference via serializeNode.\n },\n );\n it.todo(\n 'serializes an interface type by deferring to serializeNode for reference/collection',\n () => {\n // Input: ts.InterfaceType (an interface type verified by type.isClassOrInterface() and symbol flags)\n // Mock type.symbol.valueDeclaration or declarations[0] -> InterfaceDeclaration node\n // Verify serializeNode is called with the declaration node.\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/MyInterface`] }\n },\n );\n it.todo(\n 'serializes a class type by deferring to serializeNode for reference/collection',\n () => {\n // Input: ts.Type representing a class (isClass returns true)\n // Mock type.symbol.valueDeclaration -> ClassDeclaration node\n // Verify serializeNode is called with the declaration node.\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/MyClass`], $ref: `#/components/schemas/MyClass` }\n },\n );\n it.todo(\n 'serializes an interface type using its name when its declaration cannot be found',\n () => {\n // Input: ts.InterfaceType where type.symbol has no valueDeclaration or declarations[0]\n // Mock type.symbol.getName() -> 'MyInterface'\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['MyInterface'] }\n },\n );\n it.todo(\n 'serializes a class type using its name when its declaration cannot be found',\n () => {\n // Input: ts.Type for a class where type.symbol has no valueDeclaration\n // Mock type.symbol.getName() -> 'MyClass'\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['MyClass'] }\n },\n );\n});\n\ndescribe('serializeType: Unhandled Types', () => {\n it.todo(\n 'handles an unhandled type flag by using checker.typeToString and warns',\n () => {\n // Input: A ts.Type with flags not explicitly handled (e.g., potentially Enum, Index, IndexedAccess if not resolved)\n // Mock checker.typeToString -> '<specific unhandled representation>'\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['<specific unhandled representation>'] } // Check console warning\n },\n );\n // Note: Complex types like ConditionalType, IndexedAccessType are expected to be resolved by the checker *before* this function sees them.\n // We serialize the *result* of the resolution, not the conditional/indexed access type itself.\n});\n\n// --- serializeNode Functionality ---\n\ndescribe('serializeNode: Object Literal Expressions (`{ ... }`)', () => {\n it.todo(\n 'serializes an object literal node with various primitive property types',\n () => {\n // Input: ts.ObjectLiteralExpression node `{ a: 1, b: \"s\", c: true, d: null, e: undefined }`\n // Mock checker.getTypeAtLocation for the node itself\n // Mock checker.getTypeOfSymbol for properties 'a', 'b', 'c', 'd', 'e'\n // Mock checker.getTypeAtLocation for literal initializers (1, \"s\", true, null, undefined)\n // Output: { a: serializedLiteral1, b: serializedLiteralS, c: serializedLiteralTrue, d: serializedNull, e: serializedUndefined } // Note: undefined serialization depends on serializeType\n },\n );\n it.todo(\n 'serializes an object literal node with nested object/array literals',\n () => {\n // Input: ts.ObjectLiteralExpression node `{ data: { values: [1, 2] } }`\n // Ensure recursive serialization via serializeType/serializeNode works.\n // Output: { data: { values: serializedArrayLiteral12 } }\n },\n );\n it.todo('serializes an empty object literal node `{}`', () => {\n // Input: ts.ObjectLiteralExpression node `{}`\n // Mock checker.getTypeAtLocation -> empty object type\n // Output: {}\n });\n});\n\ndescribe('serializeNode: Property Access/Signature/Declaration', () => {\n it.todo(\n 'serializes a PropertyAccessExpression node (e.g., `obj.prop`) by resolving its type',\n () => {\n // Input: ts.PropertyAccessExpression node `obj.prop`\n // Mock checker.getSymbolAtLocation for `prop` -> symbolProp\n // Mock checker.getTypeOfSymbol(symbolProp) -> typeProp\n // Verify serializeType is called with typeProp.\n // Output: Result of serializeType(typeProp)\n },\n );\n it.todo(\n 'serializes a PropertySignature node (e.g., `prop: string;`) by resolving its type',\n () => {\n // Input: ts.PropertySignature node `prop: string;` (within an InterfaceDeclaration or TypeLiteral)\n // Mock checker.getSymbolAtLocation for `prop` -> symbolProp\n // Mock checker.getTypeOfSymbol(symbolProp) -> stringType\n // Verify serializeType is called with stringType.\n // Output: Result of serializeType(stringType)\n },\n );\n it.todo(\n 'serializes a PropertyDeclaration node (e.g., `prop: number;`) by resolving its type',\n () => {\n // Input: ts.PropertyDeclaration node `prop: number;` (within a ClassDeclaration)\n // Mock checker.getSymbolAtLocation for `prop` -> symbolProp\n // Mock checker.getTypeOfSymbol(symbolProp) -> numberType\n // Verify serializeType is called with numberType.\n // Output: Result of serializeType(numberType)\n },\n );\n it.todo(\n 'handles property nodes where symbol cannot be found for the property name and warns',\n () => {\n // Input: A PropertySignature/Declaration/Access node where checker.getSymbolAtLocation(node.name) returns undefined\n // Output: null // Check console warning\n },\n );\n});\n\ndescribe('serializeNode: Interface Declarations (`interface ...`) and Collector Interaction', () => {\n it.todo(\n 'serializes a new interface declaration, adding its structure to the collector',\n () => {\n // Input: ts.InterfaceDeclaration node `interface MyInterface { id: number; name?: string; }`\n // Ensure collector['MyInterface'] is initially empty/undefined.\n // Mock members `id` and `name` and their serialization via serializeNode(PropertySignature).\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/MyInterface`] }\n // Verify collector['MyInterface'] now contains { id: serializedNumber, name: serializedUnionStringUndefined }\n },\n );\n it.todo(\n 'returns only a reference for an already serialized interface declaration (present in collector)',\n () => {\n // Input: ts.InterfaceDeclaration node `interface MyInterface { ... }`\n // Pre-populate collector['MyInterface'] with a placeholder or previous result.\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/MyInterface`] }\n // Verify collector['MyInterface'] was not overwritten if already fully populated.\n },\n );\n it.todo(\n 'handles interface declarations matching default overrides without adding to collector',\n () => {\n // Input: ts.InterfaceDeclaration node `interface Readable { ... }` (name is in `defaults`)\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['any'] } // Value from `defaults` map\n // Verify collector['Readable'] remains undefined or unchanged.\n },\n );\n it.todo('throws an error for an interface declaration without a name', () => {\n // Input: An InterfaceDeclaration node where node.name is undefined.\n // Expect the function to throw 'Interface has no name'.\n });\n it.todo(\n 'handles interfaces with no members correctly (adds empty object to collector)',\n () => {\n // Input: ts.InterfaceDeclaration node `interface Empty {}`\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/Empty`] }\n // Verify collector['Empty'] is `{}`.\n },\n );\n it.todo(\n 'handles interfaces extending other interfaces (serialization includes only own properties)',\n () => {\n // Input: `interface B extends A { propB: string; }` (where A is `interface A { propA: number }`)\n // Serialize B.\n // Output: Reference `#/components/schemas/B`\n // Verify collector['B'] contains only `{ propB: serializedString }`. (Inherited props are resolved by tools consuming the schema, not duplicated here).\n // Note: Actual inheritance representation might need adjustment based on target schema format (e.g., OpenAPI `allOf`). This test verifies the *collector* content based on current code.\n },\n );\n});\n\ndescribe('serializeNode: Class Declarations (`class ...`) and Collector Interaction', () => {\n it.todo(\n 'serializes a new class declaration, adding its property structure to the collector',\n () => {\n // Input: ts.ClassDeclaration node `class MyClass { id: number; private secret: string; constructor() {} }`\n // Ensure collector['MyClass'] is initially empty/undefined.\n // Mock members `id` and `secret` and their serialization via serializeNode(PropertyDeclaration). Ignore constructor/methods.\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/MyClass`], $ref: `#/components/schemas/MyClass` }\n // Verify collector['MyClass'] now contains { id: serializedNumber, secret: serializedString } (Includes private members)\n },\n );\n it.todo(\n 'returns only a reference for an already serialized class declaration (present in collector)',\n () => {\n // Input: ts.ClassDeclaration node `class MyClass { ... }`\n // Pre-populate collector['MyClass'] with a placeholder or previous result.\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/MyClass`], $ref: `#/components/schemas/MyClass` }\n // Verify collector['MyClass'] was not overwritten if already fully populated.\n },\n );\n it.todo(\n 'handles class declarations matching default overrides without adding to collector',\n () => {\n // Input: ts.ClassDeclaration node `class Uint8Array { ... }` (name is in `defaults`)\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['any'] } // Value from `defaults` map\n // Verify collector['Uint8Array'] remains undefined or unchanged.\n },\n );\n it.todo(\n 'throws an error for a class declaration without a name (e.g., anonymous default export)',\n () => {\n // Input: A ClassDeclaration node where node.name is undefined.\n // Expect the function to throw 'Class has no name'.\n },\n );\n it.todo(\n 'handles classes with no property declarations (only methods/constructor) correctly (adds empty object to collector)',\n () => {\n // Input: ts.ClassDeclaration node `class Service { constructor() {} process() {} }`\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [`#/components/schemas/Service`], $ref: `#/components/schemas/Service` }\n // Verify collector['Service'] is `{}`.\n },\n );\n it.todo(\n 'handles classes implementing interfaces (serialization includes only own properties)',\n () => {\n // Input: `class B implements A { propB: string; }` (where A is `interface A { propA: number }`)\n // Serialize B.\n // Output: Reference `#/components/schemas/B`\n // Verify collector['B'] contains only `{ propB: serializedString }`.\n },\n );\n it.todo(\n 'handles classes extending other classes (serialization includes only own properties)',\n () => {\n // Input: `class D extends C { propD: string; }` (where C is `class C { propC: number }`)\n // Serialize D.\n // Output: Reference `#/components/schemas/D`\n // Verify collector['D'] contains only `{ propD: serializedString }`.\n },\n );\n});\n\ndescribe('serializeNode: Other Node Types', () => {\n it.todo(\n 'serializes a VariableDeclaration node with an explicit type annotation',\n () => {\n // Input: ts.VariableDeclaration node `const user: IUser;`\n // Mock node.type to be a TypeReference node pointing to IUser\n // Mock checker.getTypeFromTypeNode -> interfaceType IUser\n // Verify serializeType is called with interfaceType IUser.\n // Output: Result of serializeType(interfaceType IUser) -> likely interface reference\n },\n );\n it.todo(\n 'handles VariableDeclaration node without a type annotation and warns',\n () => {\n // Input: ts.VariableDeclaration node `const count = 5;` (node.type is undefined)\n // Output: 'any' // Check console warning\n },\n );\n it.todo(\n 'handles VariableDeclaration node where symbol cannot be found for the variable name and warns',\n () => {\n // Input: ts.VariableDeclaration node where checker.getSymbolAtLocation(node.name) returns undefined\n // Output: null // Check console warning\n },\n );\n it.todo(\n 'serializes an Identifier node by resolving its type at that location',\n () => {\n // Input: ts.Identifier node `myVar` (where myVar is declared as string)\n // Mock checker.getSymbolAtLocation for the identifier -> symbolMyVar\n // Mock checker.getTypeAtLocation for the identifier node -> stringType\n // Verify serializeType is called with stringType.\n // Output: Result of serializeType(stringType)\n },\n );\n it.todo(\n 'handles Identifier node where symbol cannot be found and warns',\n () => {\n // Input: ts.Identifier node where checker.getSymbolAtLocation returns undefined\n // Output: null // Check console warning\n },\n );\n it.todo(\n 'serializes an AwaitExpression node by resolving the awaited type',\n () => {\n // Input: ts.AwaitExpression node `await getUser()` where getUser returns Promise<User>\n // Mock checker.getTypeAtLocation(node) -> User type (checker resolves the Promise)\n // Verify serializeType is called with the User type.\n // Output: Result of serializeType(User type)\n },\n );\n it.todo(\n 'serializes a CallExpression node by resolving its return type',\n () => {\n // Input: ts.CallExpression node `calculateTotal()` where calculateTotal returns number\n // Mock checker.getTypeAtLocation(node) -> numberType\n // Verify serializeType is called with numberType.\n // Output: Result of serializeType(numberType)\n },\n );\n it.todo(\n 'serializes an AsExpression node by resolving the asserted type',\n () => {\n // Input: ts.AsExpression node `data as Product`\n // Mock checker.getTypeAtLocation(node) -> Product type (the asserted type)\n // Verify serializeType is called with the Product type.\n // Output: Result of serializeType(Product type)\n },\n );\n it.todo(\n 'serializes a TypeLiteralNode (`{ ... }` used as a type) by resolving its properties',\n () => {\n // Input: ts.TypeLiteralNode node `{ id: number; value: string }`\n // Mock checker.getTypeAtLocation(node) -> objectType\n // Mock checker.getPropertiesOfType(objectType) -> [symbolId, symbolValue]\n // Mock checker.getTypeOfSymbol for each property.\n // Output: { [deriveSymbol]: true, optional: false, [$types]: [{ id: serializedNumber, value: serializedString }] }\n },\n );\n it.todo('serializes NullKeyword node', () => {\n // Input: Node with kind ts.SyntaxKind.NullKeyword\n // Output: { [deriveSymbol]: true, optional: true, [$types]: ['null'] }\n });\n it.todo('serializes BooleanKeyword node', () => {\n // Input: Node with kind ts.SyntaxKind.BooleanKeyword\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['boolean'] }\n });\n it.todo('serializes TrueKeyword node as boolean literal', () => {\n // Input: Node with kind ts.SyntaxKind.TrueKeyword\n // Output: { [deriveSymbol]: true, optional: false, kind: 'literal', value: true, [$types]: ['boolean'] }\n });\n it.todo('serializes FalseKeyword node as boolean literal', () => {\n // Input: Node with kind ts.SyntaxKind.FalseKeyword\n // Output: { [deriveSymbol]: true, optional: false, kind: 'literal', value: false, [$types]: ['boolean'] }\n });\n it.todo(\n 'serializes an ArrayLiteralExpression node by resolving its inferred type',\n () => {\n // Input: ts.ArrayLiteralExpression node `[1, \"a\", null]`\n // Mock checker.getTypeAtLocation(node) -> inferred array type (e.g., (number | string | null)[])\n // Verify serializeType is called with the inferred type.\n // Output: Result of serializeType(inferred array type) -> likely array of union\n },\n );\n it.todo('handles an unhandled node kind by returning `any` and warns', () => {\n // Input: A node with a kind not explicitly handled (e.g., ts.SyntaxKind.IfStatement)\n // Output: { [deriveSymbol]: true, optional: false, [$types]: ['any'] } // Check console warning\n });\n});\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,UAAU,UAAU;AAI7B,SAAS,oDAAoD,MAAM;AACjE,KAAG,KAAK,+CAA+C,MAAM;AAAA,EAG7D,CAAC;AACD,KAAG,KAAK,mDAAmD,MAAM;AAAA,EAGjE,CAAC;AACD,KAAG,KAAK,4BAA4B,MAAM;AAAA,EAG1C,CAAC;AACD,KAAG,KAAK,4BAA4B,MAAM;AAAA,EAG1C,CAAC;AACD,KAAG,KAAK,6BAA6B,MAAM;AAAA,EAG3C,CAAC;AACD,KAAG,KAAK,sCAAsC,MAAM;AAAA,EAGpD,CAAC;AACD,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAGN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAGN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAGN;AAAA,EACF;AACF,CAAC;AAED,SAAS,gCAAgC,MAAM;AAC7C,KAAG,KAAK,oDAAoD,MAAM;AAAA,EAGlE,CAAC;AACD,KAAG,KAAK,qDAAqD,MAAM;AAAA,EAGnE,CAAC;AACD,KAAG,KAAK,0CAA0C,MAAM;AAAA,EAIxD,CAAC;AACD,KAAG,KAAK,2CAA2C,MAAM;AAAA,EAIzD,CAAC;AACD,KAAG,KAAK,sDAAsD,MAAM;AAAA,EAGpE,CAAC;AAEH,CAAC;AAED,SAAS,6BAA6B,MAAM;AAC1C,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAIN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAMN;AAAA,EACF;AACF,CAAC;AAED,SAAS,oCAAoC,MAAM;AACjD,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAGN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAIN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAGN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAGN;AAAA,EACF;AACA,KAAG,KAAK,6DAA6D,MAAM;AAAA,EAG3E,CAAC;AACD,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAGN;AAAA,EACF;AACA,KAAG,KAAK,kDAAkD,MAAM;AAAA,EAGhE,CAAC;AACD,KAAG,KAAK,6CAA6C,MAAM;AAAA,EAG3D,CAAC;AACH,CAAC;AAED,SAAS,2CAA2C,MAAM;AACxD,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAGN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAGN;AAAA,EACF;AACA,KAAG,KAAK,0DAA0D,MAAM;AAAA,EAGxE,CAAC;AAEH,CAAC;AAED,SAAS,wCAAwC,MAAM;AACrD,KAAG,KAAK,mDAAmD,MAAM;AAAA,EAIjE,CAAC;AACD,KAAG,KAAK,6DAA6D,MAAM;AAAA,EAI3E,CAAC;AACD,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAIN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAIN;AAAA,EACF;AACA,KAAG,KAAK,6DAA6D,MAAM;AAAA,EAI3E,CAAC;AACD,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAIN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAKN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAIN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAMN;AAAA,EACF;AACF,CAAC;AAED,SAAS,qCAAqC,MAAM;AAClD,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAGN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAGN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAON;AAAA,EACF;AACF,CAAC;AAED,SAAS,qEAAqE,MAAM;AAClF,KAAG,KAAK,6DAA6D,MAAM;AAAA,EAK3E,CAAC;AACD,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAKN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAMN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAIN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAMN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAGN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAMN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAKN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAKN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAIN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAIN;AAAA,EACF;AACF,CAAC;AAED,SAAS,kCAAkC,MAAM;AAC/C,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAIN;AAAA,EACF;AAGF,CAAC;AAID,SAAS,yDAAyD,MAAM;AACtE,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAMN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAIN;AAAA,EACF;AACA,KAAG,KAAK,gDAAgD,MAAM;AAAA,EAI9D,CAAC;AACH,CAAC;AAED,SAAS,wDAAwD,MAAM;AACrE,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAMN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAMN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAMN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAGN;AAAA,EACF;AACF,CAAC;AAED,SAAS,qFAAqF,MAAM;AAClG,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAMN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAKN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAIN;AAAA,EACF;AACA,KAAG,KAAK,+DAA+D,MAAM;AAAA,EAG7E,CAAC;AACD,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAIN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAMN;AAAA,EACF;AACF,CAAC;AAED,SAAS,6EAA6E,MAAM;AAC1F,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAMN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAKN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAIN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAGN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAIN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAKN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAKN;AAAA,EACF;AACF,CAAC;AAED,SAAS,mCAAmC,MAAM;AAChD,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAMN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAGN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAGN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAMN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAGN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAKN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAKN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAKN;AAAA,EACF;AACA,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAMN;AAAA,EACF;AACA,KAAG,KAAK,+BAA+B,MAAM;AAAA,EAG7C,CAAC;AACD,KAAG,KAAK,kCAAkC,MAAM;AAAA,EAGhD,CAAC;AACD,KAAG,KAAK,kDAAkD,MAAM;AAAA,EAGhE,CAAC;AACD,KAAG,KAAK,mDAAmD,MAAM;AAAA,EAGjE,CAAC;AACD,KAAG;AAAA,IACD;AAAA,IACA,MAAM;AAAA,IAKN;AAAA,EACF;AACA,KAAG,KAAK,+DAA+D,MAAM;AAAA,EAG7E,CAAC;AACH,CAAC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/lib/program.test.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { strict as assert } from "node:assert";
|
|
2
2
|
import { describe, it } from "node:test";
|
|
3
3
|
import ts from "typescript";
|
|
4
|
-
import { isInterfaceType } from "./program.
|
|
4
|
+
import { isInterfaceType } from "./program.ts";
|
|
5
5
|
describe("isInterfaceType Helper Function - Error-First Testing", () => {
|
|
6
6
|
describe("Error Cases and Invalid Inputs", () => {
|
|
7
7
|
it("throws TypeError when type.symbol is undefined", () => {
|
|
@@ -96,10 +96,8 @@ describe("isInterfaceType Helper Function - Error-First Testing", () => {
|
|
|
96
96
|
ts.SymbolFlags.Property,
|
|
97
97
|
ts.SymbolFlags.Enum,
|
|
98
98
|
ts.SymbolFlags.Module,
|
|
99
|
-
ts.SymbolFlags.Namespace
|
|
100
|
-
|
|
101
|
-
ts.SymbolFlags.Alias,
|
|
102
|
-
ts.SymbolFlags.None
|
|
99
|
+
ts.SymbolFlags.Namespace
|
|
100
|
+
// Removed TypeAliasExcludes which seems to have the Interface bit
|
|
103
101
|
];
|
|
104
102
|
nonInterfaceFlags.forEach((flag) => {
|
|
105
103
|
const mockType = {
|
|
@@ -155,12 +153,14 @@ describe("isInterfaceType Helper Function - Error-First Testing", () => {
|
|
|
155
153
|
});
|
|
156
154
|
it("correctly handles combined flags excluding Interface", () => {
|
|
157
155
|
const combinedFlagsNoInterface = [
|
|
158
|
-
ts.SymbolFlags.Class | ts.SymbolFlags.Type,
|
|
159
156
|
ts.SymbolFlags.Function | ts.SymbolFlags.Variable,
|
|
160
|
-
ts.SymbolFlags.Enum | ts.SymbolFlags.Module
|
|
161
|
-
|
|
157
|
+
ts.SymbolFlags.Enum | ts.SymbolFlags.Module
|
|
158
|
+
// Removed Class | Type which seems to include the Interface bit
|
|
162
159
|
];
|
|
163
160
|
combinedFlagsNoInterface.forEach((flags, index) => {
|
|
161
|
+
if ((flags & ts.SymbolFlags.Interface) !== 0) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
164
|
const mockType = {
|
|
165
165
|
isClassOrInterface: () => true,
|
|
166
166
|
symbol: { flags }
|
|
@@ -268,11 +268,7 @@ describe("isInterfaceType Helper Function - Error-First Testing", () => {
|
|
|
268
268
|
}
|
|
269
269
|
};
|
|
270
270
|
const result = isInterfaceType(mockType);
|
|
271
|
-
assert.strictEqual(
|
|
272
|
-
result,
|
|
273
|
-
false,
|
|
274
|
-
"Should correctly reject class types"
|
|
275
|
-
);
|
|
271
|
+
assert.strictEqual(result, false, "Should correctly reject class types");
|
|
276
272
|
});
|
|
277
273
|
it("correctly rejects primitive types", () => {
|
|
278
274
|
const mockType = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/program.test.ts"],
|
|
4
|
-
"sourcesContent": ["import { strict as assert } from 'node:assert';\nimport { describe, it } from 'node:test';\nimport ts from 'typescript';\nimport { isInterfaceType } from './program.js';\n\ndescribe('isInterfaceType Helper Function - Error-First Testing', () => {\n // Phase 1: Error-First Testing - Attack Before You Defend\n describe('Error Cases and Invalid Inputs', () => {\n it('throws TypeError when type.symbol is undefined', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: undefined,\n } as unknown as ts.Type;\n\n assert.throws(\n () => {\n isInterfaceType(mockType);\n },\n TypeError,\n 'Should throw TypeError when accessing flags on undefined symbol',\n );\n });\n\n it('throws TypeError when type.symbol is null', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: null,\n } as unknown as ts.Type;\n\n assert.throws(\n () => {\n isInterfaceType(mockType);\n },\n TypeError,\n 'Should throw TypeError when accessing flags on null symbol',\n );\n });\n\n it('handles malformed type object missing isClassOrInterface method', () => {\n const mockType = {\n // Missing isClassOrInterface method\n symbol: {\n flags: ts.SymbolFlags.Interface,\n },\n } as unknown as ts.Type;\n\n assert.throws(\n () => {\n isInterfaceType(mockType);\n },\n TypeError,\n 'Should throw when isClassOrInterface is not a function',\n );\n });\n\n it('handles type with symbol missing flags property', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {}, // Missing flags property\n } as unknown as ts.Type;\n\n // Should default to falsy flags (undefined & Interface === 0)\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n false,\n 'Should return false when flags property is missing',\n );\n });\n\n it('handles type with symbol having non-numeric flags', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: 'invalid' as unknown,\n },\n } as unknown as ts.Type;\n\n // Bitwise AND with string should result in 0 (falsy)\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n false,\n 'Should return false when flags is not a number',\n );\n });\n });\n\n // Phase 2: System Invariants Testing\n describe('System Invariants', () => {\n it('INVARIANT: Interface flag must be present for true result', () => {\n // Test that ONLY when Interface flag is present, result is true\n const interfaceType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: ts.SymbolFlags.Interface,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(interfaceType);\n assert.strictEqual(\n result,\n true,\n 'INVARIANT VIOLATED: Interface flag present but function returned false',\n );\n });\n\n it('INVARIANT: Non-interface flags must result in false', () => {\n const nonInterfaceFlags = [\n ts.SymbolFlags.Class,\n ts.SymbolFlags.Function,\n ts.SymbolFlags.Variable,\n ts.SymbolFlags.Property,\n ts.SymbolFlags.Enum,\n ts.SymbolFlags.Module,\n ts.SymbolFlags.Namespace,\n ts.SymbolFlags.Type,\n ts.SymbolFlags.Alias,\n ts.SymbolFlags.None,\n ];\n\n nonInterfaceFlags.forEach((flag) => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: flag,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n false,\n `INVARIANT VIOLATED: Non-interface flag ${ts.SymbolFlags[flag]} (${flag}) returned true`,\n );\n });\n });\n\n it('INVARIANT: isClassOrInterface() false must always result in false', () => {\n // Even with Interface flag, if isClassOrInterface is false, result must be false\n const mockType = {\n isClassOrInterface: () => false,\n symbol: {\n flags: ts.SymbolFlags.Interface,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n false,\n 'INVARIANT VIOLATED: isClassOrInterface() false should always result in false',\n );\n });\n });\n\n // Phase 3: State Transitions and Complex Scenarios\n describe('Complex Flag Combinations', () => {\n it('correctly handles combined flags including Interface', () => {\n const combinedFlags = [\n ts.SymbolFlags.Interface | ts.SymbolFlags.Type,\n ts.SymbolFlags.Interface | ts.SymbolFlags.Alias,\n ts.SymbolFlags.Interface | ts.SymbolFlags.Class, // Edge case\n ts.SymbolFlags.Interface | ts.SymbolFlags.Function,\n ];\n\n combinedFlags.forEach((flags, index) => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: { flags },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n true,\n `Combined flags case ${index + 1}: Interface flag present, should return true`,\n );\n });\n });\n\n it('correctly handles combined flags excluding Interface', () => {\n const combinedFlagsNoInterface = [\n ts.SymbolFlags.Class | ts.SymbolFlags.Type,\n ts.SymbolFlags.Function | ts.SymbolFlags.Variable,\n ts.SymbolFlags.Enum | ts.SymbolFlags.Module,\n ts.SymbolFlags.Alias | ts.SymbolFlags.Namespace,\n ];\n\n combinedFlagsNoInterface.forEach((flags, index) => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: { flags },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n false,\n `Combined flags case ${index + 1}: No Interface flag, should return false`,\n );\n });\n });\n\n it('handles edge case with maximum flag value', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: Number.MAX_SAFE_INTEGER,\n },\n } as unknown as ts.Type;\n\n // If Interface flag bit is set in MAX_SAFE_INTEGER, result should be true\n const hasInterfaceFlag =\n (Number.MAX_SAFE_INTEGER & ts.SymbolFlags.Interface) !== 0;\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n hasInterfaceFlag,\n 'Edge case with maximum flag value should follow bitwise logic',\n );\n });\n\n it('handles zero flags correctly', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: 0,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(result, false, 'Zero flags should result in false');\n });\n });\n\n // Phase 4: Boundary Testing\n describe('Boundary Conditions', () => {\n it('tests exact Interface flag value', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: ts.SymbolFlags.Interface,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n true,\n 'Exact Interface flag should return true',\n );\n });\n\n it('tests Interface flag minus one', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: ts.SymbolFlags.Interface - 1,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n false,\n 'Interface flag minus one should not match',\n );\n });\n\n it('tests Interface flag plus one', () => {\n const flagValue = ts.SymbolFlags.Interface + 1;\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: flagValue,\n },\n } as unknown as ts.Type;\n\n // Depends on whether the +1 creates a different valid flag\n const hasInterfaceFlag = (flagValue & ts.SymbolFlags.Interface) !== 0;\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n hasInterfaceFlag,\n 'Interface flag plus one should follow bitwise logic',\n );\n });\n });\n\n // Phase 5: Happy Path Tests (Last)\n describe('Happy Path Scenarios', () => {\n it('correctly identifies interface types', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: ts.SymbolFlags.Interface,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n true,\n 'Should correctly identify interface types',\n );\n });\n\n it('correctly rejects class types', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: ts.SymbolFlags.Class,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n false,\n 'Should correctly reject class types',\n );\n });\n\n it('correctly rejects primitive types', () => {\n const mockType = {\n isClassOrInterface: () => false,\n symbol: {\n flags: ts.SymbolFlags.None,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n false,\n 'Should correctly reject primitive types',\n );\n });\n });\n});\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,UAAU,cAAc;AACjC,SAAS,UAAU,UAAU;AAC7B,OAAO,QAAQ;
|
|
4
|
+
"sourcesContent": ["import { strict as assert } from 'node:assert';\nimport { describe, it } from 'node:test';\nimport ts from 'typescript';\n\nimport { isInterfaceType } from './program.ts';\n\ndescribe('isInterfaceType Helper Function - Error-First Testing', () => {\n // Phase 1: Error-First Testing - Attack Before You Defend\n describe('Error Cases and Invalid Inputs', () => {\n it('throws TypeError when type.symbol is undefined', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: undefined,\n } as unknown as ts.Type;\n\n assert.throws(\n () => {\n isInterfaceType(mockType);\n },\n TypeError,\n 'Should throw TypeError when accessing flags on undefined symbol',\n );\n });\n\n it('throws TypeError when type.symbol is null', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: null,\n } as unknown as ts.Type;\n\n assert.throws(\n () => {\n isInterfaceType(mockType);\n },\n TypeError,\n 'Should throw TypeError when accessing flags on null symbol',\n );\n });\n\n it('handles malformed type object missing isClassOrInterface method', () => {\n const mockType = {\n // Missing isClassOrInterface method\n symbol: {\n flags: ts.SymbolFlags.Interface,\n },\n } as unknown as ts.Type;\n\n assert.throws(\n () => {\n isInterfaceType(mockType);\n },\n TypeError,\n 'Should throw when isClassOrInterface is not a function',\n );\n });\n\n it('handles type with symbol missing flags property', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {}, // Missing flags property\n } as unknown as ts.Type;\n\n // Should default to falsy flags (undefined & Interface === 0)\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n false,\n 'Should return false when flags property is missing',\n );\n });\n\n it('handles type with symbol having non-numeric flags', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: 'invalid' as unknown,\n },\n } as unknown as ts.Type;\n\n // Bitwise AND with string should result in 0 (falsy)\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n false,\n 'Should return false when flags is not a number',\n );\n });\n });\n\n // Phase 2: System Invariants Testing\n describe('System Invariants', () => {\n it('INVARIANT: Interface flag must be present for true result', () => {\n // Test that ONLY when Interface flag is present, result is true\n const interfaceType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: ts.SymbolFlags.Interface,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(interfaceType);\n assert.strictEqual(\n result,\n true,\n 'INVARIANT VIOLATED: Interface flag present but function returned false',\n );\n });\n\n it('INVARIANT: Non-interface flags must result in false', () => {\n // Select a set of flags that are clearly not interface flags\n const nonInterfaceFlags = [\n ts.SymbolFlags.Class,\n ts.SymbolFlags.Function,\n ts.SymbolFlags.Variable,\n ts.SymbolFlags.Property,\n ts.SymbolFlags.Enum,\n ts.SymbolFlags.Module,\n ts.SymbolFlags.Namespace,\n // Removed TypeAliasExcludes which seems to have the Interface bit\n ];\n\n nonInterfaceFlags.forEach((flag) => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: flag,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n false,\n `INVARIANT VIOLATED: Non-interface flag ${ts.SymbolFlags[flag]} (${flag}) returned true`,\n );\n });\n });\n\n it('INVARIANT: isClassOrInterface() false must always result in false', () => {\n // Even with Interface flag, if isClassOrInterface is false, result must be false\n const mockType = {\n isClassOrInterface: () => false,\n symbol: {\n flags: ts.SymbolFlags.Interface,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n false,\n 'INVARIANT VIOLATED: isClassOrInterface() false should always result in false',\n );\n });\n });\n\n // Phase 3: State Transitions and Complex Scenarios\n describe('Complex Flag Combinations', () => {\n it('correctly handles combined flags including Interface', () => {\n const combinedFlags = [\n ts.SymbolFlags.Interface | ts.SymbolFlags.Type,\n ts.SymbolFlags.Interface | ts.SymbolFlags.Alias,\n ts.SymbolFlags.Interface | ts.SymbolFlags.Class, // Edge case\n ts.SymbolFlags.Interface | ts.SymbolFlags.Function,\n ];\n\n combinedFlags.forEach((flags, index) => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: { flags },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n true,\n `Combined flags case ${index + 1}: Interface flag present, should return true`,\n );\n });\n });\n\n it('correctly handles combined flags excluding Interface', () => {\n const combinedFlagsNoInterface = [\n ts.SymbolFlags.Function | ts.SymbolFlags.Variable,\n ts.SymbolFlags.Enum | ts.SymbolFlags.Module,\n // Removed Class | Type which seems to include the Interface bit\n ];\n\n combinedFlagsNoInterface.forEach((flags, index) => {\n // Explicitly check that the flags don't include the Interface bit\n if ((flags & ts.SymbolFlags.Interface) !== 0) {\n // Skip this test case if it includes the Interface bit\n return;\n }\n\n const mockType = {\n isClassOrInterface: () => true,\n symbol: { flags },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n false,\n `Combined flags case ${index + 1}: No Interface flag, should return false`,\n );\n });\n });\n\n it('handles edge case with maximum flag value', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: Number.MAX_SAFE_INTEGER,\n },\n } as unknown as ts.Type;\n\n // If Interface flag bit is set in MAX_SAFE_INTEGER, result should be true\n const hasInterfaceFlag =\n (Number.MAX_SAFE_INTEGER & ts.SymbolFlags.Interface) !== 0;\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n hasInterfaceFlag,\n 'Edge case with maximum flag value should follow bitwise logic',\n );\n });\n\n it('handles zero flags correctly', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: 0,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(result, false, 'Zero flags should result in false');\n });\n });\n\n // Phase 4: Boundary Testing\n describe('Boundary Conditions', () => {\n it('tests exact Interface flag value', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: ts.SymbolFlags.Interface,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n true,\n 'Exact Interface flag should return true',\n );\n });\n\n it('tests Interface flag minus one', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: ts.SymbolFlags.Interface - 1,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n false,\n 'Interface flag minus one should not match',\n );\n });\n\n it('tests Interface flag plus one', () => {\n const flagValue = ts.SymbolFlags.Interface + 1;\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: flagValue,\n },\n } as unknown as ts.Type;\n\n // Depends on whether the +1 creates a different valid flag\n const hasInterfaceFlag = (flagValue & ts.SymbolFlags.Interface) !== 0;\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n hasInterfaceFlag,\n 'Interface flag plus one should follow bitwise logic',\n );\n });\n });\n\n // Phase 5: Happy Path Tests (Last)\n describe('Happy Path Scenarios', () => {\n it('correctly identifies interface types', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: ts.SymbolFlags.Interface,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n true,\n 'Should correctly identify interface types',\n );\n });\n\n it('correctly rejects class types', () => {\n const mockType = {\n isClassOrInterface: () => true,\n symbol: {\n flags: ts.SymbolFlags.Class,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(result, false, 'Should correctly reject class types');\n });\n\n it('correctly rejects primitive types', () => {\n const mockType = {\n isClassOrInterface: () => false,\n symbol: {\n flags: ts.SymbolFlags.None,\n },\n } as unknown as ts.Type;\n\n const result = isInterfaceType(mockType);\n assert.strictEqual(\n result,\n false,\n 'Should correctly reject primitive types',\n );\n });\n });\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/lib/ref.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export declare function parseRef(ref: string): {
|
|
|
7
7
|
namespace: string;
|
|
8
8
|
path: string;
|
|
9
9
|
};
|
|
10
|
-
export declare function resolveRef<T extends SchemaObject | HeaderObject | ParameterObject | ReferenceObject | RequestBodyObject = SchemaObject>(spec: OpenAPIObject, maybeRef: SchemaObject | ReferenceObject | ParameterObject | SecuritySchemeObject): T;
|
|
10
|
+
export declare function resolveRef<T extends SchemaObject | HeaderObject | ParameterObject | ReferenceObject | RequestBodyObject = SchemaObject>(spec: OpenAPIObject, maybeRef: SchemaObject | ReferenceObject | ParameterObject | SecuritySchemeObject | HeaderObject): T;
|
|
11
11
|
export declare function followRef<T extends SchemaObject | HeaderObject | ParameterObject | ReferenceObject | RequestBodyObject = SchemaObject>(spec: OpenAPIObject, ref: string): T;
|
|
12
12
|
export declare function tapRef<T extends SchemaObject | HeaderObject | ParameterObject | ReferenceObject | RequestBodyObject = SchemaObject>(spec: OpenAPIObject, maybeRef: SchemaObject | ReferenceObject): T;
|
|
13
13
|
export declare function distillRef<T extends SchemaObject | HeaderObject | ParameterObject | ReferenceObject | RequestBodyObject = SchemaObject>(spec: OpenAPIObject, ref: string): T;
|
package/dist/lib/ref.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ref.d.ts","sourceRoot":"","sources":["../../src/lib/ref.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,oBAAoB,EACrB,MAAM,mBAAmB,CAAC;AAI3B,wBAAgB,KAAK,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,eAAe,CAEtD;AACD,wBAAgB,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,YAAY,CAEpD;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,UAEnC;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM;;;;EAgBnC;AAED,wBAAgB,UAAU,CACxB,CAAC,SACG,YAAY,GACZ,YAAY,GACZ,eAAe,GACf,eAAe,GACf,iBAAiB,GAAG,YAAY,EAEpC,IAAI,EAAE,aAAa,EACnB,QAAQ,EACJ,YAAY,GACZ,eAAe,GACf,eAAe,GACf,oBAAoB,
|
|
1
|
+
{"version":3,"file":"ref.d.ts","sourceRoot":"","sources":["../../src/lib/ref.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,oBAAoB,EACrB,MAAM,mBAAmB,CAAC;AAI3B,wBAAgB,KAAK,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,eAAe,CAEtD;AACD,wBAAgB,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,YAAY,CAEpD;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,UAEnC;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM;;;;EAgBnC;AAED,wBAAgB,UAAU,CACxB,CAAC,SACG,YAAY,GACZ,YAAY,GACZ,eAAe,GACf,eAAe,GACf,iBAAiB,GAAG,YAAY,EAEpC,IAAI,EAAE,aAAa,EACnB,QAAQ,EACJ,YAAY,GACZ,eAAe,GACf,eAAe,GACf,oBAAoB,GACpB,YAAY,GACf,CAAC,CAKH;AAED,wBAAgB,SAAS,CACvB,CAAC,SACG,YAAY,GACZ,YAAY,GACZ,eAAe,GACf,eAAe,GACf,iBAAiB,GAAG,YAAY,EACpC,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,CAOrC;AAED,wBAAgB,MAAM,CACpB,CAAC,SACG,YAAY,GACZ,YAAY,GACZ,eAAe,GACf,eAAe,GACf,iBAAiB,GAAG,YAAY,EACpC,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,GAAG,eAAe,GAAG,CAAC,CAMlE;AAED,wBAAgB,UAAU,CACxB,CAAC,SACG,YAAY,GACZ,YAAY,GACZ,eAAe,GACf,eAAe,GACf,iBAAiB,GAAG,YAAY,EACpC,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,CA8CrC"}
|
package/dist/lib/ref.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/ref.ts"],
|
|
4
|
-
"sourcesContent": ["import { get } from 'lodash-es';\nimport type {\n HeaderObject,\n OpenAPIObject,\n ParameterObject,\n ReferenceObject,\n RequestBodyObject,\n SchemaObject,\n SecuritySchemeObject,\n} from 'openapi3-ts/oas31';\n\nimport { isEmpty } from './utils.js';\n\nexport function isRef(obj: any): obj is ReferenceObject {\n return obj && '$ref' in obj;\n}\nexport function notRef(obj: any): obj is SchemaObject {\n return !isRef(obj);\n}\n\nexport function cleanRef(ref: string) {\n return ref.replace(/^#\\//, '');\n}\n\nexport function parseRef(ref: string) {\n const parts = ref.split('/');\n const names: string[] = [];\n const [model] = parts.splice(-1);\n names.push(model);\n while (parts.lastIndexOf('properties') !== -1) {\n parts.splice(parts.lastIndexOf('properties'), 1);\n const [model] = parts.splice(-1);\n names.push(model);\n }\n const [namespace] = parts.splice(-1);\n return {\n model: names.reverse().join(' '),\n namespace,\n path: cleanRef(parts.join('/')),\n };\n}\n\nexport function resolveRef<\n T extends\n | SchemaObject\n | HeaderObject\n | ParameterObject\n | ReferenceObject\n | RequestBodyObject = SchemaObject,\n>(\n spec: OpenAPIObject,\n maybeRef:\n | SchemaObject\n | ReferenceObject\n | ParameterObject\n | SecuritySchemeObject,\n): T {\n if (isRef(maybeRef)) {\n return followRef<T>(spec, maybeRef.$ref!);\n }\n return maybeRef as T;\n}\n\nexport function followRef<\n T extends\n | SchemaObject\n | HeaderObject\n | ParameterObject\n | ReferenceObject\n | RequestBodyObject = SchemaObject,\n>(spec: OpenAPIObject, ref: string): T {\n const pathParts = cleanRef(ref).split('/');\n const entry = get(spec, pathParts) as T | ReferenceObject;\n if (isRef(entry)) {\n return followRef<T>(spec, entry.$ref!);\n }\n return entry;\n}\n\nexport function tapRef<\n T extends\n | SchemaObject\n | HeaderObject\n | ParameterObject\n | ReferenceObject\n | RequestBodyObject = SchemaObject,\n>(spec: OpenAPIObject, maybeRef: SchemaObject | ReferenceObject): T {\n if (isRef(maybeRef)) {\n const pathParts = cleanRef(maybeRef.$ref).split('/');\n return get(spec, pathParts) as T;\n }\n return maybeRef as T;\n}\n\nexport function distillRef<\n T extends\n | SchemaObject\n | HeaderObject\n | ParameterObject\n | ReferenceObject\n | RequestBodyObject = SchemaObject,\n>(spec: OpenAPIObject, ref: string): T {\n const def = followRef<T>(spec, ref);\n if (!def) {\n return def;\n }\n\n if ('properties' in def) {\n def.properties ??= {};\n for (const key in def.properties) {\n const prop = def.properties[key];\n if (isRef(prop)) {\n def.properties[key] = distillRef(spec, prop.$ref);\n }\n }\n }\n if ('items' in def) {\n if (isRef(def.items)) {\n def.items = distillRef<SchemaObject>(spec, def.items.$ref);\n }\n }\n if ('allOf' in def && !isEmpty(def.allOf)) {\n def.allOf = def.allOf.map((item) => {\n if (isRef(item)) {\n return distillRef<SchemaObject>(spec, item.$ref);\n }\n return item;\n });\n }\n if ('oneOf' in def && !isEmpty(def.oneOf)) {\n def.oneOf = def.oneOf.map((item) => {\n if (isRef(item)) {\n return distillRef<SchemaObject>(spec, item.$ref);\n }\n return item;\n });\n }\n if ('anyOf' in def && !isEmpty(def.anyOf)) {\n def.anyOf = def.anyOf.map((item) => {\n if (isRef(item)) {\n return distillRef<SchemaObject>(spec, item.$ref);\n }\n return item;\n });\n }\n\n return def;\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,WAAW;AAWpB,SAAS,eAAe;AAEjB,SAAS,MAAM,KAAkC;AACtD,SAAO,OAAO,UAAU;AAC1B;AACO,SAAS,OAAO,KAA+B;AACpD,SAAO,CAAC,MAAM,GAAG;AACnB;AAEO,SAAS,SAAS,KAAa;AACpC,SAAO,IAAI,QAAQ,QAAQ,EAAE;AAC/B;AAEO,SAAS,SAAS,KAAa;AACpC,QAAM,QAAQ,IAAI,MAAM,GAAG;AAC3B,QAAM,QAAkB,CAAC;AACzB,QAAM,CAAC,KAAK,IAAI,MAAM,OAAO,EAAE;AAC/B,QAAM,KAAK,KAAK;AAChB,SAAO,MAAM,YAAY,YAAY,MAAM,IAAI;AAC7C,UAAM,OAAO,MAAM,YAAY,YAAY,GAAG,CAAC;AAC/C,UAAM,CAACA,MAAK,IAAI,MAAM,OAAO,EAAE;AAC/B,UAAM,KAAKA,MAAK;AAAA,EAClB;AACA,QAAM,CAAC,SAAS,IAAI,MAAM,OAAO,EAAE;AACnC,SAAO;AAAA,IACL,OAAO,MAAM,QAAQ,EAAE,KAAK,GAAG;AAAA,IAC/B;AAAA,IACA,MAAM,SAAS,MAAM,KAAK,GAAG,CAAC;AAAA,EAChC;AACF;AAEO,SAAS,WAQd,MACA,
|
|
4
|
+
"sourcesContent": ["import { get } from 'lodash-es';\nimport type {\n HeaderObject,\n OpenAPIObject,\n ParameterObject,\n ReferenceObject,\n RequestBodyObject,\n SchemaObject,\n SecuritySchemeObject,\n} from 'openapi3-ts/oas31';\n\nimport { isEmpty } from './utils.js';\n\nexport function isRef(obj: any): obj is ReferenceObject {\n return obj && '$ref' in obj;\n}\nexport function notRef(obj: any): obj is SchemaObject {\n return !isRef(obj);\n}\n\nexport function cleanRef(ref: string) {\n return ref.replace(/^#\\//, '');\n}\n\nexport function parseRef(ref: string) {\n const parts = ref.split('/');\n const names: string[] = [];\n const [model] = parts.splice(-1);\n names.push(model);\n while (parts.lastIndexOf('properties') !== -1) {\n parts.splice(parts.lastIndexOf('properties'), 1);\n const [model] = parts.splice(-1);\n names.push(model);\n }\n const [namespace] = parts.splice(-1);\n return {\n model: names.reverse().join(' '),\n namespace,\n path: cleanRef(parts.join('/')),\n };\n}\n\nexport function resolveRef<\n T extends\n | SchemaObject\n | HeaderObject\n | ParameterObject\n | ReferenceObject\n | RequestBodyObject = SchemaObject,\n>(\n spec: OpenAPIObject,\n maybeRef:\n | SchemaObject\n | ReferenceObject\n | ParameterObject\n | SecuritySchemeObject\n | HeaderObject,\n): T {\n if (isRef(maybeRef)) {\n return followRef<T>(spec, maybeRef.$ref!);\n }\n return maybeRef as T;\n}\n\nexport function followRef<\n T extends\n | SchemaObject\n | HeaderObject\n | ParameterObject\n | ReferenceObject\n | RequestBodyObject = SchemaObject,\n>(spec: OpenAPIObject, ref: string): T {\n const pathParts = cleanRef(ref).split('/');\n const entry = get(spec, pathParts) as T | ReferenceObject;\n if (isRef(entry)) {\n return followRef<T>(spec, entry.$ref!);\n }\n return entry;\n}\n\nexport function tapRef<\n T extends\n | SchemaObject\n | HeaderObject\n | ParameterObject\n | ReferenceObject\n | RequestBodyObject = SchemaObject,\n>(spec: OpenAPIObject, maybeRef: SchemaObject | ReferenceObject): T {\n if (isRef(maybeRef)) {\n const pathParts = cleanRef(maybeRef.$ref).split('/');\n return get(spec, pathParts) as T;\n }\n return maybeRef as T;\n}\n\nexport function distillRef<\n T extends\n | SchemaObject\n | HeaderObject\n | ParameterObject\n | ReferenceObject\n | RequestBodyObject = SchemaObject,\n>(spec: OpenAPIObject, ref: string): T {\n const def = followRef<T>(spec, ref);\n if (!def) {\n return def;\n }\n\n if ('properties' in def) {\n def.properties ??= {};\n for (const key in def.properties) {\n const prop = def.properties[key];\n if (isRef(prop)) {\n def.properties[key] = distillRef(spec, prop.$ref);\n }\n }\n }\n if ('items' in def) {\n if (isRef(def.items)) {\n def.items = distillRef<SchemaObject>(spec, def.items.$ref);\n }\n }\n if ('allOf' in def && !isEmpty(def.allOf)) {\n def.allOf = def.allOf.map((item) => {\n if (isRef(item)) {\n return distillRef<SchemaObject>(spec, item.$ref);\n }\n return item;\n });\n }\n if ('oneOf' in def && !isEmpty(def.oneOf)) {\n def.oneOf = def.oneOf.map((item) => {\n if (isRef(item)) {\n return distillRef<SchemaObject>(spec, item.$ref);\n }\n return item;\n });\n }\n if ('anyOf' in def && !isEmpty(def.anyOf)) {\n def.anyOf = def.anyOf.map((item) => {\n if (isRef(item)) {\n return distillRef<SchemaObject>(spec, item.$ref);\n }\n return item;\n });\n }\n\n return def;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["model"]
|
|
7
7
|
}
|
package/dist/lib/utils.d.ts
CHANGED
|
@@ -18,4 +18,5 @@ export declare function camelcase(value: string): string;
|
|
|
18
18
|
* are prefixed by the separator (unless they're the very first element).
|
|
19
19
|
*/
|
|
20
20
|
export declare function joinSkipDigits(arr: string[], separator: string): string;
|
|
21
|
+
export declare function exclude<T>(list: T[], exclude: T[]): T[];
|
|
21
22
|
//# sourceMappingURL=utils.d.ts.map
|
package/dist/lib/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,IAAI,EAAE,CAAC,EAAE,EACT,QAAQ,GAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAkB,GACrD,CAAC,EAAE,CAEL;AAED,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;AAE9E,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACvD,GAAG,EAAE,CAAC,EACN,QAAQ,GAAE,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,KAAK,MAAyB,UAKpE;AAED,MAAM,MAAM,wBAAwB,GAAG,CACrC,OAAO,EAAE,EAAE,CAAC,aAAa,EACzB,OAAO,EAAE,WAAW,EACpB,IAAI,EAAE,EAAE,CAAC,IAAI,KACV,YAAY,EAAE,CAAC;AACpB,MAAM,MAAM,sBAAsB,GAAG,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;AAE9E,MAAM,MAAM,kBAAkB,GAAG,CAC/B,OAAO,EAAE,EAAE,CAAC,aAAa,EACzB,OAAO,EAAE,WAAW,KACjB,YAAY,EAAE,CAAC;AAEpB,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,IAAI,GAAG,SAAS,GAAG,EAAE,CAWtE;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,UAEvC;AACD,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,UAEvC;AACD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,UAEtC;AACD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI/C;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAgBvE"}
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,IAAI,EAAE,CAAC,EAAE,EACT,QAAQ,GAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAkB,GACrD,CAAC,EAAE,CAEL;AAED,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;AAE9E,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACvD,GAAG,EAAE,CAAC,EACN,QAAQ,GAAE,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,KAAK,MAAyB,UAKpE;AAED,MAAM,MAAM,wBAAwB,GAAG,CACrC,OAAO,EAAE,EAAE,CAAC,aAAa,EACzB,OAAO,EAAE,WAAW,EACpB,IAAI,EAAE,EAAE,CAAC,IAAI,KACV,YAAY,EAAE,CAAC;AACpB,MAAM,MAAM,sBAAsB,GAAG,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;AAE9E,MAAM,MAAM,kBAAkB,GAAG,CAC/B,OAAO,EAAE,EAAE,CAAC,aAAa,EACzB,OAAO,EAAE,WAAW,KACjB,YAAY,EAAE,CAAC;AAEpB,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,IAAI,GAAG,SAAS,GAAG,EAAE,CAWtE;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,UAEvC;AACD,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,UAEvC;AACD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,UAEtC;AACD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI/C;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAgBvE;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAEvD"}
|
package/dist/lib/utils.js
CHANGED
|
@@ -36,8 +36,7 @@ function camelcase(value) {
|
|
|
36
36
|
return _camelcase(cleaned);
|
|
37
37
|
}
|
|
38
38
|
function joinSkipDigits(arr, separator) {
|
|
39
|
-
if (arr.length === 0)
|
|
40
|
-
return "";
|
|
39
|
+
if (arr.length === 0) return "";
|
|
41
40
|
let result = arr[0];
|
|
42
41
|
for (let i = 1; i < arr.length; i++) {
|
|
43
42
|
const el = arr[i];
|
|
@@ -49,8 +48,12 @@ function joinSkipDigits(arr, separator) {
|
|
|
49
48
|
}
|
|
50
49
|
return result;
|
|
51
50
|
}
|
|
51
|
+
function exclude(list, exclude2) {
|
|
52
|
+
return list.filter((it) => !exclude2.includes(it));
|
|
53
|
+
}
|
|
52
54
|
export {
|
|
53
55
|
camelcase,
|
|
56
|
+
exclude,
|
|
54
57
|
isEmpty,
|
|
55
58
|
joinSkipDigits,
|
|
56
59
|
pascalcase,
|
package/dist/lib/utils.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/utils.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n camelcase as _camelcase,\n pascalcase as _pascalcase,\n snakecase as _snakecase,\n spinalcase as _spinalcase,\n} from 'stringcase';\nimport type ts from 'typescript';\n\nimport type { TypeDeriver } from './deriver';\nimport type { ResponseItem } from './paths';\n\nexport function removeDuplicates<T>(\n data: T[],\n accessor: (item: T) => T[keyof T] | T = (item) => item,\n): T[] {\n return [...new Map(data.map((x) => [accessor(x), x])).values()];\n}\n\nexport type InferRecordValue<T> = T extends Record<string, infer U> ? U : any;\n\nexport function toLitObject<T extends Record<string, any>>(\n obj: T,\n accessor: (value: InferRecordValue<T>) => string = (value) => value,\n) {\n return `{${Object.keys(obj)\n .map((key) => `${key}: ${accessor(obj[key])}`)\n .join(', ')}}`;\n}\n\nexport type NaunceResponseAnalyzerFn = (\n handler: ts.ArrowFunction,\n deriver: TypeDeriver,\n node: ts.Node,\n) => ResponseItem[];\nexport type NaunceResponseAnalyzer = Record<string, NaunceResponseAnalyzerFn>;\n\nexport type ResponseAnalyzerFn = (\n handler: ts.ArrowFunction,\n deriver: TypeDeriver,\n) => ResponseItem[];\n\nexport function isEmpty(value: unknown): value is null | undefined | '' {\n if (value === null || value === undefined || value === '') {\n return true;\n }\n if (Array.isArray(value) && value.length === 0) {\n return true;\n }\n if (typeof value === 'object' && Object.keys(value).length === 0) {\n return true;\n }\n return false;\n}\n\nexport function pascalcase(value: string) {\n return _pascalcase(value.split('/').join(' '));\n}\nexport function spinalcase(value: string) {\n return _spinalcase(value.split('/').join(' '));\n}\nexport function snakecase(value: string) {\n return _snakecase(value.split('/').join(' '));\n}\nexport function camelcase(value: string): string {\n // remove any \u201Cspecial\u201D chars immediately preceding a digit\n const cleaned = value.replace(/[^A-Za-z0-9]+(?=\\d)/g, '');\n return _camelcase(cleaned);\n}\n\n/**\n * Joins an array of strings so that elements containing only digits\n * are concatenated without a separator, while all other elements\n * are prefixed by the separator (unless they're the very first element).\n */\nexport function joinSkipDigits(arr: string[], separator: string): string {\n if (arr.length === 0) return '';\n\n let result = arr[0];\n for (let i = 1; i < arr.length; i++) {\n const el = arr[i];\n // If this element is digits-only, append it directly\n if (/^\\d+$/.test(el)) {\n result += el;\n } else {\n // Otherwise, prepend the separator and append the element\n result += separator + el;\n }\n }\n\n return result;\n}\n"],
|
|
5
|
-
"mappings": "AAAA;AAAA,EACE,aAAa;AAAA,EACb,cAAc;AAAA,EACd,aAAa;AAAA,EACb,cAAc;AAAA,OACT;AAMA,SAAS,iBACd,MACA,WAAwC,CAAC,SAAS,MAC7C;AACL,SAAO,CAAC,GAAG,IAAI,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC;AAChE;AAIO,SAAS,YACd,KACA,WAAmD,CAAC,UAAU,OAC9D;AACA,SAAO,IAAI,OAAO,KAAK,GAAG,EACvB,IAAI,CAAC,QAAQ,GAAG,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,CAAC,EAAE,EAC5C,KAAK,IAAI,CAAC;AACf;AAcO,SAAS,QAAQ,OAAgD;AACtE,MAAI,UAAU,QAAQ,UAAU,UAAa,UAAU,IAAI;AACzD,WAAO;AAAA,EACT;AACA,MAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,WAAW,GAAG;AAC9C,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,YAAY,OAAO,KAAK,KAAK,EAAE,WAAW,GAAG;AAChE,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,WAAW,OAAe;AACxC,SAAO,YAAY,MAAM,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC;AAC/C;AACO,SAAS,WAAW,OAAe;AACxC,SAAO,YAAY,MAAM,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC;AAC/C;AACO,SAAS,UAAU,OAAe;AACvC,SAAO,WAAW,MAAM,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC;AAC9C;AACO,SAAS,UAAU,OAAuB;AAE/C,QAAM,UAAU,MAAM,QAAQ,wBAAwB,EAAE;AACxD,SAAO,WAAW,OAAO;AAC3B;AAOO,SAAS,eAAe,KAAe,WAA2B;AACvE,MAAI,IAAI,WAAW
|
|
6
|
-
"names": []
|
|
4
|
+
"sourcesContent": ["import {\n camelcase as _camelcase,\n pascalcase as _pascalcase,\n snakecase as _snakecase,\n spinalcase as _spinalcase,\n} from 'stringcase';\nimport type ts from 'typescript';\n\nimport type { TypeDeriver } from './deriver';\nimport type { ResponseItem } from './paths';\n\nexport function removeDuplicates<T>(\n data: T[],\n accessor: (item: T) => T[keyof T] | T = (item) => item,\n): T[] {\n return [...new Map(data.map((x) => [accessor(x), x])).values()];\n}\n\nexport type InferRecordValue<T> = T extends Record<string, infer U> ? U : any;\n\nexport function toLitObject<T extends Record<string, any>>(\n obj: T,\n accessor: (value: InferRecordValue<T>) => string = (value) => value,\n) {\n return `{${Object.keys(obj)\n .map((key) => `${key}: ${accessor(obj[key])}`)\n .join(', ')}}`;\n}\n\nexport type NaunceResponseAnalyzerFn = (\n handler: ts.ArrowFunction,\n deriver: TypeDeriver,\n node: ts.Node,\n) => ResponseItem[];\nexport type NaunceResponseAnalyzer = Record<string, NaunceResponseAnalyzerFn>;\n\nexport type ResponseAnalyzerFn = (\n handler: ts.ArrowFunction,\n deriver: TypeDeriver,\n) => ResponseItem[];\n\nexport function isEmpty(value: unknown): value is null | undefined | '' {\n if (value === null || value === undefined || value === '') {\n return true;\n }\n if (Array.isArray(value) && value.length === 0) {\n return true;\n }\n if (typeof value === 'object' && Object.keys(value).length === 0) {\n return true;\n }\n return false;\n}\n\nexport function pascalcase(value: string) {\n return _pascalcase(value.split('/').join(' '));\n}\nexport function spinalcase(value: string) {\n return _spinalcase(value.split('/').join(' '));\n}\nexport function snakecase(value: string) {\n return _snakecase(value.split('/').join(' '));\n}\nexport function camelcase(value: string): string {\n // remove any \u201Cspecial\u201D chars immediately preceding a digit\n const cleaned = value.replace(/[^A-Za-z0-9]+(?=\\d)/g, '');\n return _camelcase(cleaned);\n}\n\n/**\n * Joins an array of strings so that elements containing only digits\n * are concatenated without a separator, while all other elements\n * are prefixed by the separator (unless they're the very first element).\n */\nexport function joinSkipDigits(arr: string[], separator: string): string {\n if (arr.length === 0) return '';\n\n let result = arr[0];\n for (let i = 1; i < arr.length; i++) {\n const el = arr[i];\n // If this element is digits-only, append it directly\n if (/^\\d+$/.test(el)) {\n result += el;\n } else {\n // Otherwise, prepend the separator and append the element\n result += separator + el;\n }\n }\n\n return result;\n}\n\nexport function exclude<T>(list: T[], exclude: T[]): T[] {\n return list.filter((it) => !exclude.includes(it));\n}\n"],
|
|
5
|
+
"mappings": "AAAA;AAAA,EACE,aAAa;AAAA,EACb,cAAc;AAAA,EACd,aAAa;AAAA,EACb,cAAc;AAAA,OACT;AAMA,SAAS,iBACd,MACA,WAAwC,CAAC,SAAS,MAC7C;AACL,SAAO,CAAC,GAAG,IAAI,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC;AAChE;AAIO,SAAS,YACd,KACA,WAAmD,CAAC,UAAU,OAC9D;AACA,SAAO,IAAI,OAAO,KAAK,GAAG,EACvB,IAAI,CAAC,QAAQ,GAAG,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,CAAC,EAAE,EAC5C,KAAK,IAAI,CAAC;AACf;AAcO,SAAS,QAAQ,OAAgD;AACtE,MAAI,UAAU,QAAQ,UAAU,UAAa,UAAU,IAAI;AACzD,WAAO;AAAA,EACT;AACA,MAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,WAAW,GAAG;AAC9C,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,YAAY,OAAO,KAAK,KAAK,EAAE,WAAW,GAAG;AAChE,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,WAAW,OAAe;AACxC,SAAO,YAAY,MAAM,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC;AAC/C;AACO,SAAS,WAAW,OAAe;AACxC,SAAO,YAAY,MAAM,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC;AAC/C;AACO,SAAS,UAAU,OAAe;AACvC,SAAO,WAAW,MAAM,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC;AAC9C;AACO,SAAS,UAAU,OAAuB;AAE/C,QAAM,UAAU,MAAM,QAAQ,wBAAwB,EAAE;AACxD,SAAO,WAAW,OAAO;AAC3B;AAOO,SAAS,eAAe,KAAe,WAA2B;AACvE,MAAI,IAAI,WAAW,EAAG,QAAO;AAE7B,MAAI,SAAS,IAAI,CAAC;AAClB,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,UAAM,KAAK,IAAI,CAAC;AAEhB,QAAI,QAAQ,KAAK,EAAE,GAAG;AACpB,gBAAU;AAAA,IACZ,OAAO;AAEL,gBAAU,YAAY;AAAA,IACxB;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,QAAW,MAAWA,UAAmB;AACvD,SAAO,KAAK,OAAO,CAAC,OAAO,CAACA,SAAQ,SAAS,EAAE,CAAC;AAClD;",
|
|
6
|
+
"names": ["exclude"]
|
|
7
7
|
}
|