@dialekt/adapter-laravel 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.
@@ -1,178 +1,180 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { Effect, Either } from 'effect';
3
- import { NodePlatformLayer } from 'dialekt';
4
- import { laravel } from './adapter.js';
5
- import { mkdirSync, writeFileSync, rmSync } from 'node:fs';
6
- import { join } from 'node:path';
7
- import { tmpdir } from 'node:os';
8
- import { execSync } from 'node:child_process';
1
+ import { describe, expect, it } from "vitest";
2
+ import { Effect, Either } from "effect";
3
+ import { NodePlatformLayer } from "dialekt";
4
+ import { laravel } from "./adapter.js";
5
+ import { mkdirSync, writeFileSync, rmSync } from "node:fs";
6
+ import { join } from "node:path";
7
+ import { tmpdir } from "node:os";
8
+ import { execSync } from "node:child_process";
9
9
 
10
10
  function hasPhpBinary(): boolean {
11
11
  try {
12
- execSync('php -v', { stdio: 'ignore' });
12
+ execSync("php -v", { stdio: "ignore" });
13
13
  return true;
14
14
  } catch {
15
15
  return false;
16
16
  }
17
17
  }
18
18
 
19
- describe('laravel adapter', () => {
19
+ describe("laravel adapter", () => {
20
20
  const testDir = join(tmpdir(), `laravel-adapter-test-${Date.now()}`);
21
21
 
22
- it.skipIf(!hasPhpBinary())('reads a PHP domain resource', async () => {
23
- mkdirSync(join(testDir, 'en'), { recursive: true });
22
+ it.skipIf(!hasPhpBinary())("reads a PHP domain resource", async () => {
23
+ mkdirSync(join(testDir, "en"), { recursive: true });
24
24
  writeFileSync(
25
- join(testDir, 'en', 'validation.php'),
25
+ join(testDir, "en", "validation.php"),
26
26
  "<?php return ['email' => 'Email address'];",
27
27
  );
28
28
 
29
29
  const adapter = laravel({ langDir: testDir, scanPaths: [testDir] });
30
- const program = adapter.readResource('en', { key: 'validation', label: 'validation' }).pipe(
31
- Effect.provide(NodePlatformLayer),
32
- );
30
+ const program = adapter
31
+ .readResource("en", { key: "validation", label: "validation" })
32
+ .pipe(Effect.provide(NodePlatformLayer));
33
33
  const result = await Effect.runPromise(program);
34
- expect(result).toEqual({ email: 'Email address' });
34
+ expect(result).toEqual({ email: "Email address" });
35
35
 
36
36
  rmSync(testDir, { recursive: true, force: true });
37
37
  });
38
38
 
39
- it.skipIf(!hasPhpBinary())('returns {} for a missing resource', async () => {
40
- mkdirSync(join(testDir, 'en'), { recursive: true });
39
+ it.skipIf(!hasPhpBinary())("returns {} for a missing resource", async () => {
40
+ mkdirSync(join(testDir, "en"), { recursive: true });
41
41
 
42
42
  const adapter = laravel({ langDir: testDir, scanPaths: [testDir] });
43
- const program = adapter.readResource('en', { key: 'missing', label: 'missing' }).pipe(
44
- Effect.provide(NodePlatformLayer),
45
- );
43
+ const program = adapter
44
+ .readResource("en", { key: "missing", label: "missing" })
45
+ .pipe(Effect.provide(NodePlatformLayer));
46
46
  const result = await Effect.runPromise(program);
47
47
  expect(result).toEqual({});
48
48
 
49
49
  rmSync(testDir, { recursive: true, force: true });
50
50
  });
51
51
 
52
- it.skipIf(!hasPhpBinary())('round-trips write and read', async () => {
53
- mkdirSync(join(testDir, 'de'), { recursive: true });
52
+ it.skipIf(!hasPhpBinary())("round-trips write and read", async () => {
53
+ mkdirSync(join(testDir, "de"), { recursive: true });
54
54
 
55
55
  const adapter = laravel({ langDir: testDir, scanPaths: [testDir] });
56
56
  const writeProgram = adapter
57
- .writeResource('de', { key: 'auth', label: 'auth' }, { login: 'Anmelden' })
57
+ .writeResource("de", { key: "auth", label: "auth" }, { login: "Anmelden" })
58
58
  .pipe(Effect.provide(NodePlatformLayer));
59
59
  await Effect.runPromise(writeProgram);
60
60
 
61
- const readProgram = adapter.readResource('de', { key: 'auth', label: 'auth' }).pipe(
62
- Effect.provide(NodePlatformLayer),
63
- );
61
+ const readProgram = adapter
62
+ .readResource("de", { key: "auth", label: "auth" })
63
+ .pipe(Effect.provide(NodePlatformLayer));
64
64
  const result = await Effect.runPromise(readProgram);
65
- expect(result).toEqual({ login: 'Anmelden' });
65
+ expect(result).toEqual({ login: "Anmelden" });
66
66
 
67
67
  rmSync(testDir, { recursive: true, force: true });
68
68
  });
69
69
 
70
- it('reads a JSON locale resource', async () => {
70
+ it("reads a JSON locale resource", async () => {
71
71
  mkdirSync(testDir, { recursive: true });
72
- writeFileSync(join(testDir, 'en.json'), JSON.stringify({ greeting: 'Hello' }));
72
+ writeFileSync(join(testDir, "en.json"), JSON.stringify({ greeting: "Hello" }));
73
73
 
74
74
  const adapter = laravel({ langDir: testDir, scanPaths: [testDir] });
75
- const program = adapter.readResource('en', { key: 'json', label: 'en.json' }).pipe(
76
- Effect.provide(NodePlatformLayer),
77
- );
75
+ const program = adapter
76
+ .readResource("en", { key: "json", label: "en.json" })
77
+ .pipe(Effect.provide(NodePlatformLayer));
78
78
  const result = await Effect.runPromise(program);
79
- expect(result).toEqual({ greeting: 'Hello' });
79
+ expect(result).toEqual({ greeting: "Hello" });
80
80
 
81
81
  rmSync(testDir, { recursive: true, force: true });
82
82
  });
83
83
 
84
- it('lists locales and resources', async () => {
85
- mkdirSync(join(testDir, 'en'), { recursive: true });
86
- mkdirSync(join(testDir, 'de'), { recursive: true });
87
- writeFileSync(join(testDir, 'en', 'validation.php'), '<?php return [];');
84
+ it("lists locales and resources", async () => {
85
+ mkdirSync(join(testDir, "en"), { recursive: true });
86
+ mkdirSync(join(testDir, "de"), { recursive: true });
87
+ writeFileSync(join(testDir, "en", "validation.php"), "<?php return [];");
88
88
 
89
89
  const adapter = laravel({ langDir: testDir, scanPaths: [testDir] });
90
- const locales = await Effect.runPromise(adapter.listLocales().pipe(Effect.provide(NodePlatformLayer)));
91
- expect(locales).toContain('en');
92
- expect(locales).toContain('de');
90
+ const locales = await Effect.runPromise(
91
+ adapter.listLocales().pipe(Effect.provide(NodePlatformLayer)),
92
+ );
93
+ expect(locales).toContain("en");
94
+ expect(locales).toContain("de");
93
95
 
94
96
  const resources = await Effect.runPromise(
95
- adapter.listResources('en').pipe(Effect.provide(NodePlatformLayer)),
97
+ adapter.listResources("en").pipe(Effect.provide(NodePlatformLayer)),
96
98
  );
97
- expect(resources.map((r) => r.key)).toContain('validation');
99
+ expect(resources.map((r) => r.key)).toContain("validation");
98
100
 
99
101
  rmSync(testDir, { recursive: true, force: true });
100
102
  });
101
103
 
102
- it('finds unused keys', async () => {
103
- mkdirSync(join(testDir, 'en'), { recursive: true });
104
- writeFileSync(join(testDir, 'en', 'validation.php'), "<?php return ['email' => 'Email'];");
105
- mkdirSync(join(testDir, 'views'), { recursive: true });
106
- writeFileSync(join(testDir, 'views', 'page.blade.php'), "__('validation.email')");
104
+ it("finds unused keys", async () => {
105
+ mkdirSync(join(testDir, "en"), { recursive: true });
106
+ writeFileSync(join(testDir, "en", "validation.php"), "<?php return ['email' => 'Email'];");
107
+ mkdirSync(join(testDir, "views"), { recursive: true });
108
+ writeFileSync(join(testDir, "views", "page.blade.php"), "__('validation.email')");
107
109
 
108
- const adapter = laravel({ langDir: testDir, scanPaths: [join(testDir, 'views')] });
109
- const program = adapter
110
- .findUnusedKeys!('en', { key: 'validation', label: 'validation' })
111
- .pipe(Effect.provide(NodePlatformLayer));
110
+ const adapter = laravel({ langDir: testDir, scanPaths: [join(testDir, "views")] });
111
+ const program = adapter.findUnusedKeys!("en", { key: "validation", label: "validation" }).pipe(
112
+ Effect.provide(NodePlatformLayer),
113
+ );
112
114
  const result = await Effect.runPromise(program);
113
115
  expect(result).toEqual([]);
114
116
 
115
117
  rmSync(testDir, { recursive: true, force: true });
116
118
  });
117
119
 
118
- it.skipIf(!hasPhpBinary())('reads nested PHP arrays', async () => {
119
- mkdirSync(join(testDir, 'en'), { recursive: true });
120
+ it.skipIf(!hasPhpBinary())("reads nested PHP arrays", async () => {
121
+ mkdirSync(join(testDir, "en"), { recursive: true });
120
122
  writeFileSync(
121
- join(testDir, 'en', 'nested.php'),
123
+ join(testDir, "en", "nested.php"),
122
124
  "<?php return ['validation' => ['email' => 'Email', 'required' => 'Required']];",
123
125
  );
124
126
 
125
127
  const adapter = laravel({ langDir: testDir, scanPaths: [testDir] });
126
- const program = adapter.readResource('en', { key: 'nested', label: 'nested' }).pipe(
127
- Effect.provide(NodePlatformLayer),
128
- );
128
+ const program = adapter
129
+ .readResource("en", { key: "nested", label: "nested" })
130
+ .pipe(Effect.provide(NodePlatformLayer));
129
131
  const result = await Effect.runPromise(program);
130
132
  expect(result).toEqual({
131
- 'validation.email': 'Email',
132
- 'validation.required': 'Required',
133
+ "validation.email": "Email",
134
+ "validation.required": "Required",
133
135
  });
134
136
 
135
137
  rmSync(testDir, { recursive: true, force: true });
136
138
  });
137
139
 
138
- it('returns empty for missing JSON locale file', async () => {
140
+ it("returns empty for missing JSON locale file", async () => {
139
141
  mkdirSync(testDir, { recursive: true });
140
142
 
141
143
  const adapter = laravel({ langDir: testDir, scanPaths: [testDir] });
142
- const program = adapter.readResource('en', { key: 'json', label: 'en.json' }).pipe(
143
- Effect.provide(NodePlatformLayer),
144
- );
144
+ const program = adapter
145
+ .readResource("en", { key: "json", label: "en.json" })
146
+ .pipe(Effect.provide(NodePlatformLayer));
145
147
  const result = await Effect.runPromise(program);
146
148
  expect(result).toEqual({});
147
149
 
148
150
  rmSync(testDir, { recursive: true, force: true });
149
151
  });
150
152
 
151
- it('handles capabilities flags', () => {
153
+ it("handles capabilities flags", () => {
152
154
  const adapter = laravel({ langDir: testDir });
153
155
  expect(adapter.capabilities.canCreateResource).toBe(true);
154
156
  expect(adapter.capabilities.unusedKeyDetection).toBe(true);
155
157
  });
156
158
 
157
- it('reports adapter name', () => {
159
+ it("reports adapter name", () => {
158
160
  const adapter = laravel({ langDir: testDir });
159
- expect(adapter.name).toBe('laravel');
161
+ expect(adapter.name).toBe("laravel");
160
162
  });
161
163
 
162
- it.skipIf(!hasPhpBinary())('writes JSON locale files', async () => {
164
+ it.skipIf(!hasPhpBinary())("writes JSON locale files", async () => {
163
165
  mkdirSync(testDir, { recursive: true });
164
166
 
165
167
  const adapter = laravel({ langDir: testDir, scanPaths: [testDir] });
166
168
  const writeProgram = adapter
167
- .writeResource('en', { key: 'json', label: 'en.json' }, { greeting: 'Hello' })
169
+ .writeResource("en", { key: "json", label: "en.json" }, { greeting: "Hello" })
168
170
  .pipe(Effect.provide(NodePlatformLayer));
169
171
  await Effect.runPromise(writeProgram);
170
172
 
171
- const readProgram = adapter.readResource('en', { key: 'json', label: 'en.json' }).pipe(
172
- Effect.provide(NodePlatformLayer),
173
- );
173
+ const readProgram = adapter
174
+ .readResource("en", { key: "json", label: "en.json" })
175
+ .pipe(Effect.provide(NodePlatformLayer));
174
176
  const result = await Effect.runPromise(readProgram);
175
- expect(result).toEqual({ greeting: 'Hello' });
177
+ expect(result).toEqual({ greeting: "Hello" });
176
178
 
177
179
  rmSync(testDir, { recursive: true, force: true });
178
180
  });
package/src/adapter.ts CHANGED
@@ -1,11 +1,6 @@
1
- import { Effect } from 'effect';
2
- import { Path } from '@effect/platform/Path';
3
- import type {
4
- ResourceRef,
5
- TranslationAdapter,
6
- AdapterReadError,
7
- AdapterWriteError,
8
- } from 'dialekt';
1
+ import { Effect } from "effect";
2
+ import { Path } from "@effect/platform/Path";
3
+ import type { ResourceRef, TranslationAdapter, AdapterReadError, AdapterWriteError } from "dialekt";
9
4
  import {
10
5
  AdapterReadError as AdapterReadErrorClass,
11
6
  AdapterWriteError as AdapterWriteErrorClass,
@@ -15,10 +10,10 @@ import {
15
10
  readPhpArrayAsJson,
16
11
  readFileIfExists,
17
12
  writeFileEnsuringDir,
18
- } from 'dialekt';
19
- import { renderPhpFile } from './php-array-writer.js';
20
- import { listLaravelLocales, listLaravelResources } from './resources.js';
21
- import { findUnusedLaravelKeys } from './unused-keys.js';
13
+ } from "dialekt";
14
+ import { renderPhpFile } from "./php-array-writer.js";
15
+ import { listLaravelLocales, listLaravelResources } from "./resources.js";
16
+ import { findUnusedLaravelKeys } from "./unused-keys.js";
22
17
 
23
18
  export interface LaravelAdapterOptions {
24
19
  readonly langDir: string;
@@ -30,7 +25,7 @@ export function laravel(options: LaravelAdapterOptions): TranslationAdapter {
30
25
  const { langDir, scanPaths = [] } = options;
31
26
 
32
27
  return {
33
- name: 'laravel',
28
+ name: "laravel",
34
29
  capabilities: {
35
30
  canCreateResource: true,
36
31
  unusedKeyDetection: true,
@@ -38,20 +33,21 @@ export function laravel(options: LaravelAdapterOptions): TranslationAdapter {
38
33
 
39
34
  listLocales: () => listLaravelLocales(langDir).pipe(Effect.provide(NodePlatformLayer)),
40
35
 
41
- listResources: (locale) => listLaravelResources(langDir, locale).pipe(Effect.provide(NodePlatformLayer)),
36
+ listResources: (locale) =>
37
+ listLaravelResources(langDir, locale).pipe(Effect.provide(NodePlatformLayer)),
42
38
 
43
39
  readResource: (locale, resource) =>
44
40
  Effect.gen(function* () {
45
41
  const path = yield* Path;
46
42
 
47
- if (resource.key === 'json') {
43
+ if (resource.key === "json") {
48
44
  // JSON locale file
49
45
  const filePath = path.join(langDir, `${locale}.json`);
50
46
  const content = yield* readFileIfExists(filePath).pipe(
51
47
  Effect.mapError(
52
48
  (cause) =>
53
49
  new AdapterReadErrorClass({
54
- adapter: 'laravel',
50
+ adapter: "laravel",
55
51
  locale,
56
52
  resource: resource.key,
57
53
  cause,
@@ -63,7 +59,7 @@ export function laravel(options: LaravelAdapterOptions): TranslationAdapter {
63
59
  try: () => JSON.parse(content) as Record<string, string>,
64
60
  catch: (cause) =>
65
61
  new AdapterReadErrorClass({
66
- adapter: 'laravel',
62
+ adapter: "laravel",
67
63
  locale,
68
64
  resource: resource.key,
69
65
  cause,
@@ -74,11 +70,11 @@ export function laravel(options: LaravelAdapterOptions): TranslationAdapter {
74
70
  // PHP domain file
75
71
  const filePath = path.join(langDir, locale, `${resource.key}.php`);
76
72
  const result = yield* readPhpArrayAsJson(filePath).pipe(
77
- Effect.catchTag('PhpExecutionError', () => Effect.succeed({})),
73
+ Effect.catchTag("PhpExecutionError", () => Effect.succeed({})),
78
74
  Effect.mapError(
79
75
  (cause) =>
80
76
  new AdapterReadErrorClass({
81
- adapter: 'laravel',
77
+ adapter: "laravel",
82
78
  locale,
83
79
  resource: resource.key,
84
80
  cause,
@@ -86,20 +82,24 @@ export function laravel(options: LaravelAdapterOptions): TranslationAdapter {
86
82
  ),
87
83
  );
88
84
  return flattenObject(result);
89
- }).pipe(Effect.provide([NodePlatformLayer])) as Effect.Effect<Record<string, string>, AdapterReadError, never>,
85
+ }).pipe(Effect.provide([NodePlatformLayer])) as Effect.Effect<
86
+ Record<string, string>,
87
+ AdapterReadError,
88
+ never
89
+ >,
90
90
 
91
91
  writeResource: (locale, resource, entries) =>
92
92
  Effect.gen(function* () {
93
93
  const path = yield* Path;
94
94
 
95
- if (resource.key === 'json') {
95
+ if (resource.key === "json") {
96
96
  // JSON locale file
97
97
  const filePath = path.join(langDir, `${locale}.json`);
98
98
  yield* writeFileEnsuringDir(filePath, JSON.stringify(entries, null, 2)).pipe(
99
99
  Effect.mapError(
100
100
  (cause) =>
101
101
  new AdapterWriteErrorClass({
102
- adapter: 'laravel',
102
+ adapter: "laravel",
103
103
  locale,
104
104
  resource: resource.key,
105
105
  cause,
@@ -116,7 +116,7 @@ export function laravel(options: LaravelAdapterOptions): TranslationAdapter {
116
116
  Effect.mapError(
117
117
  (cause) =>
118
118
  new AdapterWriteErrorClass({
119
- adapter: 'laravel',
119
+ adapter: "laravel",
120
120
  locale,
121
121
  resource: resource.key,
122
122
  cause,
@@ -128,13 +128,16 @@ export function laravel(options: LaravelAdapterOptions): TranslationAdapter {
128
128
  findUnusedKeys: (locale, resource) =>
129
129
  Effect.gen(function* () {
130
130
  const path = yield* Path;
131
- const adapterScanPaths =
132
- scanPaths.length > 0 ? scanPaths : [path.resolve(langDir, '..')];
131
+ const adapterScanPaths = scanPaths.length > 0 ? scanPaths : [path.resolve(langDir, "..")];
133
132
  const keys = yield* Effect.gen(function* () {
134
133
  const map = yield* laravel(options).readResource(locale, resource);
135
134
  return Object.keys(map);
136
135
  });
137
136
  return yield* findUnusedLaravelKeys(adapterScanPaths, resource.key, keys);
138
- }).pipe(Effect.provide([NodePlatformLayer])) as Effect.Effect<readonly string[], AdapterReadError, never>,
137
+ }).pipe(Effect.provide([NodePlatformLayer])) as Effect.Effect<
138
+ readonly string[],
139
+ AdapterReadError,
140
+ never
141
+ >,
139
142
  };
140
143
  }
package/src/index.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { laravel } from './adapter.js';
2
- export type { LaravelAdapterOptions } from './adapter.js';
1
+ export { laravel } from "./adapter.js";
2
+ export type { LaravelAdapterOptions } from "./adapter.js";
@@ -1,58 +1,58 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { renderPhpArray, renderPhpFile } from './php-array-writer.js';
1
+ import { describe, expect, it } from "vitest";
2
+ import { renderPhpArray, renderPhpFile } from "./php-array-writer.js";
3
3
 
4
- describe('renderPhpArray', () => {
5
- it('renders an empty array', () => {
6
- expect(renderPhpArray({})).toBe('[]');
4
+ describe("renderPhpArray", () => {
5
+ it("renders an empty array", () => {
6
+ expect(renderPhpArray({})).toBe("[]");
7
7
  });
8
8
 
9
- it('renders flat key-value pairs', () => {
10
- const result = renderPhpArray({ hello: 'Hello' });
9
+ it("renders flat key-value pairs", () => {
10
+ const result = renderPhpArray({ hello: "Hello" });
11
11
  expect(result).toContain("'hello' => 'Hello'");
12
12
  });
13
13
 
14
- it('renders nested objects', () => {
15
- const result = renderPhpArray({ validation: { email: 'Email address' } });
14
+ it("renders nested objects", () => {
15
+ const result = renderPhpArray({ validation: { email: "Email address" } });
16
16
  expect(result).toContain("'validation' => [");
17
17
  expect(result).toContain(" 'email' => 'Email address',");
18
18
  });
19
19
 
20
- it('escapes single quotes', () => {
20
+ it("escapes single quotes", () => {
21
21
  const result = renderPhpArray({ key: "it's" });
22
22
  expect(result).toContain("'it\\'s'");
23
23
  });
24
24
 
25
- it('escapes backslashes', () => {
26
- const result = renderPhpArray({ key: 'a\\b' });
25
+ it("escapes backslashes", () => {
26
+ const result = renderPhpArray({ key: "a\\b" });
27
27
  expect(result).toContain("'a\\\\b'");
28
28
  });
29
29
 
30
- it('preserves unicode literally', () => {
31
- const result = renderPhpArray({ key: 'Héllo 🌍 — 日本語' });
32
- expect(result).toContain('Héllo 🌍 — 日本語');
30
+ it("preserves unicode literally", () => {
31
+ const result = renderPhpArray({ key: "Héllo 🌍 — 日本語" });
32
+ expect(result).toContain("Héllo 🌍 — 日本語");
33
33
  });
34
34
 
35
- it('preserves empty string', () => {
36
- const result = renderPhpArray({ key: '' });
35
+ it("preserves empty string", () => {
36
+ const result = renderPhpArray({ key: "" });
37
37
  expect(result).toContain("'key' => '',");
38
38
  });
39
39
 
40
- it('preserves double quotes without escaping', () => {
40
+ it("preserves double quotes without escaping", () => {
41
41
  const result = renderPhpArray({ key: 'He said "hi"' });
42
42
  expect(result).toContain('"hi"');
43
43
  });
44
44
 
45
- it('renders numeric keys without quotes', () => {
46
- const result = renderPhpArray({ 0: 'first', 1: 'second' });
45
+ it("renders numeric keys without quotes", () => {
46
+ const result = renderPhpArray({ 0: "first", 1: "second" });
47
47
  expect(result).toContain("0 => 'first'");
48
48
  expect(result).toContain("1 => 'second'");
49
49
  });
50
50
  });
51
51
 
52
- describe('renderPhpFile', () => {
53
- it('wraps in PHP tags', () => {
54
- const result = renderPhpFile({ hello: 'World' });
55
- expect(result.startsWith('<?php\n\nreturn ')).toBe(true);
56
- expect(result.endsWith(';\n')).toBe(true);
52
+ describe("renderPhpFile", () => {
53
+ it("wraps in PHP tags", () => {
54
+ const result = renderPhpFile({ hello: "World" });
55
+ expect(result.startsWith("<?php\n\nreturn ")).toBe(true);
56
+ expect(result.endsWith(";\n")).toBe(true);
57
57
  });
58
58
  });
@@ -1,36 +1,33 @@
1
1
  function phpVarExport(value: string): string {
2
2
  // Wrap in single quotes; escape backslashes and single quotes only.
3
3
  // This matches PHP var_export() semantics for plain strings.
4
- const escaped = value.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
4
+ const escaped = value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
5
5
  return `'${escaped}'`;
6
6
  }
7
7
 
8
- export function renderPhpArray(
9
- value: Record<string, unknown>,
10
- indent = 0,
11
- ): string {
8
+ export function renderPhpArray(value: Record<string, unknown>, indent = 0): string {
12
9
  const entries = Object.entries(value);
13
10
  if (entries.length === 0) {
14
- return '[]';
11
+ return "[]";
15
12
  }
16
13
 
17
- const pad = ' '.repeat(indent);
18
- const innerPad = ' '.repeat(indent + 1);
19
- const lines: string[] = ['['];
14
+ const pad = " ".repeat(indent);
15
+ const innerPad = " ".repeat(indent + 1);
16
+ const lines: string[] = ["["];
20
17
 
21
18
  for (const [key, val] of entries) {
22
19
  const renderedKey = /^\d+$/.test(key) ? key : phpVarExport(key);
23
20
  const renderedValue =
24
- typeof val === 'object' && val !== null && !Array.isArray(val)
21
+ typeof val === "object" && val !== null && !Array.isArray(val)
25
22
  ? renderPhpArray(val as Record<string, unknown>, indent + 1)
26
- : typeof val === 'string'
23
+ : typeof val === "string"
27
24
  ? phpVarExport(val)
28
25
  : String(val);
29
26
  lines.push(`${innerPad}${renderedKey} => ${renderedValue},`);
30
27
  }
31
28
 
32
29
  lines.push(`${pad}]`);
33
- return lines.join('\n');
30
+ return lines.join("\n");
34
31
  }
35
32
 
36
33
  export function renderPhpFile(value: Record<string, unknown>): string {
@@ -1,58 +1,58 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { Effect } from 'effect';
3
- import { FileSystem, Path } from '@effect/platform';
4
- import { NodePlatformLayer } from 'dialekt';
5
- import { listLaravelLocales, listLaravelResources } from './resources.js';
6
- import { mkdirSync, writeFileSync, rmSync } from 'node:fs';
7
- import { join } from 'node:path';
8
- import { tmpdir } from 'node:os';
9
-
10
- describe('listLaravelLocales', () => {
11
- it('detects locales from directory structure', async () => {
1
+ import { describe, expect, it } from "vitest";
2
+ import { Effect } from "effect";
3
+ import { FileSystem, Path } from "@effect/platform";
4
+ import { NodePlatformLayer } from "dialekt";
5
+ import { listLaravelLocales, listLaravelResources } from "./resources.js";
6
+ import { mkdirSync, writeFileSync, rmSync } from "node:fs";
7
+ import { join } from "node:path";
8
+ import { tmpdir } from "node:os";
9
+
10
+ describe("listLaravelLocales", () => {
11
+ it("detects locales from directory structure", async () => {
12
12
  const dir = join(tmpdir(), `laravel-locales-${Date.now()}`);
13
- mkdirSync(join(dir, 'en'), { recursive: true });
14
- mkdirSync(join(dir, 'de'), { recursive: true });
15
- mkdirSync(join(dir, 'es'), { recursive: true });
13
+ mkdirSync(join(dir, "en"), { recursive: true });
14
+ mkdirSync(join(dir, "de"), { recursive: true });
15
+ mkdirSync(join(dir, "es"), { recursive: true });
16
16
 
17
17
  const program = listLaravelLocales(dir).pipe(Effect.provide(NodePlatformLayer));
18
18
  const result = await Effect.runPromise(program);
19
- expect(result).toContain('en');
20
- expect(result).toContain('de');
21
- expect(result).toContain('es');
19
+ expect(result).toContain("en");
20
+ expect(result).toContain("de");
21
+ expect(result).toContain("es");
22
22
 
23
23
  rmSync(dir, { recursive: true, force: true });
24
24
  });
25
25
 
26
- it('excludes vendor and lang directories', async () => {
26
+ it("excludes vendor and lang directories", async () => {
27
27
  const dir = join(tmpdir(), `laravel-locales-exclude-${Date.now()}`);
28
- mkdirSync(join(dir, 'en'), { recursive: true });
29
- mkdirSync(join(dir, 'vendor'), { recursive: true });
30
- mkdirSync(join(dir, 'lang'), { recursive: true });
28
+ mkdirSync(join(dir, "en"), { recursive: true });
29
+ mkdirSync(join(dir, "vendor"), { recursive: true });
30
+ mkdirSync(join(dir, "lang"), { recursive: true });
31
31
 
32
32
  const program = listLaravelLocales(dir).pipe(Effect.provide(NodePlatformLayer));
33
33
  const result = await Effect.runPromise(program);
34
- expect(result).toContain('en');
35
- expect(result).not.toContain('vendor');
36
- expect(result).not.toContain('lang');
34
+ expect(result).toContain("en");
35
+ expect(result).not.toContain("vendor");
36
+ expect(result).not.toContain("lang");
37
37
 
38
38
  rmSync(dir, { recursive: true, force: true });
39
39
  });
40
40
  });
41
41
 
42
- describe('listLaravelResources', () => {
43
- it('lists PHP domain files and JSON file', async () => {
42
+ describe("listLaravelResources", () => {
43
+ it("lists PHP domain files and JSON file", async () => {
44
44
  const dir = join(tmpdir(), `laravel-resources-${Date.now()}`);
45
- mkdirSync(join(dir, 'en'), { recursive: true });
46
- writeFileSync(join(dir, 'en', 'validation.php'), '<?php return [];');
47
- writeFileSync(join(dir, 'en', 'auth.php'), '<?php return [];');
48
- writeFileSync(join(dir, 'en.json'), '{}');
45
+ mkdirSync(join(dir, "en"), { recursive: true });
46
+ writeFileSync(join(dir, "en", "validation.php"), "<?php return [];");
47
+ writeFileSync(join(dir, "en", "auth.php"), "<?php return [];");
48
+ writeFileSync(join(dir, "en.json"), "{}");
49
49
 
50
- const program = listLaravelResources(dir, 'en').pipe(Effect.provide(NodePlatformLayer));
50
+ const program = listLaravelResources(dir, "en").pipe(Effect.provide(NodePlatformLayer));
51
51
  const result = await Effect.runPromise(program);
52
52
  const keys = result.map((r) => r.key);
53
- expect(keys).toContain('validation');
54
- expect(keys).toContain('auth');
55
- expect(keys).toContain('json');
53
+ expect(keys).toContain("validation");
54
+ expect(keys).toContain("auth");
55
+ expect(keys).toContain("json");
56
56
 
57
57
  rmSync(dir, { recursive: true, force: true });
58
58
  });