@omnifyjp/ts 5.8.33 → 5.8.35
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/cli.js +4 -0
- package/dist/enum-generator.d.ts +17 -2
- package/dist/enum-generator.js +34 -5
- package/dist/generator.d.ts +2 -0
- package/dist/generator.js +15 -9
- package/dist/types.d.ts +21 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -107,6 +107,7 @@ function resolveFromConfig(configPath) {
|
|
|
107
107
|
tsOutput,
|
|
108
108
|
tsPlatform: tsConfig?.platform,
|
|
109
109
|
tsAuth: tsConfig?.auth,
|
|
110
|
+
tsEnumStyle: tsConfig?.enumStyle,
|
|
110
111
|
laravelEnabled,
|
|
111
112
|
laravelOverrides,
|
|
112
113
|
};
|
|
@@ -127,6 +128,7 @@ program
|
|
|
127
128
|
let tsOutput;
|
|
128
129
|
let tsPlatform;
|
|
129
130
|
let tsAuth;
|
|
131
|
+
let tsEnumStyle;
|
|
130
132
|
let laravelEnabled = false;
|
|
131
133
|
let laravelOverrides;
|
|
132
134
|
let configDir = process.cwd();
|
|
@@ -151,6 +153,7 @@ program
|
|
|
151
153
|
tsOutput = opts.output ? resolve(opts.output) : resolved.tsOutput;
|
|
152
154
|
tsPlatform = resolved.tsPlatform;
|
|
153
155
|
tsAuth = resolved.tsAuth;
|
|
156
|
+
tsEnumStyle = resolved.tsEnumStyle;
|
|
154
157
|
laravelEnabled = resolved.laravelEnabled;
|
|
155
158
|
laravelOverrides = resolved.laravelOverrides;
|
|
156
159
|
}
|
|
@@ -178,6 +181,7 @@ program
|
|
|
178
181
|
const files = generateTypeScript(input, {
|
|
179
182
|
platform: tsPlatform,
|
|
180
183
|
auth: tsAuth,
|
|
184
|
+
enumStyle: tsEnumStyle,
|
|
181
185
|
});
|
|
182
186
|
mkdirSync(join(tsOutput, 'base'), { recursive: true });
|
|
183
187
|
mkdirSync(join(tsOutput, 'enum'), { recursive: true });
|
package/dist/enum-generator.d.ts
CHANGED
|
@@ -15,8 +15,23 @@ export declare function schemaToEnum(schema: SchemaDefinition, options: Generato
|
|
|
15
15
|
export declare function generateEnums(schemas: Record<string, SchemaDefinition>, options: GeneratorOptions): TSEnum[];
|
|
16
16
|
/** Generate enums from plugin enums (customTypes.enums in schemas.json). */
|
|
17
17
|
export declare function generatePluginEnums(pluginEnums: Record<string, string[]>, _options: GeneratorOptions): TSEnum[];
|
|
18
|
-
/** Format a TypeScript enum with helpers (Values array, type guard, label getter).
|
|
19
|
-
|
|
18
|
+
/** Format a TypeScript enum with helpers (Values array, type guard, label getter).
|
|
19
|
+
*
|
|
20
|
+
* Two emission shapes (issue #103 Issue 1):
|
|
21
|
+
*
|
|
22
|
+
* - `'enum'` (DEFAULT): native `export enum X { ... }` — backwards-
|
|
23
|
+
* compatible with every project that depended on TS enum semantics
|
|
24
|
+
* (declaration merging via namespace, etc.) before v5.8.34.
|
|
25
|
+
*
|
|
26
|
+
* - `'const'`: `export const X = {...} as const; export type X = ...` —
|
|
27
|
+
* compiles under TS 5.5+ `erasableSyntaxOnly` (Vite 7 default).
|
|
28
|
+
* Call-site ergonomics identical to enum: `X.User === 'user'` works,
|
|
29
|
+
* string union narrowing works, all helper signatures unchanged.
|
|
30
|
+
*
|
|
31
|
+
* Pass `style` to pick. Default preserves the pre-v5.8.34 behavior so an
|
|
32
|
+
* upgrade without config change doesn't break consumer code.
|
|
33
|
+
*/
|
|
34
|
+
export declare function formatEnum(enumDef: TSEnum, style?: 'enum' | 'const'): string;
|
|
20
35
|
/** Format a TypeScript type alias with helpers. */
|
|
21
36
|
export declare function formatTypeAlias(alias: TSTypeAlias): string;
|
|
22
37
|
/** Result of extracting inline enums. */
|
package/dist/enum-generator.js
CHANGED
|
@@ -97,16 +97,45 @@ function lowerFirst(str) {
|
|
|
97
97
|
function escapeString(str) {
|
|
98
98
|
return str.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
|
99
99
|
}
|
|
100
|
-
/** Format a TypeScript enum with helpers (Values array, type guard, label getter).
|
|
101
|
-
|
|
100
|
+
/** Format a TypeScript enum with helpers (Values array, type guard, label getter).
|
|
101
|
+
*
|
|
102
|
+
* Two emission shapes (issue #103 Issue 1):
|
|
103
|
+
*
|
|
104
|
+
* - `'enum'` (DEFAULT): native `export enum X { ... }` — backwards-
|
|
105
|
+
* compatible with every project that depended on TS enum semantics
|
|
106
|
+
* (declaration merging via namespace, etc.) before v5.8.34.
|
|
107
|
+
*
|
|
108
|
+
* - `'const'`: `export const X = {...} as const; export type X = ...` —
|
|
109
|
+
* compiles under TS 5.5+ `erasableSyntaxOnly` (Vite 7 default).
|
|
110
|
+
* Call-site ergonomics identical to enum: `X.User === 'user'` works,
|
|
111
|
+
* string union narrowing works, all helper signatures unchanged.
|
|
112
|
+
*
|
|
113
|
+
* Pass `style` to pick. Default preserves the pre-v5.8.34 behavior so an
|
|
114
|
+
* upgrade without config change doesn't break consumer code.
|
|
115
|
+
*/
|
|
116
|
+
export function formatEnum(enumDef, style = 'enum') {
|
|
102
117
|
const { name, values, comment } = enumDef;
|
|
103
118
|
const parts = [];
|
|
104
119
|
if (comment) {
|
|
105
120
|
parts.push(`/**\n * ${comment}\n */\n`);
|
|
106
121
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
122
|
+
if (style === 'const') {
|
|
123
|
+
// Const object — works under erasableSyntaxOnly. Identical access at
|
|
124
|
+
// call sites: `X.User === 'user'` (literal string equality).
|
|
125
|
+
const enumValues = values.map(v => ` ${v.name}: '${v.value}',`).join('\n');
|
|
126
|
+
parts.push(`export const ${name} = {\n${enumValues}\n} as const;\n\n`);
|
|
127
|
+
// Type alias — string union derived from the const object's values.
|
|
128
|
+
// The `keyof typeof` extraction is the canonical TS pattern for this.
|
|
129
|
+
parts.push(`export type ${name} = typeof ${name}[keyof typeof ${name}];\n\n`);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
// Native `enum` — pre-v5.8.34 default. Some downstream projects
|
|
133
|
+
// depend on declaration-merging or other TS-enum-specific semantics
|
|
134
|
+
// that the const-object pattern can't replicate, so we keep this
|
|
135
|
+
// available as the safe upgrade path.
|
|
136
|
+
const enumValues = values.map(v => ` ${v.name} = '${v.value}',`).join('\n');
|
|
137
|
+
parts.push(`export enum ${name} {\n${enumValues}\n}\n\n`);
|
|
138
|
+
}
|
|
110
139
|
// Values array
|
|
111
140
|
parts.push(`/** All ${name} values */\n`);
|
|
112
141
|
parts.push(`export const ${name}Values = Object.values(${name}) as ${name}[];\n\n`);
|
package/dist/generator.d.ts
CHANGED
|
@@ -18,6 +18,8 @@ import type { SchemasJson, TypeScriptFile } from './types.js';
|
|
|
18
18
|
export interface GenerateExtraConfig {
|
|
19
19
|
platform?: 'web' | 'expo';
|
|
20
20
|
auth?: 'cookie' | 'secureStore';
|
|
21
|
+
/** Enum emission style — see GeneratorOptions.enumStyle. Issue #103. */
|
|
22
|
+
enumStyle?: 'enum' | 'const';
|
|
21
23
|
}
|
|
22
24
|
/**
|
|
23
25
|
* Generate all TypeScript files from schemas.json input.
|
package/dist/generator.js
CHANGED
|
@@ -42,6 +42,7 @@ function buildOptions(input, extra) {
|
|
|
42
42
|
customTypes: input.customTypes,
|
|
43
43
|
platform: extra?.platform,
|
|
44
44
|
auth: extra?.auth,
|
|
45
|
+
enumStyle: extra?.enumStyle,
|
|
45
46
|
};
|
|
46
47
|
}
|
|
47
48
|
/** Generate a base interface file for a schema. */
|
|
@@ -106,10 +107,15 @@ function generateBaseInterfaceFile(schemaName, schemas, options) {
|
|
|
106
107
|
// would be empty noise.
|
|
107
108
|
const formShape = buildFormShape(schema, schemas, options);
|
|
108
109
|
if (formShape.fields.length > 0) {
|
|
109
|
-
// The builders
|
|
110
|
-
// `
|
|
111
|
-
//
|
|
112
|
-
|
|
110
|
+
// The builders only reference `Locale` / `buildI18nPayload` /
|
|
111
|
+
// `emptyLocaleMap` for translatable fields. When the schema has no
|
|
112
|
+
// translatable field, those imports would be unused → trip TS6133
|
|
113
|
+
// (declared but never read) under noUnusedLocals. Pilot #103 Issue 2
|
|
114
|
+
// — emit imports conditionally on actual i18n usage.
|
|
115
|
+
const hasTranslatableField = formShape.fields.some(f => f.translatable);
|
|
116
|
+
if (hasTranslatableField) {
|
|
117
|
+
insertPayloadImports(parts);
|
|
118
|
+
}
|
|
113
119
|
parts.push(formatPayloadBuilderSection(formShape, options.defaultLocale));
|
|
114
120
|
}
|
|
115
121
|
return {
|
|
@@ -139,9 +145,9 @@ function insertPayloadImports(parts) {
|
|
|
139
145
|
parts.splice(1, 0, importBlock);
|
|
140
146
|
}
|
|
141
147
|
/** Generate an enum file. */
|
|
142
|
-
function generateEnumFile(enumDef, isPlugin) {
|
|
148
|
+
function generateEnumFile(enumDef, isPlugin, options) {
|
|
143
149
|
const parts = [generateBaseHeader()];
|
|
144
|
-
parts.push(formatEnum(enumDef));
|
|
150
|
+
parts.push(formatEnum(enumDef, options.enumStyle));
|
|
145
151
|
parts.push('\n');
|
|
146
152
|
return {
|
|
147
153
|
filePath: `${enumDef.name}.ts`,
|
|
@@ -451,12 +457,12 @@ export function generateTypeScript(input, extra) {
|
|
|
451
457
|
// Schema enums (e.g., PostStatus)
|
|
452
458
|
const schemaEnums = generateEnums(schemas, options);
|
|
453
459
|
for (const enumDef of schemaEnums) {
|
|
454
|
-
files.push(generateEnumFile(enumDef, false));
|
|
460
|
+
files.push(generateEnumFile(enumDef, false, options));
|
|
455
461
|
}
|
|
456
462
|
// Plugin enums (e.g., Prefecture, BankAccountType from customTypes.enums)
|
|
457
463
|
const pluginEnums = generatePluginEnums(input.customTypes.enums, options);
|
|
458
464
|
for (const enumDef of pluginEnums) {
|
|
459
|
-
files.push(generateEnumFile(enumDef, true));
|
|
465
|
+
files.push(generateEnumFile(enumDef, true, options));
|
|
460
466
|
}
|
|
461
467
|
// Inline enums from properties (type aliases or full enums)
|
|
462
468
|
const inlineEnums = extractInlineEnums(schemas, options);
|
|
@@ -464,7 +470,7 @@ export function generateTypeScript(input, extra) {
|
|
|
464
470
|
for (const item of inlineEnums) {
|
|
465
471
|
if (item.enum) {
|
|
466
472
|
schemaEnums.push(item.enum);
|
|
467
|
-
files.push(generateEnumFile(item.enum, false));
|
|
473
|
+
files.push(generateEnumFile(item.enum, false, options));
|
|
468
474
|
}
|
|
469
475
|
else if (item.typeAlias) {
|
|
470
476
|
inlineTypeAliases.push(item.typeAlias);
|
package/dist/types.d.ts
CHANGED
|
@@ -448,4 +448,25 @@ export interface GeneratorOptions {
|
|
|
448
448
|
readonly platform?: 'web' | 'expo';
|
|
449
449
|
/** Auth strategy: 'cookie' (default) or 'secureStore' (Expo). Issue #63. */
|
|
450
450
|
readonly auth?: 'cookie' | 'secureStore';
|
|
451
|
+
/**
|
|
452
|
+
* Enum emission style. Issue #103 Issue 1.
|
|
453
|
+
*
|
|
454
|
+
* - `'enum'` (default): emit `export enum X { ... }` — TypeScript native
|
|
455
|
+
* syntax. Compatible with projects predating TS 5.5 / projects that
|
|
456
|
+
* declaration-merge enums via namespace. INCOMPATIBLE with the
|
|
457
|
+
* `erasableSyntaxOnly` strict-mode option (TS 5.5+ default in Vite 7
|
|
458
|
+
* starters), which rejects enums because they emit runtime code that
|
|
459
|
+
* type-only-stripping tools (esbuild/deno/bun) can't erase.
|
|
460
|
+
*
|
|
461
|
+
* - `'const'`: emit `export const X = {...} as const; export type X = ...`
|
|
462
|
+
* — works under all strict modes. Identical call-site ergonomics
|
|
463
|
+
* (`X.User === 'user'`, type narrowing, helper functions). Pilot
|
|
464
|
+
* downstream uses this when their tsconfig enables erasableSyntaxOnly.
|
|
465
|
+
*
|
|
466
|
+
* Default `'enum'` preserves backwards compatibility for projects
|
|
467
|
+
* upgrading omnify without changing their omnify.yaml — set
|
|
468
|
+
* `enumStyle: 'const'` explicitly to opt into the strict-mode-friendly
|
|
469
|
+
* output.
|
|
470
|
+
*/
|
|
471
|
+
readonly enumStyle?: 'enum' | 'const';
|
|
451
472
|
}
|