dialekt 0.1.0 → 0.1.1

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 (71) hide show
  1. package/README.md +8 -10
  2. package/TESTING.md +29 -29
  3. package/dist/cli/main.d.mts +1 -1
  4. package/dist/cli/main.mjs +549 -362
  5. package/dist/formatters-De4Q-X1d.mjs +516 -435
  6. package/dist/index.d.mts +162 -25
  7. package/dist/index.mjs +119 -34
  8. package/package.json +3 -3
  9. package/pnpm-workspace.yaml +3 -3
  10. package/src/adapter/types.test.ts +57 -57
  11. package/src/adapter/types.ts +7 -4
  12. package/src/benchmark/metrics.test.ts +141 -69
  13. package/src/benchmark/metrics.ts +6 -6
  14. package/src/benchmark/report.test.ts +38 -38
  15. package/src/benchmark/report.ts +6 -6
  16. package/src/benchmark/runner.test.ts +70 -72
  17. package/src/benchmark/runner.ts +4 -4
  18. package/src/cli/commands/add.test.ts +90 -109
  19. package/src/cli/commands/add.ts +40 -28
  20. package/src/cli/commands/benchmark.test.ts +77 -64
  21. package/src/cli/commands/benchmark.ts +64 -41
  22. package/src/cli/commands/languages.test.ts +45 -42
  23. package/src/cli/commands/languages.ts +16 -12
  24. package/src/cli/commands/missing.test.ts +143 -92
  25. package/src/cli/commands/missing.ts +24 -17
  26. package/src/cli/commands/translate.test.ts +79 -79
  27. package/src/cli/commands/translate.ts +41 -31
  28. package/src/cli/commands/unused.test.ts +62 -51
  29. package/src/cli/commands/unused.ts +18 -14
  30. package/src/cli/commands/validate.test.ts +130 -72
  31. package/src/cli/commands/validate.ts +25 -20
  32. package/src/cli/config-resolution.test.ts +169 -49
  33. package/src/cli/config-resolution.ts +5 -7
  34. package/src/cli/format.test.ts +50 -50
  35. package/src/cli/format.ts +57 -60
  36. package/src/cli/formatters.test.ts +128 -106
  37. package/src/cli/formatters.ts +72 -95
  38. package/src/cli/main.ts +13 -13
  39. package/src/config/define-config.test.ts +44 -29
  40. package/src/config/define-config.ts +1 -1
  41. package/src/config/load-config.test.ts +21 -18
  42. package/src/config/load-config.ts +5 -5
  43. package/src/config/types.test.ts +50 -44
  44. package/src/config/types.ts +2 -2
  45. package/src/index.ts +22 -26
  46. package/src/keys/flatten.test.ts +52 -52
  47. package/src/keys/flatten.ts +7 -9
  48. package/src/sdk/file-io.test.ts +47 -59
  49. package/src/sdk/file-io.ts +2 -2
  50. package/src/sdk/node-layer.test.ts +18 -18
  51. package/src/sdk/node-layer.ts +2 -2
  52. package/src/sdk/php-array-reader.test.ts +49 -40
  53. package/src/sdk/php-array-reader.ts +5 -5
  54. package/src/translation/chunking.test.ts +52 -44
  55. package/src/translation/chunking.ts +1 -1
  56. package/src/translation/missing-keys.test.ts +86 -93
  57. package/src/translation/missing-keys.ts +4 -6
  58. package/src/translation/model-registry.test.ts +41 -32
  59. package/src/translation/model-registry.ts +9 -9
  60. package/src/translation/one-shot-strategy.test.ts +105 -86
  61. package/src/translation/one-shot-strategy.ts +10 -12
  62. package/src/translation/orchestrator.test.ts +90 -101
  63. package/src/translation/orchestrator.ts +26 -26
  64. package/src/translation/prompt.test.ts +76 -76
  65. package/src/translation/prompt.ts +2 -2
  66. package/src/translation/tool-loop-strategy.test.ts +134 -107
  67. package/src/translation/tool-loop-strategy.ts +14 -18
  68. package/src/translation/types.test.ts +22 -22
  69. package/src/translation/types.ts +3 -3
  70. package/tsdown.config.ts +3 -3
  71. package/vitest.config.ts +3 -3
