@xndrjs/i18n 0.8.1 → 0.8.2-alpha.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.
Files changed (93) hide show
  1. package/README.md +1 -2
  2. package/dist/cli/audit.js +739 -0
  3. package/dist/cli/audit.js.map +1 -0
  4. package/dist/cli/codegen.js +1471 -0
  5. package/dist/cli/codegen.js.map +1 -0
  6. package/dist/cli/setup.js +148 -0
  7. package/dist/cli/setup.js.map +1 -0
  8. package/dist/codegen/index.js +43 -40
  9. package/dist/codegen/index.js.map +1 -1
  10. package/package.json +6 -9
  11. package/bin/audit.mjs +0 -14
  12. package/bin/codegen.mjs +0 -17
  13. package/bin/setup.mjs +0 -14
  14. package/src/IcuTranslationProviderMulti.test.ts +0 -215
  15. package/src/IcuTranslationProviderMulti.ts +0 -188
  16. package/src/audit/audit-dictionaries.test.ts +0 -134
  17. package/src/audit/audit-dictionaries.ts +0 -178
  18. package/src/audit/run-audit.test.ts +0 -169
  19. package/src/audit/run-audit.ts +0 -94
  20. package/src/builder-load-registry.test.ts +0 -44
  21. package/src/builder-load-registry.ts +0 -78
  22. package/src/builder-loaders.ts +0 -15
  23. package/src/builder-types.test.ts +0 -57
  24. package/src/builder-types.ts +0 -24
  25. package/src/builder.test.ts +0 -303
  26. package/src/builder.ts +0 -15
  27. package/src/codegen/codegen-config-schema.ts +0 -156
  28. package/src/codegen/config.test.ts +0 -231
  29. package/src/codegen/config.ts +0 -42
  30. package/src/codegen/constants.ts +0 -9
  31. package/src/codegen/delivery-artifacts.test.ts +0 -167
  32. package/src/codegen/delivery-artifacts.ts +0 -154
  33. package/src/codegen/dictionary-spec-contract.test.ts +0 -28
  34. package/src/codegen/dictionary-spec-contract.ts +0 -138
  35. package/src/codegen/emit/dictionary-schema-file.ts +0 -113
  36. package/src/codegen/emit/instance-file.test.ts +0 -71
  37. package/src/codegen/emit/instance-file.ts +0 -257
  38. package/src/codegen/emit/namespace-loaders-file.test.ts +0 -251
  39. package/src/codegen/emit/namespace-loaders-file.ts +0 -229
  40. package/src/codegen/emit/types-file.test.ts +0 -96
  41. package/src/codegen/emit/types-file.ts +0 -142
  42. package/src/codegen/fixtures/billing-namespace.json +0 -6
  43. package/src/codegen/generate-i18n-types.test.ts +0 -1137
  44. package/src/codegen/generate-i18n-types.ts +0 -20
  45. package/src/codegen/icu-analysis.ts +0 -110
  46. package/src/codegen/locale-fallback.ts +0 -73
  47. package/src/codegen/locale-policy.test.ts +0 -35
  48. package/src/codegen/locale-policy.ts +0 -30
  49. package/src/codegen/paths.ts +0 -44
  50. package/src/codegen/project-locales-set-namespace.test.ts +0 -134
  51. package/src/codegen/read-dictionary.test.ts +0 -594
  52. package/src/codegen/read-dictionary.ts +0 -260
  53. package/src/codegen/regenerate-namespaces.ts +0 -180
  54. package/src/codegen/run-codegen.test.ts +0 -230
  55. package/src/codegen/run-codegen.ts +0 -252
  56. package/src/codegen/types.ts +0 -10
  57. package/src/codegen/write-file-if-changed.test.ts +0 -42
  58. package/src/codegen/write-file-if-changed.ts +0 -20
  59. package/src/codegen-config/build-config.ts +0 -15
  60. package/src/codegen-config/codegen-config.test.ts +0 -36
  61. package/src/codegen-config/index.ts +0 -37
  62. package/src/codegen-config/type-names.ts +0 -20
  63. package/src/codegen-config/write-config.ts +0 -8
  64. package/src/engine.ts +0 -47
  65. package/src/fetch-artifact.ts +0 -16
  66. package/src/format-core.ts +0 -91
  67. package/src/i18n-handle.ts +0 -216
  68. package/src/icu/extract-variables.test.ts +0 -199
  69. package/src/icu/extract-variables.ts +0 -227
  70. package/src/icu/parse-template.ts +0 -31
  71. package/src/index.ts +0 -63
  72. package/src/load-state.ts +0 -15
  73. package/src/project-locales.test.ts +0 -280
  74. package/src/project-locales.ts +0 -211
  75. package/src/resolve-locale.test.ts +0 -91
  76. package/src/resolve-locale.ts +0 -88
  77. package/src/scope-multi.ts +0 -105
  78. package/src/scope-types.ts +0 -35
  79. package/src/scope.test.ts +0 -172
  80. package/src/serialized-state.test.ts +0 -114
  81. package/src/serialized-state.ts +0 -28
  82. package/src/setup/setup-i18n.test.ts +0 -85
  83. package/src/setup/setup-i18n.ts +0 -156
  84. package/src/types.ts +0 -65
  85. package/src/validation/create-args-schema.ts +0 -76
  86. package/src/validation/create-normalized-schema.ts +0 -52
  87. package/src/validation/errors.ts +0 -43
  88. package/src/validation/index.ts +0 -202
  89. package/src/validation/normalize.ts +0 -299
  90. package/src/validation/to-dictionary.ts +0 -67
  91. package/src/validation/types.ts +0 -82
  92. package/src/validation/validate-normalized.ts +0 -133
  93. package/src/validation/validation.test.ts +0 -562
