@famgia/omnify-typescript 0.0.1 → 0.0.2
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/chunk-J46F3EBS.js +638 -0
- package/dist/chunk-J46F3EBS.js.map +1 -0
- package/dist/index.cjs +315 -155
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -36
- package/dist/index.d.ts +43 -36
- package/dist/index.js +2 -7
- package/dist/plugin.cjs +324 -186
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +10 -20
- package/dist/plugin.d.ts +10 -20
- package/dist/plugin.js +11 -40
- package/dist/plugin.js.map +1 -1
- package/package.json +6 -4
- package/scripts/postinstall.js +274 -0
- package/dist/chunk-2BXDNKIN.js +0 -477
- package/dist/chunk-2BXDNKIN.js.map +0 -1
package/dist/plugin.cjs
CHANGED
|
@@ -26,6 +26,7 @@ __export(plugin_exports, {
|
|
|
26
26
|
module.exports = __toCommonJS(plugin_exports);
|
|
27
27
|
|
|
28
28
|
// src/interface-generator.ts
|
|
29
|
+
var import_omnify_types = require("@famgia/omnify-types");
|
|
29
30
|
var TYPE_MAP = {
|
|
30
31
|
String: "string",
|
|
31
32
|
Int: "number",
|
|
@@ -51,6 +52,15 @@ var PK_TYPE_MAP = {
|
|
|
51
52
|
Uuid: "string",
|
|
52
53
|
String: "string"
|
|
53
54
|
};
|
|
55
|
+
function resolveDisplayName(value, options = {}) {
|
|
56
|
+
if (value === void 0) {
|
|
57
|
+
return void 0;
|
|
58
|
+
}
|
|
59
|
+
return (0, import_omnify_types.resolveLocalizedString)(value, {
|
|
60
|
+
locale: options.locale,
|
|
61
|
+
config: options.localeConfig
|
|
62
|
+
});
|
|
63
|
+
}
|
|
54
64
|
function toPropertyName(name) {
|
|
55
65
|
return name;
|
|
56
66
|
}
|
|
@@ -112,6 +122,7 @@ function getPropertyType(property, _allSchemas) {
|
|
|
112
122
|
function propertyToTSProperties(propertyName, property, allSchemas, options = {}) {
|
|
113
123
|
const baseProp = property;
|
|
114
124
|
const isReadonly = options.readonly ?? true;
|
|
125
|
+
const displayName = resolveDisplayName(baseProp.displayName, options);
|
|
115
126
|
if (property.type === "Association") {
|
|
116
127
|
const assocProp = property;
|
|
117
128
|
if (assocProp.relation === "MorphTo" && assocProp.targets && assocProp.targets.length > 0) {
|
|
@@ -139,7 +150,7 @@ function propertyToTSProperties(propertyName, property, allSchemas, options = {}
|
|
|
139
150
|
type: `${relationUnion} | null`,
|
|
140
151
|
optional: true,
|
|
141
152
|
readonly: isReadonly,
|
|
142
|
-
comment:
|
|
153
|
+
comment: displayName ?? `Polymorphic relation to ${assocProp.targets.join(", ")}`
|
|
143
154
|
}
|
|
144
155
|
];
|
|
145
156
|
}
|
|
@@ -150,7 +161,7 @@ function propertyToTSProperties(propertyName, property, allSchemas, options = {}
|
|
|
150
161
|
type,
|
|
151
162
|
optional: baseProp.nullable ?? false,
|
|
152
163
|
readonly: isReadonly,
|
|
153
|
-
comment:
|
|
164
|
+
comment: displayName
|
|
154
165
|
}];
|
|
155
166
|
}
|
|
156
167
|
function schemaToInterface(schema, allSchemas, options = {}) {
|
|
@@ -197,10 +208,11 @@ function schemaToInterface(schema, allSchemas, options = {}) {
|
|
|
197
208
|
comment: "Soft delete timestamp"
|
|
198
209
|
});
|
|
199
210
|
}
|
|
211
|
+
const schemaDisplayName = resolveDisplayName(schema.displayName, options);
|
|
200
212
|
return {
|
|
201
213
|
name: toInterfaceName(schema.name),
|
|
202
214
|
properties,
|
|
203
|
-
comment:
|
|
215
|
+
comment: schemaDisplayName ?? schema.name
|
|
204
216
|
};
|
|
205
217
|
}
|
|
206
218
|
function formatProperty(property) {
|
|
@@ -233,31 +245,54 @@ function generateInterfaces(schemas, options = {}) {
|
|
|
233
245
|
}
|
|
234
246
|
|
|
235
247
|
// src/enum-generator.ts
|
|
248
|
+
var import_omnify_types2 = require("@famgia/omnify-types");
|
|
249
|
+
function resolveDisplayName2(value, options = {}) {
|
|
250
|
+
if (value === void 0) {
|
|
251
|
+
return void 0;
|
|
252
|
+
}
|
|
253
|
+
return (0, import_omnify_types2.resolveLocalizedString)(value, {
|
|
254
|
+
locale: options.locale,
|
|
255
|
+
config: options.localeConfig
|
|
256
|
+
});
|
|
257
|
+
}
|
|
236
258
|
function toEnumMemberName(value) {
|
|
237
259
|
return value.split(/[-_\s]+/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join("").replace(/[^a-zA-Z0-9]/g, "");
|
|
238
260
|
}
|
|
239
261
|
function toEnumName(schemaName) {
|
|
240
262
|
return schemaName;
|
|
241
263
|
}
|
|
242
|
-
function
|
|
264
|
+
function parseEnumValue(value) {
|
|
265
|
+
if (typeof value === "string") {
|
|
266
|
+
return {
|
|
267
|
+
name: toEnumMemberName(value),
|
|
268
|
+
value
|
|
269
|
+
// No label or extra - will fallback to value
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
return {
|
|
273
|
+
name: toEnumMemberName(value.value),
|
|
274
|
+
value: value.value,
|
|
275
|
+
label: value.label,
|
|
276
|
+
extra: value.extra
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
function schemaToEnum(schema, options = {}) {
|
|
243
280
|
if (schema.kind !== "enum" || !schema.values) {
|
|
244
281
|
return null;
|
|
245
282
|
}
|
|
246
|
-
const values = schema.values.map((value) => (
|
|
247
|
-
|
|
248
|
-
value
|
|
249
|
-
}));
|
|
283
|
+
const values = schema.values.map((value) => parseEnumValue(value));
|
|
284
|
+
const displayName = resolveDisplayName2(schema.displayName, options);
|
|
250
285
|
return {
|
|
251
286
|
name: toEnumName(schema.name),
|
|
252
287
|
values,
|
|
253
|
-
comment:
|
|
288
|
+
comment: displayName ?? schema.name
|
|
254
289
|
};
|
|
255
290
|
}
|
|
256
|
-
function generateEnums(schemas) {
|
|
291
|
+
function generateEnums(schemas, options = {}) {
|
|
257
292
|
const enums = [];
|
|
258
293
|
for (const schema of Object.values(schemas)) {
|
|
259
294
|
if (schema.kind === "enum") {
|
|
260
|
-
const enumDef = schemaToEnum(schema);
|
|
295
|
+
const enumDef = schemaToEnum(schema, options);
|
|
261
296
|
if (enumDef) {
|
|
262
297
|
enums.push(enumDef);
|
|
263
298
|
}
|
|
@@ -266,23 +301,132 @@ function generateEnums(schemas) {
|
|
|
266
301
|
return enums;
|
|
267
302
|
}
|
|
268
303
|
function formatEnum(enumDef) {
|
|
269
|
-
const comment = enumDef
|
|
270
|
-
|
|
304
|
+
const { name, values, comment } = enumDef;
|
|
305
|
+
const parts = [];
|
|
306
|
+
if (comment) {
|
|
307
|
+
parts.push(`/**
|
|
308
|
+
* ${comment}
|
|
271
309
|
*/
|
|
272
|
-
`
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
${
|
|
276
|
-
}
|
|
310
|
+
`);
|
|
311
|
+
}
|
|
312
|
+
const enumValues = values.map((v) => ` ${v.name} = '${v.value}',`).join("\n");
|
|
313
|
+
parts.push(`export enum ${name} {
|
|
314
|
+
${enumValues}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
`);
|
|
318
|
+
parts.push(`/** All ${name} values */
|
|
319
|
+
`);
|
|
320
|
+
parts.push(`export const ${name}Values = Object.values(${name});
|
|
321
|
+
|
|
322
|
+
`);
|
|
323
|
+
parts.push(`/** Type guard for ${name} */
|
|
324
|
+
`);
|
|
325
|
+
parts.push(`export function is${name}(value: unknown): value is ${name} {
|
|
326
|
+
`);
|
|
327
|
+
parts.push(` return ${name}Values.includes(value as ${name});
|
|
328
|
+
`);
|
|
329
|
+
parts.push(`}
|
|
330
|
+
|
|
331
|
+
`);
|
|
332
|
+
const hasLabels = values.some((v) => v.label !== void 0);
|
|
333
|
+
if (hasLabels) {
|
|
334
|
+
const labelEntries = values.filter((v) => v.label !== void 0).map((v) => ` [${name}.${v.name}]: '${v.label}',`).join("\n");
|
|
335
|
+
parts.push(`const ${lowerFirst(name)}Labels: Partial<Record<${name}, string>> = {
|
|
336
|
+
${labelEntries}
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
`);
|
|
340
|
+
}
|
|
341
|
+
parts.push(`/** Get label for ${name} value (fallback to value if no label) */
|
|
342
|
+
`);
|
|
343
|
+
parts.push(`export function get${name}Label(value: ${name}): string {
|
|
344
|
+
`);
|
|
345
|
+
if (hasLabels) {
|
|
346
|
+
parts.push(` return ${lowerFirst(name)}Labels[value] ?? value;
|
|
347
|
+
`);
|
|
348
|
+
} else {
|
|
349
|
+
parts.push(` return value;
|
|
350
|
+
`);
|
|
351
|
+
}
|
|
352
|
+
parts.push(`}
|
|
353
|
+
|
|
354
|
+
`);
|
|
355
|
+
const hasExtra = values.some((v) => v.extra !== void 0);
|
|
356
|
+
if (hasExtra) {
|
|
357
|
+
const extraEntries = values.filter((v) => v.extra !== void 0).map((v) => ` [${name}.${v.name}]: ${JSON.stringify(v.extra)},`).join("\n");
|
|
358
|
+
parts.push(`const ${lowerFirst(name)}Extra: Partial<Record<${name}, Record<string, unknown>>> = {
|
|
359
|
+
${extraEntries}
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
`);
|
|
363
|
+
parts.push(`/** Get extra metadata for ${name} value (undefined if not defined) */
|
|
364
|
+
`);
|
|
365
|
+
parts.push(`export function get${name}Extra(value: ${name}): Record<string, unknown> | undefined {
|
|
366
|
+
`);
|
|
367
|
+
parts.push(` return ${lowerFirst(name)}Extra[value];
|
|
368
|
+
`);
|
|
369
|
+
parts.push(`}`);
|
|
370
|
+
} else {
|
|
371
|
+
parts.push(`/** Get extra metadata for ${name} value (undefined if not defined) */
|
|
372
|
+
`);
|
|
373
|
+
parts.push(`export function get${name}Extra(_value: ${name}): Record<string, unknown> | undefined {
|
|
374
|
+
`);
|
|
375
|
+
parts.push(` return undefined;
|
|
376
|
+
`);
|
|
377
|
+
parts.push(`}`);
|
|
378
|
+
}
|
|
379
|
+
return parts.join("");
|
|
380
|
+
}
|
|
381
|
+
function lowerFirst(str) {
|
|
382
|
+
return str.charAt(0).toLowerCase() + str.slice(1);
|
|
277
383
|
}
|
|
278
384
|
function formatTypeAlias(alias) {
|
|
279
|
-
const comment = alias
|
|
280
|
-
|
|
385
|
+
const { name, type, comment } = alias;
|
|
386
|
+
const parts = [];
|
|
387
|
+
if (comment) {
|
|
388
|
+
parts.push(`/**
|
|
389
|
+
* ${comment}
|
|
281
390
|
*/
|
|
282
|
-
`
|
|
283
|
-
|
|
391
|
+
`);
|
|
392
|
+
}
|
|
393
|
+
parts.push(`export type ${name} = ${type};
|
|
394
|
+
|
|
395
|
+
`);
|
|
396
|
+
const values = type.split(" | ").map((v) => v.trim());
|
|
397
|
+
parts.push(`/** All ${name} values */
|
|
398
|
+
`);
|
|
399
|
+
parts.push(`export const ${name}Values: ${name}[] = [${values.join(", ")}];
|
|
400
|
+
|
|
401
|
+
`);
|
|
402
|
+
parts.push(`/** Type guard for ${name} */
|
|
403
|
+
`);
|
|
404
|
+
parts.push(`export function is${name}(value: unknown): value is ${name} {
|
|
405
|
+
`);
|
|
406
|
+
parts.push(` return ${name}Values.includes(value as ${name});
|
|
407
|
+
`);
|
|
408
|
+
parts.push(`}
|
|
409
|
+
|
|
410
|
+
`);
|
|
411
|
+
parts.push(`/** Get label for ${name} value (returns value as-is) */
|
|
412
|
+
`);
|
|
413
|
+
parts.push(`export function get${name}Label(value: ${name}): string {
|
|
414
|
+
`);
|
|
415
|
+
parts.push(` return value;
|
|
416
|
+
`);
|
|
417
|
+
parts.push(`}
|
|
418
|
+
|
|
419
|
+
`);
|
|
420
|
+
parts.push(`/** Get extra metadata for ${name} value (always undefined for type aliases) */
|
|
421
|
+
`);
|
|
422
|
+
parts.push(`export function get${name}Extra(_value: ${name}): Record<string, unknown> | undefined {
|
|
423
|
+
`);
|
|
424
|
+
parts.push(` return undefined;
|
|
425
|
+
`);
|
|
426
|
+
parts.push(`}`);
|
|
427
|
+
return parts.join("");
|
|
284
428
|
}
|
|
285
|
-
function extractInlineEnums(schemas) {
|
|
429
|
+
function extractInlineEnums(schemas, options = {}) {
|
|
286
430
|
const typeAliases = [];
|
|
287
431
|
for (const schema of Object.values(schemas)) {
|
|
288
432
|
if (schema.kind === "enum" || !schema.properties) {
|
|
@@ -293,10 +437,14 @@ function extractInlineEnums(schemas) {
|
|
|
293
437
|
const enumProp = property;
|
|
294
438
|
if (Array.isArray(enumProp.enum) && enumProp.enum.length > 0) {
|
|
295
439
|
const typeName = `${schema.name}${propName.charAt(0).toUpperCase() + propName.slice(1)}`;
|
|
440
|
+
const values = enumProp.enum.map(
|
|
441
|
+
(v) => typeof v === "string" ? v : v.value
|
|
442
|
+
);
|
|
443
|
+
const displayName = resolveDisplayName2(enumProp.displayName, options);
|
|
296
444
|
typeAliases.push({
|
|
297
445
|
name: typeName,
|
|
298
|
-
type:
|
|
299
|
-
comment:
|
|
446
|
+
type: values.map((v) => `'${v}'`).join(" | "),
|
|
447
|
+
comment: displayName ?? `${schema.name} ${propName} enum`
|
|
300
448
|
});
|
|
301
449
|
}
|
|
302
450
|
}
|
|
@@ -304,10 +452,11 @@ function extractInlineEnums(schemas) {
|
|
|
304
452
|
const selectProp = property;
|
|
305
453
|
if (selectProp.options && selectProp.options.length > 0) {
|
|
306
454
|
const typeName = `${schema.name}${propName.charAt(0).toUpperCase() + propName.slice(1)}`;
|
|
455
|
+
const displayName = resolveDisplayName2(selectProp.displayName, options);
|
|
307
456
|
typeAliases.push({
|
|
308
457
|
name: typeName,
|
|
309
458
|
type: selectProp.options.map((v) => `'${v}'`).join(" | "),
|
|
310
|
-
comment:
|
|
459
|
+
comment: displayName ?? `${schema.name} ${propName} options`
|
|
311
460
|
});
|
|
312
461
|
}
|
|
313
462
|
}
|
|
@@ -318,196 +467,187 @@ function extractInlineEnums(schemas) {
|
|
|
318
467
|
|
|
319
468
|
// src/generator.ts
|
|
320
469
|
var DEFAULT_OPTIONS = {
|
|
321
|
-
singleFile: true,
|
|
322
|
-
fileName: "types.ts",
|
|
323
470
|
readonly: true,
|
|
324
471
|
strictNullChecks: true
|
|
325
472
|
};
|
|
326
|
-
function
|
|
473
|
+
function generateBaseHeader() {
|
|
327
474
|
return `/**
|
|
328
475
|
* Auto-generated TypeScript types from Omnify schemas.
|
|
329
|
-
* DO NOT EDIT - This file is automatically generated.
|
|
476
|
+
* DO NOT EDIT - This file is automatically generated and will be overwritten.
|
|
330
477
|
*/
|
|
331
478
|
|
|
332
479
|
`;
|
|
333
480
|
}
|
|
334
|
-
function
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
481
|
+
function generateModelHeader(schemaName) {
|
|
482
|
+
return `/**
|
|
483
|
+
* ${schemaName} Model
|
|
484
|
+
*
|
|
485
|
+
* This file extends the auto-generated base interface.
|
|
486
|
+
* You can add custom methods, computed properties, or override types here.
|
|
487
|
+
* This file will NOT be overwritten by the generator.
|
|
488
|
+
*/
|
|
489
|
+
|
|
490
|
+
`;
|
|
491
|
+
}
|
|
492
|
+
function generateBaseInterfaceFile(schemaName, schemas, options) {
|
|
493
|
+
const interfaces = generateInterfaces(schemas, options);
|
|
494
|
+
const iface = interfaces.find((i) => i.name === schemaName);
|
|
495
|
+
if (!iface) {
|
|
496
|
+
throw new Error(`Interface not found for schema: ${schemaName}`);
|
|
497
|
+
}
|
|
498
|
+
const parts = [generateBaseHeader()];
|
|
499
|
+
parts.push(formatInterface(iface));
|
|
500
|
+
parts.push("\n");
|
|
501
|
+
return {
|
|
502
|
+
filePath: `base/${schemaName}.ts`,
|
|
503
|
+
content: parts.join(""),
|
|
504
|
+
types: [schemaName],
|
|
505
|
+
overwrite: true
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
function generateEnumFile(enumDef) {
|
|
509
|
+
const parts = [generateBaseHeader()];
|
|
510
|
+
parts.push(formatEnum(enumDef));
|
|
511
|
+
parts.push("\n");
|
|
512
|
+
return {
|
|
513
|
+
filePath: `enum/${enumDef.name}.ts`,
|
|
514
|
+
content: parts.join(""),
|
|
515
|
+
types: [enumDef.name],
|
|
516
|
+
overwrite: true
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
function generateTypeAliasFile(alias) {
|
|
520
|
+
const parts = [generateBaseHeader()];
|
|
521
|
+
parts.push(formatTypeAlias(alias));
|
|
522
|
+
parts.push("\n");
|
|
523
|
+
return {
|
|
524
|
+
filePath: `enum/${alias.name}.ts`,
|
|
525
|
+
content: parts.join(""),
|
|
526
|
+
types: [alias.name],
|
|
527
|
+
overwrite: true
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
function generateModelFile(schemaName) {
|
|
531
|
+
const parts = [generateModelHeader(schemaName)];
|
|
532
|
+
parts.push(`import type { ${schemaName} as ${schemaName}Base } from './base/${schemaName}.js';
|
|
533
|
+
|
|
534
|
+
`);
|
|
535
|
+
parts.push(`/**
|
|
536
|
+
* ${schemaName} model interface.
|
|
537
|
+
* Add custom properties or methods here.
|
|
538
|
+
*/
|
|
539
|
+
`);
|
|
540
|
+
parts.push(`export interface ${schemaName} extends ${schemaName}Base {
|
|
541
|
+
`);
|
|
542
|
+
parts.push(` // Add custom properties here
|
|
543
|
+
`);
|
|
544
|
+
parts.push(`}
|
|
545
|
+
|
|
546
|
+
`);
|
|
547
|
+
parts.push(`// Re-export base type for internal use
|
|
548
|
+
`);
|
|
549
|
+
parts.push(`export type { ${schemaName}Base };
|
|
550
|
+
`);
|
|
551
|
+
return {
|
|
552
|
+
filePath: `${schemaName}.ts`,
|
|
553
|
+
content: parts.join(""),
|
|
554
|
+
types: [schemaName],
|
|
555
|
+
overwrite: false
|
|
556
|
+
// Never overwrite user models
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
function generateIndexFile(schemas, enums, typeAliases) {
|
|
560
|
+
const parts = [generateBaseHeader()];
|
|
561
|
+
if (enums.length > 0 || typeAliases.length > 0) {
|
|
562
|
+
parts.push(`// Enums
|
|
563
|
+
`);
|
|
341
564
|
for (const enumDef of enums) {
|
|
342
|
-
parts.push(
|
|
343
|
-
|
|
344
|
-
|
|
565
|
+
parts.push(`export {
|
|
566
|
+
`);
|
|
567
|
+
parts.push(` ${enumDef.name},
|
|
568
|
+
`);
|
|
569
|
+
parts.push(` ${enumDef.name}Values,
|
|
570
|
+
`);
|
|
571
|
+
parts.push(` is${enumDef.name},
|
|
572
|
+
`);
|
|
573
|
+
parts.push(` get${enumDef.name}Label,
|
|
574
|
+
`);
|
|
575
|
+
parts.push(` get${enumDef.name}Extra,
|
|
576
|
+
`);
|
|
577
|
+
parts.push(`} from './enum/${enumDef.name}.js';
|
|
578
|
+
`);
|
|
345
579
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
parts.push(
|
|
352
|
-
|
|
353
|
-
|
|
580
|
+
for (const alias of typeAliases) {
|
|
581
|
+
parts.push(`export {
|
|
582
|
+
`);
|
|
583
|
+
parts.push(` type ${alias.name},
|
|
584
|
+
`);
|
|
585
|
+
parts.push(` ${alias.name}Values,
|
|
586
|
+
`);
|
|
587
|
+
parts.push(` is${alias.name},
|
|
588
|
+
`);
|
|
589
|
+
parts.push(` get${alias.name}Label,
|
|
590
|
+
`);
|
|
591
|
+
parts.push(` get${alias.name}Extra,
|
|
592
|
+
`);
|
|
593
|
+
parts.push(`} from './enum/${alias.name}.js';
|
|
594
|
+
`);
|
|
354
595
|
}
|
|
596
|
+
parts.push("\n");
|
|
355
597
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
types.push(iface.name);
|
|
363
|
-
}
|
|
598
|
+
parts.push(`// Models
|
|
599
|
+
`);
|
|
600
|
+
for (const schema of Object.values(schemas)) {
|
|
601
|
+
if (schema.kind === "enum") continue;
|
|
602
|
+
parts.push(`export type { ${schema.name} } from './${schema.name}.js';
|
|
603
|
+
`);
|
|
364
604
|
}
|
|
365
605
|
return {
|
|
366
|
-
|
|
367
|
-
content: parts.join("")
|
|
368
|
-
types
|
|
606
|
+
filePath: "index.ts",
|
|
607
|
+
content: parts.join(""),
|
|
608
|
+
types: [],
|
|
609
|
+
overwrite: true
|
|
369
610
|
};
|
|
370
611
|
}
|
|
371
|
-
function
|
|
612
|
+
function generateTypeScript(schemas, options = {}) {
|
|
372
613
|
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
373
614
|
const files = [];
|
|
374
615
|
const enums = generateEnums(schemas);
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
files.push({
|
|
378
|
-
fileName: "enums.ts",
|
|
379
|
-
content,
|
|
380
|
-
types: enums.map((e) => e.name)
|
|
381
|
-
});
|
|
616
|
+
for (const enumDef of enums) {
|
|
617
|
+
files.push(generateEnumFile(enumDef));
|
|
382
618
|
}
|
|
383
|
-
const
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
files.push({
|
|
387
|
-
fileName: "type-aliases.ts",
|
|
388
|
-
content,
|
|
389
|
-
types: inlineEnums.map((a) => a.name)
|
|
390
|
-
});
|
|
619
|
+
const typeAliases = extractInlineEnums(schemas);
|
|
620
|
+
for (const alias of typeAliases) {
|
|
621
|
+
files.push(generateTypeAliasFile(alias));
|
|
391
622
|
}
|
|
392
|
-
const
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
const importStatement = formatImports(imports);
|
|
396
|
-
const content = generateHeader() + (importStatement ? importStatement + "\n\n" : "") + formatInterface(iface) + "\n";
|
|
397
|
-
files.push({
|
|
398
|
-
fileName: `${toKebabCase(iface.name)}.ts`,
|
|
399
|
-
content,
|
|
400
|
-
types: [iface.name]
|
|
401
|
-
});
|
|
402
|
-
}
|
|
403
|
-
const indexContent = generateIndexFile(files);
|
|
404
|
-
files.push({
|
|
405
|
-
fileName: "index.ts",
|
|
406
|
-
content: indexContent,
|
|
407
|
-
types: []
|
|
408
|
-
});
|
|
409
|
-
return files;
|
|
410
|
-
}
|
|
411
|
-
function toKebabCase(name) {
|
|
412
|
-
return name.replace(/([A-Z])/g, "-$1").toLowerCase().replace(/^-/, "");
|
|
413
|
-
}
|
|
414
|
-
function collectImports(iface, enums, typeAliases, allInterfaces) {
|
|
415
|
-
const imports = /* @__PURE__ */ new Map();
|
|
416
|
-
const enumNames = new Set(enums.map((e) => e.name));
|
|
417
|
-
const aliasNames = new Set(typeAliases.map((a) => a.name));
|
|
418
|
-
const interfaceNames = new Set(allInterfaces.map((i) => i.name));
|
|
419
|
-
for (const prop of iface.properties) {
|
|
420
|
-
if (enumNames.has(prop.type)) {
|
|
421
|
-
const existing = imports.get("./enums.js") ?? [];
|
|
422
|
-
if (!existing.includes(prop.type)) {
|
|
423
|
-
imports.set("./enums.js", [...existing, prop.type]);
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
if (aliasNames.has(prop.type)) {
|
|
427
|
-
const existing = imports.get("./type-aliases.js") ?? [];
|
|
428
|
-
if (!existing.includes(prop.type)) {
|
|
429
|
-
imports.set("./type-aliases.js", [...existing, prop.type]);
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
const baseType = prop.type.replace("[]", "");
|
|
433
|
-
if (interfaceNames.has(baseType) && baseType !== iface.name) {
|
|
434
|
-
const fileName = `./${toKebabCase(baseType)}.js`;
|
|
435
|
-
const existing = imports.get(fileName) ?? [];
|
|
436
|
-
if (!existing.includes(baseType)) {
|
|
437
|
-
imports.set(fileName, [...existing, baseType]);
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
return imports;
|
|
442
|
-
}
|
|
443
|
-
function formatImports(imports) {
|
|
444
|
-
if (imports.size === 0) return "";
|
|
445
|
-
const lines = [];
|
|
446
|
-
for (const [path, names] of imports) {
|
|
447
|
-
lines.push(`import type { ${names.join(", ")} } from '${path}';`);
|
|
448
|
-
}
|
|
449
|
-
return lines.join("\n");
|
|
450
|
-
}
|
|
451
|
-
function generateIndexFile(files) {
|
|
452
|
-
const exports2 = [generateHeader().trim(), ""];
|
|
453
|
-
for (const file of files) {
|
|
454
|
-
if (file.fileName === "index.ts") continue;
|
|
455
|
-
const moduleName = file.fileName.replace(".ts", ".js");
|
|
456
|
-
exports2.push(`export * from './${moduleName}';`);
|
|
623
|
+
for (const schema of Object.values(schemas)) {
|
|
624
|
+
if (schema.kind === "enum") continue;
|
|
625
|
+
files.push(generateBaseInterfaceFile(schema.name, schemas, opts));
|
|
457
626
|
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
462
|
-
if (opts.singleFile) {
|
|
463
|
-
return [generateTypeScriptFile(schemas, opts)];
|
|
627
|
+
for (const schema of Object.values(schemas)) {
|
|
628
|
+
if (schema.kind === "enum") continue;
|
|
629
|
+
files.push(generateModelFile(schema.name));
|
|
464
630
|
}
|
|
465
|
-
|
|
631
|
+
files.push(generateIndexFile(schemas, enums, typeAliases));
|
|
632
|
+
return files;
|
|
466
633
|
}
|
|
467
634
|
|
|
468
635
|
// src/plugin.ts
|
|
469
636
|
var TYPESCRIPT_CONFIG_SCHEMA = {
|
|
470
637
|
fields: [
|
|
471
638
|
{
|
|
472
|
-
key: "
|
|
639
|
+
key: "modelsPath",
|
|
473
640
|
type: "path",
|
|
474
|
-
label: "
|
|
475
|
-
description: "Directory for generated TypeScript
|
|
476
|
-
default: "types",
|
|
477
|
-
group: "output"
|
|
478
|
-
},
|
|
479
|
-
{
|
|
480
|
-
key: "singleFile",
|
|
481
|
-
type: "boolean",
|
|
482
|
-
label: "Single File Output",
|
|
483
|
-
description: "Generate all types in a single file (types.ts) instead of separate files",
|
|
484
|
-
default: true,
|
|
641
|
+
label: "Models Output Path",
|
|
642
|
+
description: "Directory for generated TypeScript model files",
|
|
643
|
+
default: "types/models",
|
|
485
644
|
group: "output"
|
|
486
|
-
},
|
|
487
|
-
{
|
|
488
|
-
key: "generateEnums",
|
|
489
|
-
type: "boolean",
|
|
490
|
-
label: "Generate Enums",
|
|
491
|
-
description: "Generate TypeScript enums from schema enums",
|
|
492
|
-
default: true,
|
|
493
|
-
group: "options"
|
|
494
|
-
},
|
|
495
|
-
{
|
|
496
|
-
key: "generateRelationships",
|
|
497
|
-
type: "boolean",
|
|
498
|
-
label: "Generate Relationships",
|
|
499
|
-
description: "Include relationship types in interfaces",
|
|
500
|
-
default: true,
|
|
501
|
-
group: "options"
|
|
502
645
|
}
|
|
503
646
|
]
|
|
504
647
|
};
|
|
505
648
|
function resolveOptions(options) {
|
|
506
649
|
return {
|
|
507
|
-
|
|
508
|
-
singleFile: options?.singleFile ?? true,
|
|
509
|
-
generateEnums: options?.generateEnums ?? true,
|
|
510
|
-
generateRelationships: options?.generateRelationships ?? true
|
|
650
|
+
modelsPath: options?.modelsPath ?? "types/models"
|
|
511
651
|
};
|
|
512
652
|
}
|
|
513
653
|
function typescriptPlugin(options) {
|
|
@@ -518,17 +658,15 @@ function typescriptPlugin(options) {
|
|
|
518
658
|
configSchema: TYPESCRIPT_CONFIG_SCHEMA,
|
|
519
659
|
generators: [
|
|
520
660
|
{
|
|
521
|
-
name: "typescript-
|
|
522
|
-
description: "Generate TypeScript
|
|
661
|
+
name: "typescript-models",
|
|
662
|
+
description: "Generate TypeScript model definitions",
|
|
523
663
|
generate: async (ctx) => {
|
|
524
|
-
const
|
|
525
|
-
singleFile: resolved.singleFile
|
|
526
|
-
};
|
|
527
|
-
const files = generateTypeScript(ctx.schemas, tsOptions);
|
|
664
|
+
const files = generateTypeScript(ctx.schemas);
|
|
528
665
|
return files.map((file) => ({
|
|
529
|
-
path: `${resolved.
|
|
666
|
+
path: `${resolved.modelsPath}/${file.filePath}`,
|
|
530
667
|
content: file.content,
|
|
531
668
|
type: "type",
|
|
669
|
+
overwrite: file.overwrite,
|
|
532
670
|
metadata: {
|
|
533
671
|
types: file.types
|
|
534
672
|
}
|