@player-lang/functional-dsl-generator 0.0.2-next.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/cjs/index.cjs +2146 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/index.legacy-esm.js +2075 -0
- package/dist/index.mjs +2075 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +38 -0
- package/src/__tests__/__snapshots__/generator.test.ts.snap +886 -0
- package/src/__tests__/builder-class-generator.test.ts +627 -0
- package/src/__tests__/cli.test.ts +685 -0
- package/src/__tests__/default-value-generator.test.ts +365 -0
- package/src/__tests__/generator.test.ts +2860 -0
- package/src/__tests__/import-generator.test.ts +444 -0
- package/src/__tests__/path-utils.test.ts +174 -0
- package/src/__tests__/type-collector.test.ts +674 -0
- package/src/__tests__/type-transformer.test.ts +934 -0
- package/src/__tests__/utils.test.ts +597 -0
- package/src/builder-class-generator.ts +254 -0
- package/src/cli.ts +285 -0
- package/src/default-value-generator.ts +307 -0
- package/src/generator.ts +257 -0
- package/src/import-generator.ts +331 -0
- package/src/index.ts +38 -0
- package/src/path-utils.ts +155 -0
- package/src/ts-morph-type-finder.ts +319 -0
- package/src/type-categorizer.ts +131 -0
- package/src/type-collector.ts +296 -0
- package/src/type-resolver.ts +266 -0
- package/src/type-transformer.ts +487 -0
- package/src/utils.ts +762 -0
- package/types/builder-class-generator.d.ts +56 -0
- package/types/cli.d.ts +6 -0
- package/types/default-value-generator.d.ts +74 -0
- package/types/generator.d.ts +102 -0
- package/types/import-generator.d.ts +77 -0
- package/types/index.d.ts +12 -0
- package/types/path-utils.d.ts +65 -0
- package/types/ts-morph-type-finder.d.ts +73 -0
- package/types/type-categorizer.d.ts +46 -0
- package/types/type-collector.d.ts +62 -0
- package/types/type-resolver.d.ts +49 -0
- package/types/type-transformer.d.ts +74 -0
- package/types/utils.d.ts +205 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import { describe, test, expect } from "vitest";
|
|
2
|
+
import type { ObjectType } from "@xlr-lib/xlr";
|
|
3
|
+
import { DefaultValueGenerator } from "../default-value-generator";
|
|
4
|
+
|
|
5
|
+
describe("DefaultValueGenerator", () => {
|
|
6
|
+
const generator = new DefaultValueGenerator();
|
|
7
|
+
|
|
8
|
+
describe("Asset Type Defaults", () => {
|
|
9
|
+
test("adds asset type default", () => {
|
|
10
|
+
const objectType: ObjectType = {
|
|
11
|
+
type: "object",
|
|
12
|
+
properties: {},
|
|
13
|
+
extends: { type: "ref", ref: "Asset<'text'>" },
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const defaults = generator.generateDefaults(objectType, "text");
|
|
17
|
+
expect(defaults).toEqual({ type: "text", id: "" });
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test("adds id default for Asset extensions", () => {
|
|
21
|
+
const objectType: ObjectType = {
|
|
22
|
+
type: "object",
|
|
23
|
+
properties: {},
|
|
24
|
+
extends: { type: "ref", ref: "Asset<'button'>" },
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const defaults = generator.generateDefaults(objectType);
|
|
28
|
+
expect(defaults).toEqual({ id: "" });
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test("adds id default for types with id property", () => {
|
|
32
|
+
const objectType: ObjectType = {
|
|
33
|
+
type: "object",
|
|
34
|
+
properties: {
|
|
35
|
+
id: { required: true, node: { type: "string" } },
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const defaults = generator.generateDefaults(objectType);
|
|
40
|
+
expect(defaults).toEqual({ id: "" });
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe("Primitive Defaults", () => {
|
|
45
|
+
test("generates string default", () => {
|
|
46
|
+
const objectType: ObjectType = {
|
|
47
|
+
type: "object",
|
|
48
|
+
properties: {
|
|
49
|
+
name: { required: true, node: { type: "string" } },
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const defaults = generator.generateDefaults(objectType);
|
|
54
|
+
expect(defaults).toEqual({ name: "" });
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("generates number default", () => {
|
|
58
|
+
const objectType: ObjectType = {
|
|
59
|
+
type: "object",
|
|
60
|
+
properties: {
|
|
61
|
+
count: { required: true, node: { type: "number" } },
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const defaults = generator.generateDefaults(objectType);
|
|
66
|
+
expect(defaults).toEqual({ count: 0 });
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("generates boolean default", () => {
|
|
70
|
+
const objectType: ObjectType = {
|
|
71
|
+
type: "object",
|
|
72
|
+
properties: {
|
|
73
|
+
enabled: { required: true, node: { type: "boolean" } },
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const defaults = generator.generateDefaults(objectType);
|
|
78
|
+
expect(defaults).toEqual({ enabled: false });
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("preserves const values", () => {
|
|
82
|
+
const objectType: ObjectType = {
|
|
83
|
+
type: "object",
|
|
84
|
+
properties: {
|
|
85
|
+
status: { required: true, node: { type: "string", const: "active" } },
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const defaults = generator.generateDefaults(objectType);
|
|
90
|
+
expect(defaults).toEqual({ status: "active" });
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe("Expression and Binding Defaults", () => {
|
|
95
|
+
test("generates Expression default", () => {
|
|
96
|
+
const objectType: ObjectType = {
|
|
97
|
+
type: "object",
|
|
98
|
+
properties: {
|
|
99
|
+
exp: { required: true, node: { type: "ref", ref: "Expression" } },
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const defaults = generator.generateDefaults(objectType);
|
|
104
|
+
expect(defaults).toEqual({ exp: "" });
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test("generates Binding default", () => {
|
|
108
|
+
const objectType: ObjectType = {
|
|
109
|
+
type: "object",
|
|
110
|
+
properties: {
|
|
111
|
+
binding: { required: true, node: { type: "ref", ref: "Binding" } },
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const defaults = generator.generateDefaults(objectType);
|
|
116
|
+
expect(defaults).toEqual({ binding: "" });
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
describe("Array Defaults", () => {
|
|
121
|
+
test("generates array default", () => {
|
|
122
|
+
const objectType: ObjectType = {
|
|
123
|
+
type: "object",
|
|
124
|
+
properties: {
|
|
125
|
+
items: {
|
|
126
|
+
required: true,
|
|
127
|
+
node: { type: "array", elementType: { type: "string" } },
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const defaults = generator.generateDefaults(objectType);
|
|
133
|
+
expect(defaults).toEqual({ items: [] });
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
describe("Union Type Defaults", () => {
|
|
138
|
+
test("picks first non-null variant for union", () => {
|
|
139
|
+
const objectType: ObjectType = {
|
|
140
|
+
type: "object",
|
|
141
|
+
properties: {
|
|
142
|
+
value: {
|
|
143
|
+
required: true,
|
|
144
|
+
node: {
|
|
145
|
+
type: "or",
|
|
146
|
+
or: [{ type: "null" }, { type: "string" }],
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const defaults = generator.generateDefaults(objectType);
|
|
153
|
+
expect(defaults).toEqual({ value: "" });
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test("skips null and undefined variants", () => {
|
|
157
|
+
const objectType: ObjectType = {
|
|
158
|
+
type: "object",
|
|
159
|
+
properties: {
|
|
160
|
+
value: {
|
|
161
|
+
required: true,
|
|
162
|
+
node: {
|
|
163
|
+
type: "or",
|
|
164
|
+
or: [{ type: "null" }, { type: "undefined" }, { type: "number" }],
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const defaults = generator.generateDefaults(objectType);
|
|
171
|
+
expect(defaults).toEqual({ value: 0 });
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
describe("Object Type Defaults", () => {
|
|
176
|
+
test("generates defaults for nested required properties", () => {
|
|
177
|
+
const objectType: ObjectType = {
|
|
178
|
+
type: "object",
|
|
179
|
+
properties: {
|
|
180
|
+
config: {
|
|
181
|
+
required: true,
|
|
182
|
+
node: {
|
|
183
|
+
type: "object",
|
|
184
|
+
properties: {
|
|
185
|
+
name: { required: true, node: { type: "string" } },
|
|
186
|
+
count: { required: true, node: { type: "number" } },
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const defaults = generator.generateDefaults(objectType);
|
|
194
|
+
expect(defaults).toEqual({ config: { name: "", count: 0 } });
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
test("respects depth limit for recursive objects", () => {
|
|
198
|
+
const generator3 = new DefaultValueGenerator({ maxDepth: 3 });
|
|
199
|
+
|
|
200
|
+
// Create a deeply nested structure
|
|
201
|
+
const objectType: ObjectType = {
|
|
202
|
+
type: "object",
|
|
203
|
+
properties: {
|
|
204
|
+
level1: {
|
|
205
|
+
required: true,
|
|
206
|
+
node: {
|
|
207
|
+
type: "object",
|
|
208
|
+
properties: {
|
|
209
|
+
level2: {
|
|
210
|
+
required: true,
|
|
211
|
+
node: {
|
|
212
|
+
type: "object",
|
|
213
|
+
properties: {
|
|
214
|
+
level3: {
|
|
215
|
+
required: true,
|
|
216
|
+
node: {
|
|
217
|
+
type: "object",
|
|
218
|
+
properties: {
|
|
219
|
+
level4: {
|
|
220
|
+
required: true,
|
|
221
|
+
node: {
|
|
222
|
+
type: "object",
|
|
223
|
+
properties: {
|
|
224
|
+
deep: {
|
|
225
|
+
required: true,
|
|
226
|
+
node: { type: "string" },
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
const defaults = generator3.generateDefaults(objectType);
|
|
244
|
+
// At maxDepth=3, level4 should be {} (depth limit reached)
|
|
245
|
+
expect(defaults).toEqual({
|
|
246
|
+
level1: { level2: { level3: { level4: {} } } },
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
describe("AssetWrapper Skipping", () => {
|
|
252
|
+
test("skips AssetWrapper properties", () => {
|
|
253
|
+
const objectType: ObjectType = {
|
|
254
|
+
type: "object",
|
|
255
|
+
properties: {
|
|
256
|
+
name: { required: true, node: { type: "string" } },
|
|
257
|
+
slot: {
|
|
258
|
+
required: true,
|
|
259
|
+
node: { type: "ref", ref: "AssetWrapper" },
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
const defaults = generator.generateDefaults(objectType);
|
|
265
|
+
// AssetWrapper should be skipped - user must provide
|
|
266
|
+
expect(defaults).toEqual({ name: "" });
|
|
267
|
+
expect("slot" in defaults).toBe(false);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
test("skips Asset properties", () => {
|
|
271
|
+
const objectType: ObjectType = {
|
|
272
|
+
type: "object",
|
|
273
|
+
properties: {
|
|
274
|
+
name: { required: true, node: { type: "string" } },
|
|
275
|
+
asset: { required: true, node: { type: "ref", ref: "Asset" } },
|
|
276
|
+
},
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
const defaults = generator.generateDefaults(objectType);
|
|
280
|
+
expect(defaults).toEqual({ name: "" });
|
|
281
|
+
expect("asset" in defaults).toBe(false);
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
test("skips AssetWrapper with generic", () => {
|
|
285
|
+
const objectType: ObjectType = {
|
|
286
|
+
type: "object",
|
|
287
|
+
properties: {
|
|
288
|
+
icon: {
|
|
289
|
+
required: true,
|
|
290
|
+
node: { type: "ref", ref: "AssetWrapper<ImageAsset>" },
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
const defaults = generator.generateDefaults(objectType);
|
|
296
|
+
expect("icon" in defaults).toBe(false);
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
describe("Optional Properties", () => {
|
|
301
|
+
test("does not generate defaults for optional properties", () => {
|
|
302
|
+
const objectType: ObjectType = {
|
|
303
|
+
type: "object",
|
|
304
|
+
properties: {
|
|
305
|
+
requiredProp: { required: true, node: { type: "string" } },
|
|
306
|
+
optionalProp: { required: false, node: { type: "string" } },
|
|
307
|
+
},
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
const defaults = generator.generateDefaults(objectType);
|
|
311
|
+
expect(defaults).toEqual({ requiredProp: "" });
|
|
312
|
+
expect("optionalProp" in defaults).toBe(false);
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
describe("Ref Types", () => {
|
|
317
|
+
test("generates empty object for unknown ref types", () => {
|
|
318
|
+
const objectType: ObjectType = {
|
|
319
|
+
type: "object",
|
|
320
|
+
properties: {
|
|
321
|
+
config: {
|
|
322
|
+
required: true,
|
|
323
|
+
node: { type: "ref", ref: "CustomConfig" },
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
const defaults = generator.generateDefaults(objectType);
|
|
329
|
+
expect(defaults).toEqual({ config: {} });
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
describe("Intersection Types", () => {
|
|
334
|
+
test("merges defaults for intersection types", () => {
|
|
335
|
+
const objectType: ObjectType = {
|
|
336
|
+
type: "object",
|
|
337
|
+
properties: {
|
|
338
|
+
combined: {
|
|
339
|
+
required: true,
|
|
340
|
+
node: {
|
|
341
|
+
type: "and",
|
|
342
|
+
and: [
|
|
343
|
+
{
|
|
344
|
+
type: "object",
|
|
345
|
+
properties: {
|
|
346
|
+
name: { required: true, node: { type: "string" } },
|
|
347
|
+
},
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
type: "object",
|
|
351
|
+
properties: {
|
|
352
|
+
count: { required: true, node: { type: "number" } },
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
],
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
},
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
const defaults = generator.generateDefaults(objectType);
|
|
362
|
+
expect(defaults).toEqual({ combined: { name: "", count: 0 } });
|
|
363
|
+
});
|
|
364
|
+
});
|
|
365
|
+
});
|