@@ -1,16 +1,16 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { Effect, Option } from 'effect';
3
- import { runUnused, unusedCommand } from './unused.js';
4
- import type { DialektConfig } from '../../config/types.js';
5
- import type { TranslationAdapter, ResourceRef } from '../../adapter/types.js';
1
+ import { describe, expect, it } from "vitest";
2
+ import { Effect, Option } from "effect";
3
+ import { runUnused, unusedCommand } from "./unused.js";
4
+ import type { DialektConfig } from "../../config/types.js";
5
+ import type { TranslationAdapter, ResourceRef } from "../../adapter/types.js";
6
6
 
7
- describe('runUnused', () => {
7
+ describe("runUnused", () => {
8
8
  const baseConfig: DialektConfig = {
9
- sourceLocale: 'en',
10
- targetLocales: ['de', 'fr'],
11
- strategy: 'one-shot',
12
- model: { provider: 'openai', modelId: 'gpt-4o' },
13
- fastModel: { provider: 'openai', modelId: 'gpt-4o-mini' },
9
+ sourceLocale: "en",
10
+ targetLocales: ["de", "fr"],
11
+ strategy: "one-shot",
12
+ model: { provider: "openai", modelId: "gpt-4o" },
13
+ fastModel: { provider: "openai", modelId: "gpt-4o-mini" },
14
14
  chunking: { maxTokens: 3000, charsPerToken: 3.0, concurrency: 3 },
15
15
  retry: { maxAttempts: 3, baseDelayMs: 1000 },
16
16
  adapters: [],
@@ -29,8 +29,9 @@ describe('runUnused', () => {
29
29
  canCreateResource: true,
30
30
  unusedKeyDetection: opts.hasUnusedDetection ?? true,
31
31
  },
32
- listLocales: () => Effect.succeed(opts.locales ?? ['en', 'de']),
33
- listResources: () => Effect.succeed(opts.resources ?? [{ key: 'messages', label: 'messages' }]),
32
+ listLocales: () => Effect.succeed(opts.locales ?? ["en", "de"]),
33
+ listResources: () =>
34
+ Effect.succeed(opts.resources ?? [{ key: "messages", label: "messages" }]),
34
35
  readResource: () => Effect.succeed({}),
35
36
  writeResource: () => Effect.void,
36
37
  };
@@ -43,13 +44,13 @@ describe('runUnused', () => {
43
44
  return base as TranslationAdapter;
44
45
  }
45
46
 
46
- it('logs unused keys for capable adapters', async () => {
47
+ it("logs unused keys for capable adapters", async () => {
47
48
  const logs: string[] = [];
48
- const adapter = makeAdapter({ name: 'test', unused: ['old_key', 'another'] });
49
- const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig['adapters'] };
49
+ const adapter = makeAdapter({ name: "test", unused: ["old_key", "another"] });
50
+ const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig["adapters"] };
50
51
 
51
52
  const program = runUnused(
52
- { config: './config.ts', adapter: Option.none(), baseLanguage: Option.none() },
53
+ { config: "./config.ts", adapter: Option.none(), baseLanguage: Option.none() },
53
54
  () => Effect.succeed(config),
54
55
  (msg) => Effect.sync(() => logs.push(msg)),
55
56
  () => Effect.void,
@@ -59,19 +60,19 @@ describe('runUnused', () => {
59
60
  expect(logs).toHaveLength(1);
60
61
  const parsed = JSON.parse(logs[0]!);
61
62
  expect(parsed).toEqual([
62
- { adapter: 'test', locale: 'en', resource: 'messages', key: 'old_key' },
63
- { adapter: 'test', locale: 'en', resource: 'messages', key: 'another' },
63
+ { adapter: "test", locale: "en", resource: "messages", key: "old_key" },
64
+ { adapter: "test", locale: "en", resource: "messages", key: "another" },
64
65
  ]);
65
66
  });
66
67
 
67
- it('skips adapters without unusedKeyDetection with a warning', async () => {
68
+ it("skips adapters without unusedKeyDetection with a warning", async () => {
68
69
  const logs: string[] = [];
69
70
  const errors: string[] = [];
70
- const legacy = makeAdapter({ name: 'legacy', hasUnusedDetection: false });
71
- const config = { ...baseConfig, adapters: [legacy] as unknown as DialektConfig['adapters'] };
71
+ const legacy = makeAdapter({ name: "legacy", hasUnusedDetection: false });
72
+ const config = { ...baseConfig, adapters: [legacy] as unknown as DialektConfig["adapters"] };
72
73
 
73
74
  const program = runUnused(
74
- { config: './config.ts', adapter: Option.none(), baseLanguage: Option.none() },
75
+ { config: "./config.ts", adapter: Option.none(), baseLanguage: Option.none() },
75
76
  () => Effect.succeed(config),
76
77
  (msg) => Effect.sync(() => logs.push(msg)),
77
78
  (msg) => Effect.sync(() => errors.push(msg)),
@@ -86,20 +87,20 @@ describe('runUnused', () => {
86
87
  expect(JSON.parse(logs[0]!)).toEqual([]);
87
88
  });
88
89
 
89
- it('handles multiple resources', async () => {
90
+ it("handles multiple resources", async () => {
90
91
  const logs: string[] = [];
91
92
  const adapter = makeAdapter({
92
- name: 'multi',
93
+ name: "multi",
93
94
  resources: [
94
- { key: 'auth', label: 'auth' },
95
- { key: 'validation', label: 'validation' },
95
+ { key: "auth", label: "auth" },
96
+ { key: "validation", label: "validation" },
96
97
  ],
97
- unused: ['unused_auth'],
98
+ unused: ["unused_auth"],
98
99
  });
99
- const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig['adapters'] };
100
+ const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig["adapters"] };
100
101
 
101
102
  const program = runUnused(
102
- { config: './config.ts', adapter: Option.none(), baseLanguage: Option.none() },
103
+ { config: "./config.ts", adapter: Option.none(), baseLanguage: Option.none() },
103
104
  () => Effect.succeed(config),
104
105
  (msg) => Effect.sync(() => logs.push(msg)),
105
106
  () => Effect.void,
@@ -108,15 +109,20 @@ describe('runUnused', () => {
108
109
  await Effect.runPromise(program);
109
110
  expect(logs).toHaveLength(1);
110
111
  const parsed = JSON.parse(logs[0]!);
111
- expect(parsed).toContainEqual({ adapter: 'multi', locale: 'en', resource: 'auth', key: 'unused_auth' });
112
+ expect(parsed).toContainEqual({
113
+ adapter: "multi",
114
+ locale: "en",
115
+ resource: "auth",
116
+ key: "unused_auth",
117
+ });
112
118
  });
113
119
 
114
- it('handles empty adapter list', async () => {
120
+ it("handles empty adapter list", async () => {
115
121
  const logs: string[] = [];
116
122
  const config = { ...baseConfig, adapters: [] };
117
123
 
118
124
  const program = runUnused(
119
- { config: './config.ts', adapter: Option.none(), baseLanguage: Option.none() },
125
+ { config: "./config.ts", adapter: Option.none(), baseLanguage: Option.none() },
120
126
  () => Effect.succeed(config),
121
127
  (msg) => Effect.sync(() => logs.push(msg)),
122
128
  () => Effect.void,
@@ -127,13 +133,13 @@ describe('runUnused', () => {
127
133
  expect(JSON.parse(logs[0]!)).toEqual([]);
128
134
  });
129
135
 
130
- it('handles adapter with no resources', async () => {
136
+ it("handles adapter with no resources", async () => {
131
137
  const logs: string[] = [];
132
- const adapter = makeAdapter({ name: 'empty', resources: [] });
133
- const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig['adapters'] };
138
+ const adapter = makeAdapter({ name: "empty", resources: [] });
139
+ const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig["adapters"] };
134
140
 
135
141
  const program = runUnused(
136
- { config: './config.ts', adapter: Option.none(), baseLanguage: Option.none() },
142
+ { config: "./config.ts", adapter: Option.none(), baseLanguage: Option.none() },
137
143
  () => Effect.succeed(config),
138
144
  (msg) => Effect.sync(() => logs.push(msg)),
139
145
  () => Effect.void,
@@ -144,13 +150,13 @@ describe('runUnused', () => {
144
150
  expect(JSON.parse(logs[0]!)).toEqual([]);
145
151
  });
146
152
 
147
- it('handles no unused keys gracefully', async () => {
153
+ it("handles no unused keys gracefully", async () => {
148
154
  const logs: string[] = [];
149
- const adapter = makeAdapter({ name: 'clean', unused: [] });
150
- const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig['adapters'] };
155
+ const adapter = makeAdapter({ name: "clean", unused: [] });
156
+ const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig["adapters"] };
151
157
 
152
158
  const program = runUnused(
153
- { config: './config.ts', adapter: Option.none(), baseLanguage: Option.none() },
159
+ { config: "./config.ts", adapter: Option.none(), baseLanguage: Option.none() },
154
160
  () => Effect.succeed(config),
155
161
  (msg) => Effect.sync(() => logs.push(msg)),
156
162
  () => Effect.void,
@@ -161,24 +167,29 @@ describe('runUnused', () => {
161
167
  expect(JSON.parse(logs[0]!)).toEqual([]);
162
168
  });
163
169
 
164
- it('fails when configLoader fails', async () => {
170
+ it("fails when configLoader fails", async () => {
165
171
  const program = runUnused(
166
- { config: './missing.ts', adapter: Option.none(), baseLanguage: Option.none() },
167
- () => Effect.fail(new Error('Config not found')),
172
+ { config: "./missing.ts", adapter: Option.none(), baseLanguage: Option.none() },
173
+ () => Effect.fail(new Error("Config not found")),
168
174
  () => Effect.void,
169
175
  () => Effect.void,
170
176
  );
171
177
 
172
- await expect(Effect.runPromise(program)).rejects.toThrow('Config not found');
178
+ await expect(Effect.runPromise(program)).rejects.toThrow("Config not found");
173
179
  });
174
180
 
175
- it('outputs pretty when --format pretty is passed', async () => {
181
+ it("outputs pretty when --format pretty is passed", async () => {
176
182
  const logs: string[] = [];
177
- const adapter = makeAdapter({ name: 'test', unused: ['old_key'] });
178
- const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig['adapters'] };
183
+ const adapter = makeAdapter({ name: "test", unused: ["old_key"] });
184
+ const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig["adapters"] };
179
185
 
180
186
  const program = runUnused(
181
- { config: './config.ts', adapter: Option.none(), baseLanguage: Option.none(), format: Option.some('pretty') },
187
+ {
188
+ config: "./config.ts",
189
+ adapter: Option.none(),
190
+ baseLanguage: Option.none(),
191
+ format: Option.some("pretty"),
192
+ },
182
193
  () => Effect.succeed(config),
183
194
  (msg) => Effect.sync(() => logs.push(msg)),
184
195
  () => Effect.void,
@@ -186,7 +197,7 @@ describe('runUnused', () => {
186
197
 
187
198
  await Effect.runPromise(program);
188
199
  expect(logs).toHaveLength(1);
189
- expect(logs[0]).toContain('test');
190
- expect(logs[0]).toContain('old_key');
200
+ expect(logs[0]).toContain("test");
201
+ expect(logs[0]).toContain("old_key");
191
202
  });
192
203
  });
@@ -1,11 +1,11 @@
1
- import { Command, Options } from '@effect/cli';
2
- import { Effect, Console, Option } from 'effect';
3
- import { loadConfig } from '../../config/load-config.js';
4
- import { resolveEffectiveConfig } from '../config-resolution.js';
5
- import { detectFormat, type OutputFormat } from '../format.js';
6
- import { formatUnusedKeys, formatError } from '../formatters.js';
7
- import type { DialektConfig } from '../../config/types.js';
8
- import type { TranslationAdapter, ResourceRef } from '../../adapter/types.js';
1
+ import { Command, Options } from "@effect/cli";
2
+ import { Effect, Console, Option } from "effect";
3
+ import { loadConfig } from "../../config/load-config.js";
4
+ import { resolveEffectiveConfig } from "../config-resolution.js";
5
+ import { detectFormat, type OutputFormat } from "../format.js";
6
+ import { formatUnusedKeys, formatError } from "../formatters.js";
7
+ import type { DialektConfig } from "../../config/types.js";
8
+ import type { TranslationAdapter, ResourceRef } from "../../adapter/types.js";
9
9
 
10
10
  export interface UnusedFlags {
11
11
  readonly config: string;
@@ -79,9 +79,13 @@ export function runUnused(
79
79
  }).pipe(Effect.mapError((e) => e as never)) as Effect.Effect<void, never, never>;
80
80
  }
81
81
 
82
- export const unusedCommand = Command.make('unused', {
83
- config: Options.text('config').pipe(Options.withDefault('./dialekt.config.ts')),
84
- adapter: Options.optional(Options.text('adapter')),
85
- baseLanguage: Options.optional(Options.text('base-language')),
86
- format: Options.optional(Options.text('format')),
87
- }, (flags) => runUnused(flags));
82
+ export const unusedCommand = Command.make(
83
+ "unused",
84
+ {
85
+ config: Options.text("config").pipe(Options.withDefault("./dialekt.config.ts")),
86
+ adapter: Options.optional(Options.text("adapter")),
87
+ baseLanguage: Options.optional(Options.text("base-language")),
88
+ format: Options.optional(Options.text("format")),
89
+ },
90
+ (flags) => runUnused(flags),
91
+ );
@@ -1,16 +1,16 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { Effect, Option } from 'effect';
3
- import { runValidate, validateCommand } from './validate.js';
4
- import type { DialektConfig } from '../../config/types.js';
5
- import type { TranslationAdapter, ResourceRef } from '../../adapter/types.js';
1
+ import { describe, expect, it } from "vitest";
2
+ import { Effect, Option } from "effect";
3
+ import { runValidate, validateCommand } from "./validate.js";
4
+ import type { DialektConfig } from "../../config/types.js";
5
+ import type { TranslationAdapter, ResourceRef } from "../../adapter/types.js";
6
6
 
7
- describe('runValidate', () => {
7
+ describe("runValidate", () => {
8
8
  const baseConfig: DialektConfig = {
9
- sourceLocale: 'en',
10
- targetLocales: ['de', 'fr'],
11
- strategy: 'one-shot',
12
- model: { provider: 'openai', modelId: 'gpt-4o' },
13
- fastModel: { provider: 'openai', modelId: 'gpt-4o-mini' },
9
+ sourceLocale: "en",
10
+ targetLocales: ["de", "fr"],
11
+ strategy: "one-shot",
12
+ model: { provider: "openai", modelId: "gpt-4o" },
13
+ fastModel: { provider: "openai", modelId: "gpt-4o-mini" },
14
14
  chunking: { maxTokens: 3000, charsPerToken: 3.0, concurrency: 3 },
15
15
  retry: { maxAttempts: 3, baseDelayMs: 1000 },
16
16
  adapters: [],
@@ -24,20 +24,25 @@ describe('runValidate', () => {
24
24
  return {
25
25
  name: opts.name,
26
26
  capabilities: { canCreateResource: true, unusedKeyDetection: false },
27
- listLocales: () => Effect.succeed(opts.locales ?? ['en', 'de']),
28
- listResources: () => Effect.succeed([{ key: 'messages', label: 'messages' }]),
27
+ listLocales: () => Effect.succeed(opts.locales ?? ["en", "de"]),
28
+ listResources: () => Effect.succeed([{ key: "messages", label: "messages" }]),
29
29
  readResource: () => Effect.succeed({}),
30
30
  writeResource: () => Effect.void,
31
31
  };
32
32
  }
33
33
 
34
- it('passes when no keys are missing', async () => {
34
+ it("passes when no keys are missing", async () => {
35
35
  const logs: string[] = [];
36
- const adapter = makeAdapter({ name: 'test' });
37
- const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig['adapters'] };
36
+ const adapter = makeAdapter({ name: "test" });
37
+ const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig["adapters"] };
38
38
 
39
39
  const program = runValidate(
40
- { config: './config.ts', adapter: Option.none(), baseLanguage: Option.none(), language: Option.none() },
40
+ {
41
+ config: "./config.ts",
42
+ adapter: Option.none(),
43
+ baseLanguage: Option.none(),
44
+ language: Option.none(),
45
+ },
41
46
  () => Effect.succeed(config),
42
47
  () => Effect.succeed([]),
43
48
  (msg) => Effect.sync(() => logs.push(msg)),
@@ -50,20 +55,22 @@ describe('runValidate', () => {
50
55
  expect(parsed.entries).toEqual([]);
51
56
  });
52
57
 
53
- it('fails and reports missing keys', async () => {
58
+ it("fails and reports missing keys", async () => {
54
59
  const logs: string[] = [];
55
- const adapter = makeAdapter({ name: 'test' });
56
- const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig['adapters'] };
57
- const resource: ResourceRef = { key: 'messages', label: 'messages' };
60
+ const adapter = makeAdapter({ name: "test" });
61
+ const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig["adapters"] };
62
+ const resource: ResourceRef = { key: "messages", label: "messages" };
58
63
 
59
64
  const originalExitCode = process.exitCode;
60
65
  const program = runValidate(
61
- { config: './config.ts', adapter: Option.none(), baseLanguage: Option.none(), language: Option.none() },
66
+ {
67
+ config: "./config.ts",
68
+ adapter: Option.none(),
69
+ baseLanguage: Option.none(),
70
+ language: Option.none(),
71
+ },
62
72
  () => Effect.succeed(config),
63
- () =>
64
- Effect.succeed([
65
- { adapter: 'test', locale: 'de', resource, missing: ['hello'] },
66
- ]),
73
+ () => Effect.succeed([{ adapter: "test", locale: "de", resource, missing: ["hello"] }]),
67
74
  (msg) => Effect.sync(() => logs.push(msg)),
68
75
  );
69
76
 
@@ -74,23 +81,33 @@ describe('runValidate', () => {
74
81
  const parsed = JSON.parse(logs[0]!);
75
82
  expect(parsed.passing).toBe(false);
76
83
  expect(parsed.entries).toHaveLength(1);
77
- expect(parsed.entries[0]).toMatchObject({ adapter: 'test', locale: 'de', resource: 'messages', count: 1 });
84
+ expect(parsed.entries[0]).toMatchObject({
85
+ adapter: "test",
86
+ locale: "de",
87
+ resource: "messages",
88
+ count: 1,
89
+ });
78
90
  });
79
91
 
80
- it('reports missing keys for multiple adapters', async () => {
92
+ it("reports missing keys for multiple adapters", async () => {
81
93
  const logs: string[] = [];
82
- const a1 = makeAdapter({ name: 'a1' });
83
- const a2 = makeAdapter({ name: 'a2', locales: ['en', 'fr'] });
84
- const config = { ...baseConfig, adapters: [a1, a2] as unknown as DialektConfig['adapters'] };
85
- const resource: ResourceRef = { key: 'messages', label: 'messages' };
94
+ const a1 = makeAdapter({ name: "a1" });
95
+ const a2 = makeAdapter({ name: "a2", locales: ["en", "fr"] });
96
+ const config = { ...baseConfig, adapters: [a1, a2] as unknown as DialektConfig["adapters"] };
97
+ const resource: ResourceRef = { key: "messages", label: "messages" };
86
98
 
87
99
  const originalExitCode = process.exitCode;
88
100
  const program = runValidate(
89
- { config: './config.ts', adapter: Option.none(), baseLanguage: Option.none(), language: Option.none() },
101
+ {
102
+ config: "./config.ts",
103
+ adapter: Option.none(),
104
+ baseLanguage: Option.none(),
105
+ language: Option.none(),
106
+ },
90
107
  () => Effect.succeed(config),
91
108
  (a) =>
92
109
  Effect.succeed([
93
- { adapter: a.name, locale: a.name === 'a1' ? 'de' : 'fr', resource, missing: ['k1'] },
110
+ { adapter: a.name, locale: a.name === "a1" ? "de" : "fr", resource, missing: ["k1"] },
94
111
  ]),
95
112
  (msg) => Effect.sync(() => logs.push(msg)),
96
113
  );
@@ -104,14 +121,19 @@ describe('runValidate', () => {
104
121
  expect(parsed.entries).toHaveLength(2);
105
122
  });
106
123
 
107
- it('filters by --adapter flag', async () => {
124
+ it("filters by --adapter flag", async () => {
108
125
  let queriedAdapter: string | undefined;
109
- const a1 = makeAdapter({ name: 'a1' });
110
- const a2 = makeAdapter({ name: 'a2' });
111
- const config = { ...baseConfig, adapters: [a1, a2] as unknown as DialektConfig['adapters'] };
126
+ const a1 = makeAdapter({ name: "a1" });
127
+ const a2 = makeAdapter({ name: "a2" });
128
+ const config = { ...baseConfig, adapters: [a1, a2] as unknown as DialektConfig["adapters"] };
112
129
 
113
130
  const program = runValidate(
114
- { config: './config.ts', adapter: Option.some('a2'), baseLanguage: Option.none(), language: Option.none() },
131
+ {
132
+ config: "./config.ts",
133
+ adapter: Option.some("a2"),
134
+ baseLanguage: Option.none(),
135
+ language: Option.none(),
136
+ },
115
137
  () => Effect.succeed(config),
116
138
  (a) =>
117
139
  Effect.sync(() => {
@@ -122,62 +144,82 @@ describe('runValidate', () => {
122
144
  );
123
145
 
124
146
  await Effect.runPromise(program);
125
- expect(queriedAdapter).toBe('a2');
147
+ expect(queriedAdapter).toBe("a2");
126
148
  });
127
149
 
128
- it('fails when configLoader fails', async () => {
150
+ it("fails when configLoader fails", async () => {
129
151
  const program = runValidate(
130
- { config: './missing.ts', adapter: Option.none(), baseLanguage: Option.none(), language: Option.none() },
131
- () => Effect.fail(new Error('Config not found')),
152
+ {
153
+ config: "./missing.ts",
154
+ adapter: Option.none(),
155
+ baseLanguage: Option.none(),
156
+ language: Option.none(),
157
+ },
158
+ () => Effect.fail(new Error("Config not found")),
132
159
  () => Effect.succeed([]),
133
160
  () => Effect.void,
134
161
  );
135
162
 
136
- await expect(Effect.runPromise(program)).rejects.toThrow('Config not found');
163
+ await expect(Effect.runPromise(program)).rejects.toThrow("Config not found");
137
164
  });
138
165
 
139
- it('fails when listLocales fails', async () => {
166
+ it("fails when listLocales fails", async () => {
140
167
  const adapter: TranslationAdapter = {
141
- name: 'broken',
168
+ name: "broken",
142
169
  capabilities: { canCreateResource: true, unusedKeyDetection: false },
143
- listLocales: () => Effect.fail(new Error('disk error') as never),
170
+ listLocales: () => Effect.fail(new Error("disk error") as never),
144
171
  listResources: () => Effect.succeed([]),
145
172
  readResource: () => Effect.succeed({}),
146
173
  writeResource: () => Effect.void,
147
174
  };
148
- const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig['adapters'] };
175
+ const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig["adapters"] };
149
176
 
150
177
  const program = runValidate(
151
- { config: './config.ts', adapter: Option.none(), baseLanguage: Option.none(), language: Option.none() },
178
+ {
179
+ config: "./config.ts",
180
+ adapter: Option.none(),
181
+ baseLanguage: Option.none(),
182
+ language: Option.none(),
183
+ },
152
184
  () => Effect.succeed(config),
153
185
  () => Effect.succeed([]),
154
186
  () => Effect.void,
155
187
  );
156
188
 
157
- await expect(Effect.runPromise(program)).rejects.toThrow('disk error');
189
+ await expect(Effect.runPromise(program)).rejects.toThrow("disk error");
158
190
  });
159
191
 
160
- it('fails when missingKeysComputer fails', async () => {
161
- const adapter = makeAdapter({ name: 'test' });
162
- const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig['adapters'] };
192
+ it("fails when missingKeysComputer fails", async () => {
193
+ const adapter = makeAdapter({ name: "test" });
194
+ const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig["adapters"] };
163
195
 
164
196
  const program = runValidate(
165
- { config: './config.ts', adapter: Option.none(), baseLanguage: Option.none(), language: Option.none() },
197
+ {
198
+ config: "./config.ts",
199
+ adapter: Option.none(),
200
+ baseLanguage: Option.none(),
201
+ language: Option.none(),
202
+ },
166
203
  () => Effect.succeed(config),
167
- () => Effect.fail(new Error('read error')),
204
+ () => Effect.fail(new Error("read error")),
168
205
  () => Effect.void,
169
206
  );
170
207
 
171
- await expect(Effect.runPromise(program)).rejects.toThrow('read error');
208
+ await expect(Effect.runPromise(program)).rejects.toThrow("read error");
172
209
  });
173
210
 
174
- it('filters by --language flag', async () => {
211
+ it("filters by --language flag", async () => {
175
212
  let checkedLocale: string | undefined;
176
- const adapter = makeAdapter({ name: 'test' });
177
- const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig['adapters'] };
213
+ const adapter = makeAdapter({ name: "test" });
214
+ const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig["adapters"] };
178
215
 
179
216
  const program = runValidate(
180
- { config: './config.ts', adapter: Option.none(), baseLanguage: Option.none(), language: Option.some('de') },
217
+ {
218
+ config: "./config.ts",
219
+ adapter: Option.none(),
220
+ baseLanguage: Option.none(),
221
+ language: Option.some("de"),
222
+ },
181
223
  () => Effect.succeed(config),
182
224
  (_a, _s, targets) =>
183
225
  Effect.sync(() => {
@@ -188,16 +230,22 @@ describe('runValidate', () => {
188
230
  );
189
231
 
190
232
  await Effect.runPromise(program);
191
- expect(checkedLocale).toBe('de');
233
+ expect(checkedLocale).toBe("de");
192
234
  });
193
235
 
194
- it('outputs pretty when --format pretty is passed', async () => {
236
+ it("outputs pretty when --format pretty is passed", async () => {
195
237
  const logs: string[] = [];
196
- const adapter = makeAdapter({ name: 'test' });
197
- const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig['adapters'] };
238
+ const adapter = makeAdapter({ name: "test" });
239
+ const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig["adapters"] };
198
240
 
199
241
  const program = runValidate(
200
- { config: './config.ts', adapter: Option.none(), baseLanguage: Option.none(), language: Option.none(), format: Option.some('pretty') },
242
+ {
243
+ config: "./config.ts",
244
+ adapter: Option.none(),
245
+ baseLanguage: Option.none(),
246
+ language: Option.none(),
247
+ format: Option.some("pretty"),
248
+ },
201
249
  () => Effect.succeed(config),
202
250
  () => Effect.succeed([]),
203
251
  (msg) => Effect.sync(() => logs.push(msg)),
@@ -205,15 +253,20 @@ describe('runValidate', () => {
205
253
 
206
254
  await Effect.runPromise(program);
207
255
  expect(logs).toHaveLength(1);
208
- expect(logs[0]).toContain('up to date');
256
+ expect(logs[0]).toContain("up to date");
209
257
  });
210
258
 
211
- it('handles empty adapter list', async () => {
259
+ it("handles empty adapter list", async () => {
212
260
  const logs: string[] = [];
213
261
  const config = { ...baseConfig, adapters: [] };
214
262
 
215
263
  const program = runValidate(
216
- { config: './config.ts', adapter: Option.none(), baseLanguage: Option.none(), language: Option.none() },
264
+ {
265
+ config: "./config.ts",
266
+ adapter: Option.none(),
267
+ baseLanguage: Option.none(),
268
+ language: Option.none(),
269
+ },
217
270
  () => Effect.succeed(config),
218
271
  () => Effect.succeed([]),
219
272
  (msg) => Effect.sync(() => logs.push(msg)),
@@ -225,13 +278,18 @@ describe('runValidate', () => {
225
278
  expect(parsed.passing).toBe(true);
226
279
  });
227
280
 
228
- it('handles adapter with only source locale (no targets)', async () => {
281
+ it("handles adapter with only source locale (no targets)", async () => {
229
282
  const logs: string[] = [];
230
- const adapter = makeAdapter({ name: 'mono', locales: ['en'] });
231
- const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig['adapters'] };
283
+ const adapter = makeAdapter({ name: "mono", locales: ["en"] });
284
+ const config = { ...baseConfig, adapters: [adapter] as unknown as DialektConfig["adapters"] };
232
285
 
233
286
  const program = runValidate(
234
- { config: './config.ts', adapter: Option.none(), baseLanguage: Option.none(), language: Option.none() },
287
+ {
288
+ config: "./config.ts",
289
+ adapter: Option.none(),
290
+ baseLanguage: Option.none(),
291
+ language: Option.none(),
292
+ },
235
293
  () => Effect.succeed(config),
236
294
  () => Effect.succeed([]),
237
295
  (msg) => Effect.sync(() => logs.push(msg)),