@formspec/cli 0.1.0-alpha.10
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/README.md +480 -0
- package/dist/__tests__/analyzer.test.d.ts +8 -0
- package/dist/__tests__/analyzer.test.d.ts.map +1 -0
- package/dist/__tests__/analyzer.test.js +70 -0
- package/dist/__tests__/analyzer.test.js.map +1 -0
- package/dist/__tests__/codegen.test.d.ts +8 -0
- package/dist/__tests__/codegen.test.d.ts.map +1 -0
- package/dist/__tests__/codegen.test.js +51 -0
- package/dist/__tests__/codegen.test.js.map +1 -0
- package/dist/__tests__/edge-cases.test.d.ts +12 -0
- package/dist/__tests__/edge-cases.test.d.ts.map +1 -0
- package/dist/__tests__/edge-cases.test.js +169 -0
- package/dist/__tests__/edge-cases.test.js.map +1 -0
- package/dist/__tests__/fixtures/edge-cases.d.ts +110 -0
- package/dist/__tests__/fixtures/edge-cases.d.ts.map +1 -0
- package/dist/__tests__/fixtures/edge-cases.js +137 -0
- package/dist/__tests__/fixtures/edge-cases.js.map +1 -0
- package/dist/__tests__/fixtures/sample-forms.d.ts +55 -0
- package/dist/__tests__/fixtures/sample-forms.d.ts.map +1 -0
- package/dist/__tests__/fixtures/sample-forms.js +78 -0
- package/dist/__tests__/fixtures/sample-forms.js.map +1 -0
- package/dist/__tests__/integration.test.d.ts +5 -0
- package/dist/__tests__/integration.test.d.ts.map +1 -0
- package/dist/__tests__/integration.test.js +186 -0
- package/dist/__tests__/integration.test.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +374 -0
- package/dist/index.js.map +1 -0
- package/dist/output/writer.d.ts +82 -0
- package/dist/output/writer.d.ts.map +1 -0
- package/dist/output/writer.js +152 -0
- package/dist/output/writer.js.map +1 -0
- package/dist/runtime/formspec-loader.d.ts +80 -0
- package/dist/runtime/formspec-loader.d.ts.map +1 -0
- package/dist/runtime/formspec-loader.js +152 -0
- package/dist/runtime/formspec-loader.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edge case and negative tests for CLI-specific components.
|
|
3
|
+
*
|
|
4
|
+
* Tests cover:
|
|
5
|
+
* - isFormSpec detection edge cases
|
|
6
|
+
* - File I/O error handling (output writer)
|
|
7
|
+
* - FormSpec loading failures
|
|
8
|
+
*
|
|
9
|
+
* Note: Analysis and generation edge cases are tested in @formspec/build.
|
|
10
|
+
*/
|
|
11
|
+
import { describe, it, expect, beforeAll, afterAll } from "vitest";
|
|
12
|
+
import * as fs from "node:fs";
|
|
13
|
+
import * as path from "node:path";
|
|
14
|
+
import * as os from "node:os";
|
|
15
|
+
import { createProgramContext, findClassByName, analyzeClass, generateClassSchemas, } from "@formspec/build/internals";
|
|
16
|
+
import { loadFormSpecs, isFormSpec } from "../runtime/formspec-loader.js";
|
|
17
|
+
import { writeClassSchemas } from "../output/writer.js";
|
|
18
|
+
const fixturesDir = path.join(__dirname, "fixtures");
|
|
19
|
+
const edgeCasesPath = path.join(fixturesDir, "edge-cases.ts");
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// isFormSpec Edge Cases
|
|
22
|
+
// ============================================================================
|
|
23
|
+
describe("isFormSpec - negative cases", () => {
|
|
24
|
+
it("rejects null", () => {
|
|
25
|
+
expect(isFormSpec(null)).toBe(false);
|
|
26
|
+
});
|
|
27
|
+
it("rejects undefined", () => {
|
|
28
|
+
expect(isFormSpec(undefined)).toBe(false);
|
|
29
|
+
});
|
|
30
|
+
it("rejects primitives", () => {
|
|
31
|
+
expect(isFormSpec("string")).toBe(false);
|
|
32
|
+
expect(isFormSpec(123)).toBe(false);
|
|
33
|
+
expect(isFormSpec(true)).toBe(false);
|
|
34
|
+
});
|
|
35
|
+
it("rejects object without elements", () => {
|
|
36
|
+
expect(isFormSpec({})).toBe(false);
|
|
37
|
+
expect(isFormSpec({ notElements: [] })).toBe(false);
|
|
38
|
+
});
|
|
39
|
+
it("rejects object with non-array elements", () => {
|
|
40
|
+
expect(isFormSpec({ elements: "not-array" })).toBe(false);
|
|
41
|
+
expect(isFormSpec({ elements: {} })).toBe(false);
|
|
42
|
+
expect(isFormSpec({ elements: null })).toBe(false);
|
|
43
|
+
});
|
|
44
|
+
it("rejects elements missing _type property", () => {
|
|
45
|
+
expect(isFormSpec({ elements: [{ id: "test" }] })).toBe(false);
|
|
46
|
+
expect(isFormSpec({ elements: [{ name: "test" }] })).toBe(false);
|
|
47
|
+
});
|
|
48
|
+
it("rejects elements with null values", () => {
|
|
49
|
+
expect(isFormSpec({ elements: [null] })).toBe(false);
|
|
50
|
+
expect(isFormSpec({ elements: [undefined] })).toBe(false);
|
|
51
|
+
});
|
|
52
|
+
it("accepts valid FormSpec-like object", () => {
|
|
53
|
+
expect(isFormSpec({
|
|
54
|
+
elements: [{ _type: "field", _field: "text", name: "test" }],
|
|
55
|
+
})).toBe(true);
|
|
56
|
+
});
|
|
57
|
+
it("accepts empty elements array", () => {
|
|
58
|
+
expect(isFormSpec({ elements: [] })).toBe(true);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
// ============================================================================
|
|
62
|
+
// File I/O Error Handling
|
|
63
|
+
// ============================================================================
|
|
64
|
+
describe("output writer - error handling", () => {
|
|
65
|
+
let tempDir;
|
|
66
|
+
beforeAll(() => {
|
|
67
|
+
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "formspec-test-"));
|
|
68
|
+
});
|
|
69
|
+
afterAll(() => {
|
|
70
|
+
if (tempDir && fs.existsSync(tempDir)) {
|
|
71
|
+
fs.rmSync(tempDir, { recursive: true });
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
it("creates output directory if it doesn't exist", () => {
|
|
75
|
+
const ctx = createProgramContext(edgeCasesPath);
|
|
76
|
+
const classDecl = findClassByName(ctx.sourceFile, "NullablePatterns");
|
|
77
|
+
if (!classDecl)
|
|
78
|
+
throw new Error("NullablePatterns class not found");
|
|
79
|
+
const analysis = analyzeClass(classDecl, ctx.checker);
|
|
80
|
+
const schemas = generateClassSchemas(analysis, ctx.checker);
|
|
81
|
+
const nonExistentDir = path.join(tempDir, "new-dir", "nested");
|
|
82
|
+
const result = writeClassSchemas(analysis.name, schemas, [], [], { outDir: nonExistentDir });
|
|
83
|
+
expect(fs.existsSync(result.dir)).toBe(true);
|
|
84
|
+
expect(fs.existsSync(path.join(result.dir, "schema.json"))).toBe(true);
|
|
85
|
+
});
|
|
86
|
+
it("overwrites existing files", () => {
|
|
87
|
+
const ctx = createProgramContext(edgeCasesPath);
|
|
88
|
+
const classDecl = findClassByName(ctx.sourceFile, "NullablePatterns");
|
|
89
|
+
if (!classDecl)
|
|
90
|
+
throw new Error("NullablePatterns class not found");
|
|
91
|
+
const analysis = analyzeClass(classDecl, ctx.checker);
|
|
92
|
+
const schemas = generateClassSchemas(analysis, ctx.checker);
|
|
93
|
+
const outputDir = path.join(tempDir, "overwrite-test");
|
|
94
|
+
// Write first time
|
|
95
|
+
writeClassSchemas(analysis.name, schemas, [], [], { outDir: outputDir });
|
|
96
|
+
// Modify the schema
|
|
97
|
+
const modifiedSchemas = {
|
|
98
|
+
...schemas,
|
|
99
|
+
jsonSchema: { ...schemas.jsonSchema, title: "Modified" },
|
|
100
|
+
};
|
|
101
|
+
// Write second time (should overwrite)
|
|
102
|
+
const result = writeClassSchemas(analysis.name, modifiedSchemas, [], [], { outDir: outputDir });
|
|
103
|
+
const content = JSON.parse(fs.readFileSync(path.join(result.dir, "schema.json"), "utf-8"));
|
|
104
|
+
expect(content.title).toBe("Modified");
|
|
105
|
+
});
|
|
106
|
+
it("handles special characters in class names", () => {
|
|
107
|
+
const ctx = createProgramContext(edgeCasesPath);
|
|
108
|
+
const classDecl = findClassByName(ctx.sourceFile, "MixedUnionTypes");
|
|
109
|
+
if (!classDecl)
|
|
110
|
+
throw new Error("MixedUnionTypes class not found");
|
|
111
|
+
const analysis = analyzeClass(classDecl, ctx.checker);
|
|
112
|
+
const schemas = generateClassSchemas(analysis, ctx.checker);
|
|
113
|
+
const result = writeClassSchemas(analysis.name, schemas, [], [], { outDir: tempDir });
|
|
114
|
+
expect(fs.existsSync(result.dir)).toBe(true);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
// ============================================================================
|
|
118
|
+
// FormSpec Loading Failures
|
|
119
|
+
// ============================================================================
|
|
120
|
+
describe("loadFormSpecs - error handling", () => {
|
|
121
|
+
let tempDir;
|
|
122
|
+
beforeAll(() => {
|
|
123
|
+
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "formspec-load-test-"));
|
|
124
|
+
});
|
|
125
|
+
afterAll(() => {
|
|
126
|
+
if (tempDir && fs.existsSync(tempDir)) {
|
|
127
|
+
fs.rmSync(tempDir, { recursive: true });
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
it("handles non-existent file", async () => {
|
|
131
|
+
const nonExistentPath = path.join(tempDir, "does-not-exist.js");
|
|
132
|
+
await expect(loadFormSpecs(nonExistentPath)).rejects.toThrow();
|
|
133
|
+
});
|
|
134
|
+
it("handles file with syntax error", async () => {
|
|
135
|
+
const badFilePath = path.join(tempDir, "syntax-error.mjs");
|
|
136
|
+
fs.writeFileSync(badFilePath, "export const broken = {{{");
|
|
137
|
+
await expect(loadFormSpecs(badFilePath)).rejects.toThrow();
|
|
138
|
+
});
|
|
139
|
+
it("handles file with no exports", async () => {
|
|
140
|
+
const emptyFilePath = path.join(tempDir, "empty.mjs");
|
|
141
|
+
fs.writeFileSync(emptyFilePath, "// Empty file\nconst x = 1;");
|
|
142
|
+
const { formSpecs } = await loadFormSpecs(emptyFilePath);
|
|
143
|
+
expect(formSpecs.size).toBe(0);
|
|
144
|
+
});
|
|
145
|
+
it("handles file with non-FormSpec exports", async () => {
|
|
146
|
+
const nonFormSpecPath = path.join(tempDir, "non-formspec.mjs");
|
|
147
|
+
fs.writeFileSync(nonFormSpecPath, `
|
|
148
|
+
export const notAFormSpec = { foo: "bar" };
|
|
149
|
+
export const alsoNot = [1, 2, 3];
|
|
150
|
+
export function aFunction() { return 1; }
|
|
151
|
+
`);
|
|
152
|
+
const { formSpecs } = await loadFormSpecs(nonFormSpecPath);
|
|
153
|
+
expect(formSpecs.size).toBe(0);
|
|
154
|
+
});
|
|
155
|
+
it("handles mixed exports (some FormSpec, some not)", async () => {
|
|
156
|
+
const mixedPath = path.join(tempDir, "mixed.mjs");
|
|
157
|
+
fs.writeFileSync(mixedPath, `
|
|
158
|
+
export const validFormSpec = {
|
|
159
|
+
elements: [{ _type: "field", _field: "text", name: "test" }]
|
|
160
|
+
};
|
|
161
|
+
export const notFormSpec = { foo: "bar" };
|
|
162
|
+
`);
|
|
163
|
+
const { formSpecs } = await loadFormSpecs(mixedPath);
|
|
164
|
+
expect(formSpecs.size).toBe(1);
|
|
165
|
+
expect(formSpecs.has("validFormSpec")).toBe(true);
|
|
166
|
+
expect(formSpecs.has("notFormSpec")).toBe(false);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
//# sourceMappingURL=edge-cases.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edge-cases.test.js","sourceRoot":"","sources":["../../src/__tests__/edge-cases.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edge case fixtures for testing type converter and analyzer.
|
|
3
|
+
*
|
|
4
|
+
* These test various TypeScript type patterns that might cause issues.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Mixed type union (not just literals) - should produce oneOf.
|
|
8
|
+
*/
|
|
9
|
+
export declare class MixedUnionTypes {
|
|
10
|
+
mixedPrimitive: string | number;
|
|
11
|
+
complexUnion: string | {
|
|
12
|
+
nested: boolean;
|
|
13
|
+
};
|
|
14
|
+
objectUnion: {
|
|
15
|
+
type: "a";
|
|
16
|
+
valueA: string;
|
|
17
|
+
} | {
|
|
18
|
+
type: "b";
|
|
19
|
+
valueB: number;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Various nullable patterns.
|
|
24
|
+
*/
|
|
25
|
+
export declare class NullablePatterns {
|
|
26
|
+
nullableString: string | null;
|
|
27
|
+
undefinedString: string | undefined;
|
|
28
|
+
optionalNullable?: string | null;
|
|
29
|
+
tripleUnion: string | null | undefined;
|
|
30
|
+
nullableStatus: "active" | "inactive" | null;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Various array patterns.
|
|
34
|
+
*/
|
|
35
|
+
export declare class ArrayEdgeCases {
|
|
36
|
+
strings: string[];
|
|
37
|
+
mixedArray: (string | number)[];
|
|
38
|
+
nullableArray: string[] | null;
|
|
39
|
+
objectArray: {
|
|
40
|
+
id: number;
|
|
41
|
+
name: string;
|
|
42
|
+
}[];
|
|
43
|
+
anyArray: unknown[];
|
|
44
|
+
nestedArray: string[][];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Various object type patterns.
|
|
48
|
+
*/
|
|
49
|
+
export declare class ObjectEdgeCases {
|
|
50
|
+
emptyObject: {};
|
|
51
|
+
stringRecord: Record<string, string>;
|
|
52
|
+
deepNested: {
|
|
53
|
+
level1: {
|
|
54
|
+
level2: {
|
|
55
|
+
level3: {
|
|
56
|
+
value: string;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
optionalProps: {
|
|
62
|
+
required: string;
|
|
63
|
+
optional?: number;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Special TypeScript types.
|
|
68
|
+
*/
|
|
69
|
+
export declare class SpecialTypes {
|
|
70
|
+
anyField: any;
|
|
71
|
+
unknownField: unknown;
|
|
72
|
+
voidField: void;
|
|
73
|
+
dateField: Date;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Various enum patterns.
|
|
77
|
+
*/
|
|
78
|
+
export declare class EnumVariations {
|
|
79
|
+
singleLiteral: "only";
|
|
80
|
+
numberEnum: 1 | 2 | 3;
|
|
81
|
+
mixedLiterals: "string" | 42;
|
|
82
|
+
largeEnum: "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j";
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Simple class with no decorators for testing analyzer edge cases.
|
|
86
|
+
*/
|
|
87
|
+
export declare class NoDecoratorsClass {
|
|
88
|
+
name: string;
|
|
89
|
+
count?: number;
|
|
90
|
+
active: boolean;
|
|
91
|
+
}
|
|
92
|
+
export declare const notFormSpec1: null;
|
|
93
|
+
export declare const notFormSpec2: undefined;
|
|
94
|
+
export declare const notFormSpec3 = "string";
|
|
95
|
+
export declare const notFormSpec4 = 123;
|
|
96
|
+
export declare const notFormSpec5: {
|
|
97
|
+
notElements: never[];
|
|
98
|
+
};
|
|
99
|
+
export declare const notFormSpec6: {
|
|
100
|
+
elements: string;
|
|
101
|
+
};
|
|
102
|
+
export declare const notFormSpec7: {
|
|
103
|
+
elements: {
|
|
104
|
+
missingType: boolean;
|
|
105
|
+
}[];
|
|
106
|
+
};
|
|
107
|
+
export declare const notFormSpec8: {
|
|
108
|
+
elements: null[];
|
|
109
|
+
};
|
|
110
|
+
//# sourceMappingURL=edge-cases.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edge-cases.d.ts","sourceRoot":"","sources":["../../../src/__tests__/fixtures/edge-cases.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH;;GAEG;AACH,qBAAa,eAAe;IAE1B,cAAc,EAAG,MAAM,GAAG,MAAM,CAAC;IAGjC,YAAY,EAAG,MAAM,GAAG;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC;IAG5C,WAAW,EAAG;QAAE,IAAI,EAAE,GAAG,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,GAAG,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7E;AAMD;;GAEG;AACH,qBAAa,gBAAgB;IAE3B,cAAc,EAAG,MAAM,GAAG,IAAI,CAAC;IAG/B,eAAe,EAAG,MAAM,GAAG,SAAS,CAAC;IAGrC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAGjC,WAAW,EAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAGxC,cAAc,EAAG,QAAQ,GAAG,UAAU,GAAG,IAAI,CAAC;CAC/C;AAMD;;GAEG;AACH,qBAAa,cAAc;IAEzB,OAAO,EAAG,MAAM,EAAE,CAAC;IAGnB,UAAU,EAAG,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAGjC,aAAa,EAAG,MAAM,EAAE,GAAG,IAAI,CAAC;IAGhC,WAAW,EAAG;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAG7C,QAAQ,EAAG,OAAO,EAAE,CAAC;IAGrB,WAAW,EAAG,MAAM,EAAE,EAAE,CAAC;CAC1B;AAMD;;GAEG;AACH,qBAAa,eAAe;IAG1B,WAAW,EAAG,EAAE,CAAC;IAGjB,YAAY,EAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAGtC,UAAU,EAAG;QACX,MAAM,EAAE;YACN,MAAM,EAAE;gBACN,MAAM,EAAE;oBACN,KAAK,EAAE,MAAM,CAAC;iBACf,CAAC;aACH,CAAC;SACH,CAAC;KACH,CAAC;IAGF,aAAa,EAAG;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAMD;;GAEG;AACH,qBAAa,YAAY;IAGvB,QAAQ,EAAG,GAAG,CAAC;IAGf,YAAY,EAAG,OAAO,CAAC;IAOvB,SAAS,EAAG,IAAI,CAAC;IAGjB,SAAS,EAAG,IAAI,CAAC;CAClB;AAMD;;GAEG;AACH,qBAAa,cAAc;IAEzB,aAAa,EAAG,MAAM,CAAC;IAGvB,UAAU,EAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAIvB,aAAa,EAAG,QAAQ,GAAG,EAAE,CAAC;IAG9B,SAAS,EAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;CACvE;AAMD;;GAEG;AACH,qBAAa,iBAAiB;IAE5B,IAAI,EAAG,MAAM,CAAC;IAGd,KAAK,CAAC,EAAE,MAAM,CAAC;IAGf,MAAM,EAAG,OAAO,CAAC;CAClB;AAMD,eAAO,MAAM,YAAY,MAAO,CAAC;AACjC,eAAO,MAAM,YAAY,WAAY,CAAC;AACtC,eAAO,MAAM,YAAY,WAAW,CAAC;AACrC,eAAO,MAAM,YAAY,MAAM,CAAC;AAChC,eAAO,MAAM,YAAY;;CAAsB,CAAC;AAChD,eAAO,MAAM,YAAY;;CAA4B,CAAC;AACtD,eAAO,MAAM,YAAY;;;;CAAwC,CAAC;AAClE,eAAO,MAAM,YAAY;;CAAuB,CAAC"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edge case fixtures for testing type converter and analyzer.
|
|
3
|
+
*
|
|
4
|
+
* These test various TypeScript type patterns that might cause issues.
|
|
5
|
+
*/
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// Complex Union Types
|
|
8
|
+
// ============================================================================
|
|
9
|
+
/**
|
|
10
|
+
* Mixed type union (not just literals) - should produce oneOf.
|
|
11
|
+
*/
|
|
12
|
+
export class MixedUnionTypes {
|
|
13
|
+
// string | number - incompatible union
|
|
14
|
+
mixedPrimitive;
|
|
15
|
+
// Complex union with object and primitive
|
|
16
|
+
complexUnion;
|
|
17
|
+
// Union of different object shapes
|
|
18
|
+
objectUnion;
|
|
19
|
+
}
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// Nullable and Optional Patterns
|
|
22
|
+
// ============================================================================
|
|
23
|
+
/**
|
|
24
|
+
* Various nullable patterns.
|
|
25
|
+
*/
|
|
26
|
+
export class NullablePatterns {
|
|
27
|
+
// Nullable string (T | null)
|
|
28
|
+
nullableString;
|
|
29
|
+
// Undefined union (T | undefined) - different from optional
|
|
30
|
+
undefinedString;
|
|
31
|
+
// Both nullable and optional
|
|
32
|
+
optionalNullable;
|
|
33
|
+
// Triple union (T | null | undefined)
|
|
34
|
+
tripleUnion;
|
|
35
|
+
// Nullable enum
|
|
36
|
+
nullableStatus;
|
|
37
|
+
}
|
|
38
|
+
// ============================================================================
|
|
39
|
+
// Array Edge Cases
|
|
40
|
+
// ============================================================================
|
|
41
|
+
/**
|
|
42
|
+
* Various array patterns.
|
|
43
|
+
*/
|
|
44
|
+
export class ArrayEdgeCases {
|
|
45
|
+
// Array of primitives
|
|
46
|
+
strings;
|
|
47
|
+
// Array of unions
|
|
48
|
+
mixedArray;
|
|
49
|
+
// Nullable array
|
|
50
|
+
nullableArray;
|
|
51
|
+
// Array of objects
|
|
52
|
+
objectArray;
|
|
53
|
+
// Empty array type (any[])
|
|
54
|
+
anyArray;
|
|
55
|
+
// Nested arrays
|
|
56
|
+
nestedArray;
|
|
57
|
+
}
|
|
58
|
+
// ============================================================================
|
|
59
|
+
// Object Edge Cases
|
|
60
|
+
// ============================================================================
|
|
61
|
+
/**
|
|
62
|
+
* Various object type patterns.
|
|
63
|
+
*/
|
|
64
|
+
export class ObjectEdgeCases {
|
|
65
|
+
// Empty object - Allow this as a test case for empty object type handling
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
67
|
+
emptyObject;
|
|
68
|
+
// Record type
|
|
69
|
+
stringRecord;
|
|
70
|
+
// Deeply nested object
|
|
71
|
+
deepNested;
|
|
72
|
+
// Object with optional properties
|
|
73
|
+
optionalProps;
|
|
74
|
+
}
|
|
75
|
+
// ============================================================================
|
|
76
|
+
// Special Types
|
|
77
|
+
// ============================================================================
|
|
78
|
+
/**
|
|
79
|
+
* Special TypeScript types.
|
|
80
|
+
*/
|
|
81
|
+
export class SpecialTypes {
|
|
82
|
+
// any type (should handle gracefully)
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
84
|
+
anyField;
|
|
85
|
+
// unknown type
|
|
86
|
+
unknownField;
|
|
87
|
+
// never type (edge case)
|
|
88
|
+
// Note: never is not typically used as a property type
|
|
89
|
+
// void type - Test case for void type handling, used in FormSpec codegen tests
|
|
90
|
+
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
|
|
91
|
+
voidField;
|
|
92
|
+
// Date (built-in object)
|
|
93
|
+
dateField;
|
|
94
|
+
}
|
|
95
|
+
// ============================================================================
|
|
96
|
+
// Enum Variations
|
|
97
|
+
// ============================================================================
|
|
98
|
+
/**
|
|
99
|
+
* Various enum patterns.
|
|
100
|
+
*/
|
|
101
|
+
export class EnumVariations {
|
|
102
|
+
// Single literal (degenerates to const)
|
|
103
|
+
singleLiteral;
|
|
104
|
+
// Number literal enum
|
|
105
|
+
numberEnum;
|
|
106
|
+
// Mixed literal types (should NOT be valid enum)
|
|
107
|
+
// Note: This is a union, not an enum
|
|
108
|
+
mixedLiterals;
|
|
109
|
+
// Large enum (many options)
|
|
110
|
+
largeEnum;
|
|
111
|
+
}
|
|
112
|
+
// ============================================================================
|
|
113
|
+
// Class without decorators (for testing analyzer handles undecorated classes)
|
|
114
|
+
// ============================================================================
|
|
115
|
+
/**
|
|
116
|
+
* Simple class with no decorators for testing analyzer edge cases.
|
|
117
|
+
*/
|
|
118
|
+
export class NoDecoratorsClass {
|
|
119
|
+
// Regular string field
|
|
120
|
+
name;
|
|
121
|
+
// Optional number field
|
|
122
|
+
count;
|
|
123
|
+
// Boolean field
|
|
124
|
+
active;
|
|
125
|
+
}
|
|
126
|
+
// ============================================================================
|
|
127
|
+
// Invalid FormSpec-like Objects (for testing isFormSpec)
|
|
128
|
+
// ============================================================================
|
|
129
|
+
export const notFormSpec1 = null;
|
|
130
|
+
export const notFormSpec2 = undefined;
|
|
131
|
+
export const notFormSpec3 = "string";
|
|
132
|
+
export const notFormSpec4 = 123;
|
|
133
|
+
export const notFormSpec5 = { notElements: [] };
|
|
134
|
+
export const notFormSpec6 = { elements: "not-array" };
|
|
135
|
+
export const notFormSpec7 = { elements: [{ missingType: true }] };
|
|
136
|
+
export const notFormSpec8 = { elements: [null] };
|
|
137
|
+
//# sourceMappingURL=edge-cases.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edge-cases.js","sourceRoot":"","sources":["../../../src/__tests__/fixtures/edge-cases.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,+EAA+E;AAC/E,sBAAsB;AACtB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,OAAO,eAAe;IAC1B,uCAAuC;IACvC,cAAc,CAAmB;IAEjC,0CAA0C;IAC1C,YAAY,CAAgC;IAE5C,mCAAmC;IACnC,WAAW,CAAiE;CAC7E;AAED,+EAA+E;AAC/E,iCAAiC;AACjC,+EAA+E;AAE/E;;GAEG;AACH,MAAM,OAAO,gBAAgB;IAC3B,6BAA6B;IAC7B,cAAc,CAAiB;IAE/B,4DAA4D;IAC5D,eAAe,CAAsB;IAErC,6BAA6B;IAC7B,gBAAgB,CAAiB;IAEjC,sCAAsC;IACtC,WAAW,CAA6B;IAExC,gBAAgB;IAChB,cAAc,CAAgC;CAC/C;AAED,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,OAAO,cAAc;IACzB,sBAAsB;IACtB,OAAO,CAAY;IAEnB,kBAAkB;IAClB,UAAU,CAAuB;IAEjC,iBAAiB;IACjB,aAAa,CAAmB;IAEhC,mBAAmB;IACnB,WAAW,CAAkC;IAE7C,2BAA2B;IAC3B,QAAQ,CAAa;IAErB,gBAAgB;IAChB,WAAW,CAAc;CAC1B;AAED,+EAA+E;AAC/E,oBAAoB;AACpB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,OAAO,eAAe;IAC1B,0EAA0E;IAC1E,mEAAmE;IACnE,WAAW,CAAM;IAEjB,cAAc;IACd,YAAY,CAA0B;IAEtC,uBAAuB;IACvB,UAAU,CAQR;IAEF,kCAAkC;IAClC,aAAa,CAGX;CACH;AAED,+EAA+E;AAC/E,gBAAgB;AAChB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,OAAO,YAAY;IACvB,sCAAsC;IACtC,8DAA8D;IAC9D,QAAQ,CAAO;IAEf,eAAe;IACf,YAAY,CAAW;IAEvB,yBAAyB;IACzB,uDAAuD;IAEvD,+EAA+E;IAC/E,mEAAmE;IACnE,SAAS,CAAQ;IAEjB,yBAAyB;IACzB,SAAS,CAAQ;CAClB;AAED,+EAA+E;AAC/E,kBAAkB;AAClB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,OAAO,cAAc;IACzB,wCAAwC;IACxC,aAAa,CAAU;IAEvB,sBAAsB;IACtB,UAAU,CAAa;IAEvB,iDAAiD;IACjD,qCAAqC;IACrC,aAAa,CAAiB;IAE9B,4BAA4B;IAC5B,SAAS,CAA6D;CACvE;AAED,+EAA+E;AAC/E,8EAA8E;AAC9E,+EAA+E;AAE/E;;GAEG;AACH,MAAM,OAAO,iBAAiB;IAC5B,uBAAuB;IACvB,IAAI,CAAU;IAEd,wBAAwB;IACxB,KAAK,CAAU;IAEf,gBAAgB;IAChB,MAAM,CAAW;CAClB;AAED,+EAA+E;AAC/E,yDAAyD;AACzD,+EAA+E;AAE/E,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC;AACjC,MAAM,CAAC,MAAM,YAAY,GAAG,SAAS,CAAC;AACtC,MAAM,CAAC,MAAM,YAAY,GAAG,QAAQ,CAAC;AACrC,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,CAAC;AAChC,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;AAChD,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;AACtD,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AAClE,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test fixture for CLI analyzer.
|
|
3
|
+
*
|
|
4
|
+
* Contains both:
|
|
5
|
+
* - Decorated classes (class + decorator DSL)
|
|
6
|
+
* - FormSpec exports (chain DSL)
|
|
7
|
+
*/
|
|
8
|
+
import type { InferFormSchema } from "@formspec/dsl";
|
|
9
|
+
/**
|
|
10
|
+
* FormSpec for user registration.
|
|
11
|
+
*/
|
|
12
|
+
export declare const UserRegistrationForm: import("@formspec/core").FormSpec<readonly [import("@formspec/core").TextField<"username">, import("@formspec/core").TextField<"email">, import("@formspec/core").TextField<"password">, import("@formspec/core").BooleanField<"acceptTerms">]>;
|
|
13
|
+
/**
|
|
14
|
+
* FormSpec for product configuration.
|
|
15
|
+
*/
|
|
16
|
+
export declare const ProductConfigForm: import("@formspec/core").FormSpec<readonly [import("@formspec/core").TextField<"name">, import("@formspec/core").NumberField<"price">, import("@formspec/core").StaticEnumField<"status", readonly ["draft", "active", "archived"]>]>;
|
|
17
|
+
/**
|
|
18
|
+
* FormSpec for method parameters.
|
|
19
|
+
*/
|
|
20
|
+
export declare const ActivateParams: import("@formspec/core").FormSpec<readonly [import("@formspec/core").NumberField<"amount">, import("@formspec/core").NumberField<"installments">]>;
|
|
21
|
+
export declare const CancelParams: import("@formspec/core").FormSpec<readonly [import("@formspec/core").StaticEnumField<"reason", readonly ["user_request", "fraud", "other"]>, import("@formspec/core").TextField<"notes">]>;
|
|
22
|
+
/**
|
|
23
|
+
* Sample class with decorated fields and methods.
|
|
24
|
+
*/
|
|
25
|
+
export declare class InstallmentPlan {
|
|
26
|
+
status: "active" | "paused" | "canceled";
|
|
27
|
+
amount: number;
|
|
28
|
+
customerEmail?: string;
|
|
29
|
+
installments: number;
|
|
30
|
+
/**
|
|
31
|
+
* Activates the plan with the given parameters.
|
|
32
|
+
*/
|
|
33
|
+
activate(params: InferFormSchema<typeof ActivateParams>): {
|
|
34
|
+
success: boolean;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Cancels the plan.
|
|
38
|
+
*/
|
|
39
|
+
cancelPlan(params: InferFormSchema<typeof CancelParams>): void;
|
|
40
|
+
/**
|
|
41
|
+
* Static factory method.
|
|
42
|
+
*/
|
|
43
|
+
static createStandard(name: string, amount: number): InstallmentPlan;
|
|
44
|
+
}
|
|
45
|
+
export declare class SimpleProduct {
|
|
46
|
+
name: string;
|
|
47
|
+
price?: number;
|
|
48
|
+
active: boolean;
|
|
49
|
+
tags?: string[];
|
|
50
|
+
update(data: {
|
|
51
|
+
name?: string;
|
|
52
|
+
price?: number;
|
|
53
|
+
}): boolean;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=sample-forms.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sample-forms.d.ts","sourceRoot":"","sources":["../../../src/__tests__/fixtures/sample-forms.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAMrD;;GAEG;AACH,eAAO,MAAM,oBAAoB,iPAKhC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,uOAM7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,oJAG1B,CAAC;AAEF,eAAO,MAAM,YAAY,4LAKxB,CAAC;AAMF;;GAEG;AACH,qBAAa,eAAe;IAC1B,MAAM,EAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;IAE1C,MAAM,EAAG,MAAM,CAAC;IAEhB,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,YAAY,EAAG,MAAM,CAAC;IAEtB;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC,OAAO,cAAc,CAAC,GAAG;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE;IAK9E;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,eAAe,CAAC,OAAO,YAAY,CAAC,GAAG,IAAI;IAI9D;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,eAAe;CAKrE;AAMD,qBAAa,aAAa;IACxB,IAAI,EAAG,MAAM,CAAC;IAEd,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,MAAM,EAAG,OAAO,CAAC;IAEjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB,MAAM,CAAC,IAAI,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO;CAKzD"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test fixture for CLI analyzer.
|
|
3
|
+
*
|
|
4
|
+
* Contains both:
|
|
5
|
+
* - Decorated classes (class + decorator DSL)
|
|
6
|
+
* - FormSpec exports (chain DSL)
|
|
7
|
+
*/
|
|
8
|
+
import { formspec, field } from "@formspec/dsl";
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Chain DSL FormSpecs (exported for runtime loading)
|
|
11
|
+
// ============================================================================
|
|
12
|
+
/**
|
|
13
|
+
* FormSpec for user registration.
|
|
14
|
+
*/
|
|
15
|
+
export const UserRegistrationForm = formspec(field.text("username", { label: "Username", required: true }), field.text("email", { label: "Email Address", required: true }), field.text("password", { label: "Password", required: true }), field.boolean("acceptTerms", { label: "Accept Terms", required: true }));
|
|
16
|
+
/**
|
|
17
|
+
* FormSpec for product configuration.
|
|
18
|
+
*/
|
|
19
|
+
export const ProductConfigForm = formspec(field.text("name", { label: "Product Name", required: true }), field.number("price", { label: "Price (cents)", min: 0 }), field.enum("status", ["draft", "active", "archived"], {
|
|
20
|
+
label: "Status",
|
|
21
|
+
}));
|
|
22
|
+
/**
|
|
23
|
+
* FormSpec for method parameters.
|
|
24
|
+
*/
|
|
25
|
+
export const ActivateParams = formspec(field.number("amount", { label: "Amount (cents)", min: 100 }), field.number("installments", { label: "Number of Installments", min: 2, max: 12 }));
|
|
26
|
+
export const CancelParams = formspec(field.enum("reason", ["user_request", "fraud", "other"], {
|
|
27
|
+
label: "Cancellation Reason",
|
|
28
|
+
}), field.text("notes", { label: "Additional Notes" }));
|
|
29
|
+
// ============================================================================
|
|
30
|
+
// Decorated Class (class + decorator DSL)
|
|
31
|
+
// ============================================================================
|
|
32
|
+
/**
|
|
33
|
+
* Sample class with decorated fields and methods.
|
|
34
|
+
*/
|
|
35
|
+
export class InstallmentPlan {
|
|
36
|
+
status;
|
|
37
|
+
amount;
|
|
38
|
+
customerEmail;
|
|
39
|
+
installments;
|
|
40
|
+
/**
|
|
41
|
+
* Activates the plan with the given parameters.
|
|
42
|
+
*/
|
|
43
|
+
activate(params) {
|
|
44
|
+
console.log("Activating with", params);
|
|
45
|
+
return { success: true };
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Cancels the plan.
|
|
49
|
+
*/
|
|
50
|
+
cancelPlan(params) {
|
|
51
|
+
console.log("Canceling with reason:", params.reason);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Static factory method.
|
|
55
|
+
*/
|
|
56
|
+
static createStandard(name, amount) {
|
|
57
|
+
const plan = new InstallmentPlan();
|
|
58
|
+
plan.amount = amount;
|
|
59
|
+
return plan;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// ============================================================================
|
|
63
|
+
// Simple class without FormSpec method params (for testing static analysis only)
|
|
64
|
+
// ============================================================================
|
|
65
|
+
export class SimpleProduct {
|
|
66
|
+
name;
|
|
67
|
+
price;
|
|
68
|
+
active;
|
|
69
|
+
tags;
|
|
70
|
+
update(data) {
|
|
71
|
+
if (data.name)
|
|
72
|
+
this.name = data.name;
|
|
73
|
+
if (data.price)
|
|
74
|
+
this.price = data.price;
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=sample-forms.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sample-forms.js","sourceRoot":"","sources":["../../../src/__tests__/fixtures/sample-forms.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAGhD,+EAA+E;AAC/E,qDAAqD;AACrD,+EAA+E;AAE/E;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,QAAQ,CAC1C,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAC7D,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAC/D,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAC7D,KAAK,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CACxE,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,QAAQ,CACvC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAC7D,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EACzD,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAU,EAAE;IAC7D,KAAK,EAAE,QAAQ;CAChB,CAAC,CACH,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,QAAQ,CACpC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,EAC7D,KAAK,CAAC,MAAM,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,wBAAwB,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CACnF,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,QAAQ,CAClC,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,cAAc,EAAE,OAAO,EAAE,OAAO,CAAU,EAAE;IAChE,KAAK,EAAE,qBAAqB;CAC7B,CAAC,EACF,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CACnD,CAAC;AAEF,+EAA+E;AAC/E,0CAA0C;AAC1C,+EAA+E;AAE/E;;GAEG;AACH,MAAM,OAAO,eAAe;IAC1B,MAAM,CAAoC;IAE1C,MAAM,CAAU;IAEhB,aAAa,CAAU;IAEvB,YAAY,CAAU;IAEtB;;OAEG;IACH,QAAQ,CAAC,MAA8C;QACrD,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;QACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,MAA4C;QACrD,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACvD,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,IAAY,EAAE,MAAc;QAChD,MAAM,IAAI,GAAG,IAAI,eAAe,EAAE,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAED,+EAA+E;AAC/E,iFAAiF;AACjF,+EAA+E;AAE/E,MAAM,OAAO,aAAa;IACxB,IAAI,CAAU;IAEd,KAAK,CAAU;IAEf,MAAM,CAAW;IAEjB,IAAI,CAAY;IAEhB,MAAM,CAAC,IAAuC;QAC5C,IAAI,IAAI,CAAC,IAAI;YAAE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACrC,IAAI,IAAI,CAAC,KAAK;YAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACxC,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integration.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/integration.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|