@@ -1,303 +0,0 @@
1
- import { describe, expect, expectTypeOf, it, vi } from "vitest";
2
- import { createI18nHandle } from "./builder.js";
3
- import { IcuTranslationProviderMulti } from "./IcuTranslationProviderMulti.js";
4
-
5
- type MultiSchema = {
6
- default: {
7
- login_button: { en: string; it: string };
8
- welcome: { en: string };
9
- };
10
- billing: {
11
- invoice_summary: { en: string; it: string };
12
- };
13
- };
14
-
15
- type TestMultiParams = {
16
- default: {
17
- login_button: never;
18
- welcome: { name: string };
19
- };
20
- billing: {
21
- invoice_summary: { count: number; name: string };
22
- };
23
- };
24
-
25
- const billingIt = {
26
- invoice_summary: {
27
- it: "Hai {count, plural, one {1 fattura} other {{count} fatture}} per {name}",
28
- },
29
- };
30
-
31
- const billingEn = {
32
- invoice_summary: {
33
- en: "You have {count, plural, one {1 invoice} other {{count} invoices}} for {name}",
34
- },
35
- };
36
-
37
- const defaultIt = {
38
- login_button: { it: "Accedi" },
39
- welcome: { it: "Benvenuto {name}!" },
40
- };
41
-
42
- describe("I18nHandle", () => {
43
- it("load() invokes mock loaders, merges into the engine, and returns a bound view", async () => {
44
- const billingLoader = vi.fn(async (locale: string) => {
45
- return locale === "it" ? billingIt : billingEn;
46
- });
47
- const engine = new IcuTranslationProviderMulti<MultiSchema, TestMultiParams>({});
48
- const handle = createI18nHandle(engine, {
49
- namespaceLoaders: {
50
- billing: billingLoader,
51
- },
52
- });
53
-
54
- const view = await handle.load({ namespaces: ["billing"], locale: "it" });
55
-
56
- expect(billingLoader).toHaveBeenCalledWith("it", { locale: "it" });
57
- expect(view.locale).toBe("it");
58
- expect(view.t("billing", "invoice_summary", { count: 2, name: "Ada" })).toBe(
59
- "Hai 2 fatture per Ada"
60
- );
61
- });
62
-
63
- it("loads multiple namespaces in one call", async () => {
64
- const billingLoader = vi.fn(async (locale: string) =>
65
- locale === "it" ? billingIt : billingEn
66
- );
67
- const defaultLoader = vi.fn(async () => defaultIt);
68
- const engine = new IcuTranslationProviderMulti<MultiSchema, TestMultiParams>({});
69
-
70
- const view = await createI18nHandle(engine, {
71
- namespaceLoaders: {
72
- billing: billingLoader,
73
- default: defaultLoader,
74
- },
75
- }).load({ namespaces: ["billing", "default"], locale: "it" });
76
-
77
- expect(billingLoader).toHaveBeenCalledWith("it", { locale: "it" });
78
- expect(defaultLoader).toHaveBeenCalledWith("it", { locale: "it" });
79
- expect(view.t("default", "login_button")).toBe("Accedi");
80
- expect(view.t("billing", "invoice_summary", { count: 1, name: "Bob" })).toBe(
81
- "Hai 1 fattura per Bob"
82
- );
83
- });
84
-
85
- it("accumulates engine data across repeated load() calls on the same handle", async () => {
86
- const billingLoader = vi.fn(async (locale: string) =>
87
- locale === "it" ? billingIt : billingEn
88
- );
89
- const defaultLoader = vi.fn(async () => defaultIt);
90
- const engine = new IcuTranslationProviderMulti<MultiSchema, TestMultiParams>({});
91
- const handle = createI18nHandle(engine, {
92
- namespaceLoaders: {
93
- billing: billingLoader,
94
- default: defaultLoader,
95
- },
96
- });
97
-
98
- const billingView = await handle.load({ namespaces: ["billing"], locale: "it" });
99
- const defaultView = await handle.load({ namespaces: ["default"], locale: "it" });
100
-
101
- expect(billingLoader).toHaveBeenCalledTimes(1);
102
- expect(defaultLoader).toHaveBeenCalledTimes(1);
103
- expect(billingView.t("billing", "invoice_summary", { count: 1, name: "Ada" })).toBe(
104
- "Hai 1 fattura per Ada"
105
- );
106
- expect(defaultView.t("default", "login_button")).toBe("Accedi");
107
- expect(engine.getAll().billing?.invoice_summary?.it).toBe(billingIt.invoice_summary.it);
108
- expect(engine.getAll().default?.login_button?.it).toBe("Accedi");
109
- });
110
-
111
- it("returns a view scoped to namespaces declared at load time", async () => {
112
- const billingLoader = vi.fn(async (locale: string) =>
113
- locale === "it" ? billingIt : billingEn
114
- );
115
- const defaultLoader = vi.fn(async () => defaultIt);
116
- const engine = new IcuTranslationProviderMulti<MultiSchema, TestMultiParams>({});
117
- const handle = createI18nHandle(engine, {
118
- namespaceLoaders: {
119
- billing: billingLoader,
120
- default: defaultLoader,
121
- },
122
- });
123
-
124
- const billingView = await handle.load({ namespaces: ["billing"], locale: "it" });
125
- await handle.load({ namespaces: ["default"], locale: "it" });
126
-
127
- expect(billingView.t("billing", "invoice_summary", { count: 1, name: "Ada" })).toBe(
128
- "Hai 1 fattura per Ada"
129
- );
130
- // billingView is typed for the billing namespace only; default is excluded at compile time.
131
- });
132
-
133
- it("maps locale to delivery partition via partitionForLocale", async () => {
134
- const billingLoader = vi.fn(async (area: string) => {
135
- return area === "eu" ? billingIt : billingEn;
136
- });
137
- const engine = new IcuTranslationProviderMulti<MultiSchema, TestMultiParams>({});
138
-
139
- const view = await createI18nHandle(engine, {
140
- namespaceLoaders: {
141
- billing: billingLoader,
142
- },
143
- partitionForLocale: (locale) => (locale === "it" ? "eu" : "us"),
144
- }).load({ namespaces: ["billing"], locale: "it" });
145
-
146
- expect(billingLoader).toHaveBeenCalledWith("eu", { locale: "it" });
147
- expect(view.locale).toBe("it");
148
- expect(view.t("billing", "invoice_summary", { count: 2, name: "Ada" })).toBe(
149
- "Hai 2 fatture per Ada"
150
- );
151
- expectTypeOf(view.t).toBeCallableWith("billing", "invoice_summary", {
152
- count: 2,
153
- name: "Ada",
154
- });
155
- });
156
-
157
- it("loads partitioned namespace loaders with locale", async () => {
158
- const billingLoader = vi.fn(async (locale: string) =>
159
- locale === "it"
160
- ? {
161
- invoice_summary: {
162
- it: "Hai {count, plural, one {1 fattura} other {{count} fatture}} per {name}",
163
- },
164
- }
165
- : {
166
- invoice_summary: {
167
- en: "You have {count, plural, one {1 invoice} other {{count} invoices}} for {name}",
168
- },
169
- }
170
- );
171
- const engine = new IcuTranslationProviderMulti<MultiSchema, TestMultiParams>({});
172
-
173
- const view = await createI18nHandle(engine, {
174
- namespaceLoaders: {
175
- billing: billingLoader,
176
- },
177
- }).load({ namespaces: ["billing"], locale: "en" });
178
-
179
- expect(billingLoader).toHaveBeenCalledTimes(1);
180
- expect(billingLoader.mock.calls[0]).toEqual(["en", { locale: "en" }]);
181
- expect(view.t("billing", "invoice_summary", { count: 1, name: "Ada" })).toBe(
182
- "You have 1 invoice for Ada"
183
- );
184
- });
185
-
186
- it("rejects an empty namespaces array", async () => {
187
- const billingLoader = vi.fn(async () => billingEn);
188
- const engine = new IcuTranslationProviderMulti<MultiSchema, TestMultiParams>({});
189
- const handle = createI18nHandle(engine, {
190
- namespaceLoaders: {
191
- billing: billingLoader,
192
- },
193
- });
194
-
195
- await expect(
196
- handle.load({ namespaces: [] as unknown as ["billing"], locale: "en" })
197
- ).rejects.toThrow("load() requires a non-empty namespaces array");
198
- });
199
-
200
- it("skips a repeated load for the same namespace partition", async () => {
201
- const billingLoader = vi.fn(async (locale: string) =>
202
- locale === "it" ? billingIt : billingEn
203
- );
204
- const engine = new IcuTranslationProviderMulti<MultiSchema, TestMultiParams>({});
205
- const handle = createI18nHandle(engine, {
206
- namespaceLoaders: { billing: billingLoader },
207
- });
208
-
209
- await handle.load({ namespaces: ["billing"], locale: "it" });
210
- await handle.load({ namespaces: ["billing"], locale: "it" });
211
-
212
- expect(billingLoader).toHaveBeenCalledTimes(1);
213
- });
214
-
215
- it("returns a destructuring-safe locale-bound scope from load()", async () => {
216
- const billingLoader = vi.fn(async () => billingEn);
217
- const engine = new IcuTranslationProviderMulti<MultiSchema, TestMultiParams>({});
218
- const { t } = await createI18nHandle(engine, {
219
- namespaceLoaders: { billing: billingLoader },
220
- }).load({ namespaces: ["billing"], locale: "en" });
221
-
222
- expect(t("billing", "invoice_summary", { count: 1, name: "Ada" })).toBe(
223
- "You have 1 invoice for Ada"
224
- );
225
- });
226
-
227
- it("still loads a different partition for the same namespace", async () => {
228
- const billingLoader = vi.fn(async (locale: string) =>
229
- locale === "it" ? billingIt : billingEn
230
- );
231
- const engine = new IcuTranslationProviderMulti<MultiSchema, TestMultiParams>({});
232
- const handle = createI18nHandle(engine, {
233
- namespaceLoaders: { billing: billingLoader },
234
- });
235
-
236
- await handle.load({ namespaces: ["billing"], locale: "it" });
237
- await handle.load({ namespaces: ["billing"], locale: "en" });
238
-
239
- expect(billingLoader).toHaveBeenCalledTimes(2);
240
- expect(billingLoader).toHaveBeenNthCalledWith(1, "it", { locale: "it" });
241
- expect(billingLoader).toHaveBeenNthCalledWith(2, "en", { locale: "en" });
242
- });
243
-
244
- it("peek() returns null until resources are loaded, then a sync scope", async () => {
245
- const billingLoader = vi.fn(async () => billingEn);
246
- const engine = new IcuTranslationProviderMulti<MultiSchema, TestMultiParams>({});
247
- const handle = createI18nHandle(engine, {
248
- namespaceLoaders: { billing: billingLoader },
249
- });
250
-
251
- expect(handle.peek({ namespaces: ["billing"], locale: "en" })).toBeNull();
252
-
253
- await handle.load({ namespaces: ["billing"], locale: "en" });
254
- const sync = handle.peek({ namespaces: ["billing"], locale: "en" });
255
- expect(sync).not.toBeNull();
256
- expect(sync!.t("billing", "invoice_summary", { count: 1, name: "Ada" })).toBe(
257
- "You have 1 invoice for Ada"
258
- );
259
- });
260
-
261
- it("getLoadState() tracks pending, loaded, and error resources", async () => {
262
- let resolveBilling!: () => void;
263
- const billingPending = new Promise<typeof billingEn>((resolve) => {
264
- resolveBilling = () => resolve(billingEn);
265
- });
266
- const billingLoader = vi.fn(() => billingPending);
267
- const failingLoader = vi.fn(async () => {
268
- throw new Error("load failed");
269
- });
270
- const engine = new IcuTranslationProviderMulti<MultiSchema, TestMultiParams>({});
271
- const handle = createI18nHandle(engine, {
272
- namespaceLoaders: {
273
- billing: billingLoader,
274
- default: failingLoader,
275
- },
276
- });
277
-
278
- expect(handle.getLoadState()).toEqual({ resources: [] });
279
-
280
- const pending = handle.load({ namespaces: ["billing"], locale: "en" });
281
- expect(handle.getLoadState()).toEqual({
282
- resources: [{ namespace: "billing", partition: "en", status: "pending" }],
283
- });
284
-
285
- resolveBilling();
286
- await pending;
287
-
288
- expect(handle.getLoadState()).toEqual({
289
- resources: [{ namespace: "billing", partition: "en", status: "loaded" }],
290
- });
291
-
292
- await expect(handle.load({ namespaces: ["default"], locale: "it" })).rejects.toThrow(
293
- "load failed"
294
- );
295
-
296
- expect(handle.getLoadState()).toEqual({
297
- resources: [
298
- { namespace: "billing", partition: "en", status: "loaded" },
299
- { namespace: "default", partition: "it", status: "error", error: expect.any(Error) },
300
- ],
301
- });
302
- });
303
- });
package/src/builder.ts DELETED
@@ -1,15 +0,0 @@
1
- export type { NamespaceLoader, PartitionedLoader } from "./builder-loaders.js";
2
- export { invokeNamespaceLoader } from "./builder-loaders.js";
3
- export type {
4
- I18nHandle,
5
- I18nHandleOptions,
6
- LoadNamespacesInput,
7
- PartitionForLocale,
8
- ScopeForLocale,
9
- } from "./i18n-handle.js";
10
- export { createI18nHandle } from "./i18n-handle.js";
11
- export type {
12
- I18nLoadState,
13
- I18nResourceLoadRecord,
14
- I18nResourceLoadStatus,
15
- } from "./load-state.js";
@@ -1,156 +0,0 @@
1
- import { z } from "zod";
2
- import path from "node:path";
3
- import { IDENTIFIER_NAME_PATTERN, IDENTIFIER_NAME_REQUIREMENT } from "./constants.js";
4
- import { getDeliveryArtifactsStructureIssues } from "./delivery-artifacts.js";
5
- import { typeNamesForProject } from "../codegen-config/type-names.js";
6
-
7
- const localeFallbackSchema = z.record(z.string(), z.union([z.string(), z.null()]));
8
- const deliveryArtifactsSchema = z.record(z.string(), z.array(z.string().min(1)));
9
-
10
- export const DELIVERY_MODES = ["split-by-locale", "custom"] as const;
11
- export type DeliveryMode = (typeof DELIVERY_MODES)[number];
12
-
13
- export const LOADER_STRATEGIES = ["import", "fetch"] as const;
14
- export type LoaderStrategy = (typeof LOADER_STRATEGIES)[number];
15
-
16
- const PROJECT_NAME_PATTERN = /^[A-Z][a-zA-Z0-9]*$/;
17
-
18
- const codegenConfigShape = {
19
- /** PascalCase project id — generates `{project}Params`, `{project}Schema`, `{project}Locale`. */
20
- projectName: z
21
- .string()
22
- .min(1)
23
- .regex(PROJECT_NAME_PATTERN, 'projectName must be PascalCase (e.g. "MyApp")'),
24
- namespaces: z.record(z.string(), z.string().min(1)),
25
- /**
26
- * Directory for generated TypeScript modules:
27
- * `i18n-types.generated.ts`, `instance.generated.ts`,
28
- * `namespace-loaders.generated.ts`, `dictionary-schema.generated.ts`.
29
- */
30
- codegenPath: z.string().min(1),
31
- localeFallback: localeFallbackSchema.optional(),
32
- delivery: z.enum(DELIVERY_MODES).optional().default("split-by-locale"),
33
- deliveryArtifacts: deliveryArtifactsSchema.optional(),
34
- /** Directory for delivery JSON (`translations/`). Defaults to {@link codegenPath}. */
35
- artifactsPath: z.string().min(1).optional(),
36
- /**
37
- * How generated `namespaceLoaders` resolve artifacts.
38
- * - `import` (default): dynamic `import()` — JSON is bundled; content updates need a rebuild.
39
- * - `fetch`: runtime `fetchImpl({ locale, namespace, area? })` via required `createI18n({ fetchImpl })`.
40
- * Codegen does not know URLs — mapping id → transport is an application concern.
41
- */
42
- loaderStrategy: z.enum(LOADER_STRATEGIES).optional().default("import"),
43
- };
44
-
45
- export const codegenConfigKeys = Object.keys(
46
- codegenConfigShape
47
- ) as (keyof typeof codegenConfigShape)[];
48
-
49
- export const codegenConfigSchema = z
50
- .object(codegenConfigShape)
51
- .strict()
52
- .superRefine((config, ctx) => {
53
- for (const namespace of Object.keys(config.namespaces)) {
54
- if (!IDENTIFIER_NAME_PATTERN.test(namespace)) {
55
- ctx.addIssue({
56
- code: "custom",
57
- path: ["namespaces", namespace],
58
- message: `Invalid namespace name "${namespace}" (${IDENTIFIER_NAME_REQUIREMENT}).`,
59
- });
60
- }
61
- }
62
-
63
- if (config.delivery === "custom") {
64
- if (!config.deliveryArtifacts) {
65
- ctx.addIssue({
66
- code: "custom",
67
- path: ["deliveryArtifacts"],
68
- message: 'deliveryArtifacts is required when delivery is "custom".',
69
- });
70
- } else {
71
- for (const issue of getDeliveryArtifactsStructureIssues(config.deliveryArtifacts)) {
72
- ctx.addIssue({
73
- code: "custom",
74
- path: issue.path,
75
- message: issue.message,
76
- });
77
- }
78
- }
79
- } else if (config.deliveryArtifacts !== undefined) {
80
- ctx.addIssue({
81
- code: "custom",
82
- path: ["deliveryArtifacts"],
83
- message: 'deliveryArtifacts is only allowed when delivery is "custom".',
84
- });
85
- }
86
- });
87
-
88
- export type CodegenConfigInput = z.input<typeof codegenConfigSchema>;
89
- export type CodegenConfig = z.infer<typeof codegenConfigSchema>;
90
-
91
- export const GENERATED_BASENAMES = {
92
- types: "i18n-types.generated.ts",
93
- instance: "instance.generated.ts",
94
- namespaceLoaders: "namespace-loaders.generated.ts",
95
- dictionarySchema: "dictionary-schema.generated.ts",
96
- } as const;
97
-
98
- export const DEFAULT_FACTORY_NAME = "createI18n";
99
- export const DEFAULT_LOCALE_FALLBACK_CONST_NAME = "LOCALE_FALLBACK";
100
-
101
- /** Derived paths and symbol names from `projectName` + `codegenPath`. */
102
- export interface ResolvedCodegenPaths {
103
- codegenPath: string;
104
- typesOutput: string;
105
- instanceOutput: string;
106
- namespaceLoadersOutput: string;
107
- dictionarySchemaOutput: string;
108
- artifactsPath: string;
109
- paramsTypeName: string;
110
- schemaTypeName: string;
111
- localeTypeName: string;
112
- localeFallbackConstName: string;
113
- factoryName: string;
114
- deliveryAreaTypeName: string;
115
- }
116
-
117
- export function resolveCodegenPaths(
118
- config: Pick<CodegenConfig, "projectName" | "codegenPath" | "artifactsPath">
119
- ): ResolvedCodegenPaths {
120
- const typeNames = typeNamesForProject(config.projectName);
121
- const codegenPath = config.codegenPath;
122
- return {
123
- codegenPath,
124
- typesOutput: path.join(codegenPath, GENERATED_BASENAMES.types),
125
- instanceOutput: path.join(codegenPath, GENERATED_BASENAMES.instance),
126
- namespaceLoadersOutput: path.join(codegenPath, GENERATED_BASENAMES.namespaceLoaders),
127
- dictionarySchemaOutput: path.join(codegenPath, GENERATED_BASENAMES.dictionarySchema),
128
- artifactsPath: config.artifactsPath ?? codegenPath,
129
- paramsTypeName: typeNames.paramsTypeName,
130
- schemaTypeName: typeNames.schemaTypeName,
131
- localeTypeName: typeNames.localeTypeName,
132
- localeFallbackConstName: DEFAULT_LOCALE_FALLBACK_CONST_NAME,
133
- factoryName: DEFAULT_FACTORY_NAME,
134
- deliveryAreaTypeName: `${config.projectName}DeliveryArea`,
135
- };
136
- }
137
-
138
- export function resolveArtifactsPath(
139
- config: Pick<CodegenConfig, "codegenPath" | "artifactsPath">
140
- ): string {
141
- return config.artifactsPath ?? config.codegenPath;
142
- }
143
-
144
- export function formatCodegenConfigIssues(error: z.ZodError): string {
145
- const issueLines = error.issues.map((issue) => {
146
- const path = issue.path.length > 0 ? issue.path.join(".") : "(root)";
147
- return ` - ${path}: ${issue.message}`;
148
- });
149
-
150
- return [
151
- "[Codegen Error] Invalid i18n.codegen.json:",
152
- ...issueLines,
153
- "",
154
- `Allowed keys: ${codegenConfigKeys.join(", ")}`,
155
- ].join("\n");
156
- }