@omnifyjp/ts 5.8.34 → 5.8.36

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 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 });
@@ -17,17 +17,21 @@ export declare function generateEnums(schemas: Record<string, SchemaDefinition>,
17
17
  export declare function generatePluginEnums(pluginEnums: Record<string, string[]>, _options: GeneratorOptions): TSEnum[];
18
18
  /** Format a TypeScript enum with helpers (Values array, type guard, label getter).
19
19
  *
20
- * Emits the `as const` object pattern instead of `export enum X { ... }`.
21
- * Reasoning: TS 5.5+ ships with `erasableSyntaxOnly` enabled by default in
22
- * Vite 7 starters and recommended by the TS team for new projects, which
23
- * disallows enums (they emit runtime code that type-only-stripping tools
24
- * like esbuild + deno + bun can't erase). The const-object pattern
25
- * preserves identical call-site ergonomics — `X.User` still resolves to
26
- * the string value, the union type still narrows correctly, label /
27
- * value-array helpers all work but compiles under every strict-mode
28
- * preset. Pilot #103 Issue 1.
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.
29
33
  */
30
- export declare function formatEnum(enumDef: TSEnum): string;
34
+ export declare function formatEnum(enumDef: TSEnum, style?: 'enum' | 'const'): string;
31
35
  /** Format a TypeScript type alias with helpers. */
32
36
  export declare function formatTypeAlias(alias: TSTypeAlias): string;
33
37
  /** Result of extracting inline enums. */
@@ -99,31 +99,43 @@ function escapeString(str) {
99
99
  }
100
100
  /** Format a TypeScript enum with helpers (Values array, type guard, label getter).
101
101
  *
102
- * Emits the `as const` object pattern instead of `export enum X { ... }`.
103
- * Reasoning: TS 5.5+ ships with `erasableSyntaxOnly` enabled by default in
104
- * Vite 7 starters and recommended by the TS team for new projects, which
105
- * disallows enums (they emit runtime code that type-only-stripping tools
106
- * like esbuild + deno + bun can't erase). The const-object pattern
107
- * preserves identical call-site ergonomics — `X.User` still resolves to
108
- * the string value, the union type still narrows correctly, label /
109
- * value-array helpers all work but compiles under every strict-mode
110
- * preset. Pilot #103 Issue 1.
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.
111
115
  */
112
- export function formatEnum(enumDef) {
116
+ export function formatEnum(enumDef, style = 'enum') {
113
117
  const { name, values, comment } = enumDef;
114
118
  const parts = [];
115
119
  if (comment) {
116
120
  parts.push(`/**\n * ${comment}\n */\n`);
117
121
  }
118
- // Const object works under erasableSyntaxOnly. Identical access at
119
- // call sites: `X.User === 'user'` (literal string equality).
120
- const enumValues = values.map(v => ` ${v.name}: '${v.value}',`).join('\n');
121
- parts.push(`export const ${name} = {\n${enumValues}\n} as const;\n\n`);
122
- // Type alias string union derived from the const object's values. A
123
- // function parameter typed `${name}` accepts `X.User` AND the literal
124
- // 'user' (same shape as enums had). The `keyof typeof` extraction is
125
- // the canonical TS pattern for this.
126
- parts.push(`export type ${name} = typeof ${name}[keyof typeof ${name}];\n\n`);
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
+ }
127
139
  // Values array
128
140
  parts.push(`/** All ${name} values */\n`);
129
141
  parts.push(`export const ${name}Values = Object.values(${name}) as ${name}[];\n\n`);
@@ -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. */
@@ -144,9 +145,9 @@ function insertPayloadImports(parts) {
144
145
  parts.splice(1, 0, importBlock);
145
146
  }
146
147
  /** Generate an enum file. */
147
- function generateEnumFile(enumDef, isPlugin) {
148
+ function generateEnumFile(enumDef, isPlugin, options) {
148
149
  const parts = [generateBaseHeader()];
149
- parts.push(formatEnum(enumDef));
150
+ parts.push(formatEnum(enumDef, options.enumStyle));
150
151
  parts.push('\n');
151
152
  return {
152
153
  filePath: `${enumDef.name}.ts`,
@@ -456,12 +457,12 @@ export function generateTypeScript(input, extra) {
456
457
  // Schema enums (e.g., PostStatus)
457
458
  const schemaEnums = generateEnums(schemas, options);
458
459
  for (const enumDef of schemaEnums) {
459
- files.push(generateEnumFile(enumDef, false));
460
+ files.push(generateEnumFile(enumDef, false, options));
460
461
  }
461
462
  // Plugin enums (e.g., Prefecture, BankAccountType from customTypes.enums)
462
463
  const pluginEnums = generatePluginEnums(input.customTypes.enums, options);
463
464
  for (const enumDef of pluginEnums) {
464
- files.push(generateEnumFile(enumDef, true));
465
+ files.push(generateEnumFile(enumDef, true, options));
465
466
  }
466
467
  // Inline enums from properties (type aliases or full enums)
467
468
  const inlineEnums = extractInlineEnums(schemas, options);
@@ -469,7 +470,7 @@ export function generateTypeScript(input, extra) {
469
470
  for (const item of inlineEnums) {
470
471
  if (item.enum) {
471
472
  schemaEnums.push(item.enum);
472
- files.push(generateEnumFile(item.enum, false));
473
+ files.push(generateEnumFile(item.enum, false, options));
473
474
  }
474
475
  else if (item.typeAlias) {
475
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnifyjp/ts",
3
- "version": "5.8.34",
3
+ "version": "5.8.36",
4
4
  "description": "TypeScript model type generator from Omnify schemas.json",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",