@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.
- package/README.md +37 -0
- package/TESTING.md +6 -6
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +222 -147
- package/package.json +2 -2
- package/src/adapter.test.ts +76 -74
- package/src/adapter.ts +29 -26
- package/src/index.ts +2 -2
- package/src/php-array-writer.test.ts +25 -25
- package/src/php-array-writer.ts +9 -12
- package/src/resources.test.ts +34 -34
- package/src/resources.ts +22 -22
- package/src/unused-keys.test.ts +29 -41
- package/src/unused-keys.ts +12 -15
- package/tsconfig.json +1 -3
- package/tsdown.config.ts +3 -3
- package/vitest.config.ts +3 -3
package/src/resources.ts
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import { FileSystem, Path } from
|
|
2
|
-
import { Effect } from
|
|
3
|
-
import type { ResourceRef, AdapterReadError } from
|
|
4
|
-
import { AdapterReadError as AdapterReadErrorClass } from
|
|
1
|
+
import { FileSystem, Path } from "@effect/platform";
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
import type { ResourceRef, AdapterReadError } from "dialekt";
|
|
4
|
+
import { AdapterReadError as AdapterReadErrorClass } from "dialekt";
|
|
5
5
|
|
|
6
6
|
export function listLaravelLocales(langDir: string) {
|
|
7
7
|
return Effect.gen(function* () {
|
|
8
8
|
const fs = yield* FileSystem.FileSystem;
|
|
9
9
|
const path = yield* Path.Path;
|
|
10
|
-
const entries = yield* fs
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
const entries = yield* fs
|
|
11
|
+
.readDirectory(langDir)
|
|
12
|
+
.pipe(Effect.orElseSucceed(() => [] as string[]));
|
|
13
13
|
const locales: string[] = [];
|
|
14
14
|
for (const entry of entries) {
|
|
15
15
|
const fullPath = path.join(langDir, entry);
|
|
16
16
|
const stat = yield* fs.stat(fullPath).pipe(Effect.option);
|
|
17
17
|
if (
|
|
18
|
-
stat._tag ===
|
|
19
|
-
stat.value.type ===
|
|
20
|
-
entry !==
|
|
21
|
-
entry !==
|
|
18
|
+
stat._tag === "Some" &&
|
|
19
|
+
stat.value.type === "Directory" &&
|
|
20
|
+
entry !== "vendor" &&
|
|
21
|
+
entry !== "lang"
|
|
22
22
|
) {
|
|
23
23
|
locales.push(entry);
|
|
24
24
|
}
|
|
@@ -28,9 +28,9 @@ export function listLaravelLocales(langDir: string) {
|
|
|
28
28
|
Effect.mapError(
|
|
29
29
|
(cause) =>
|
|
30
30
|
new AdapterReadErrorClass({
|
|
31
|
-
adapter:
|
|
32
|
-
locale:
|
|
33
|
-
resource:
|
|
31
|
+
adapter: "laravel",
|
|
32
|
+
locale: "",
|
|
33
|
+
resource: "",
|
|
34
34
|
cause,
|
|
35
35
|
}) as AdapterReadError,
|
|
36
36
|
),
|
|
@@ -46,12 +46,12 @@ export function listLaravelResources(langDir: string, locale: string) {
|
|
|
46
46
|
const refs: ResourceRef[] = [];
|
|
47
47
|
|
|
48
48
|
// PHP domain files
|
|
49
|
-
const entries = yield* fs
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
const entries = yield* fs
|
|
50
|
+
.readDirectory(localeDir)
|
|
51
|
+
.pipe(Effect.orElseSucceed(() => [] as string[]));
|
|
52
52
|
for (const entry of entries) {
|
|
53
|
-
if (entry.endsWith(
|
|
54
|
-
const domain = entry.replace(/\.php$/,
|
|
53
|
+
if (entry.endsWith(".php")) {
|
|
54
|
+
const domain = entry.replace(/\.php$/, "");
|
|
55
55
|
refs.push({ key: domain, label: domain });
|
|
56
56
|
}
|
|
57
57
|
}
|
|
@@ -60,7 +60,7 @@ export function listLaravelResources(langDir: string, locale: string) {
|
|
|
60
60
|
const jsonPath = path.join(langDir, `${locale}.json`);
|
|
61
61
|
const jsonExists = yield* fs.exists(jsonPath).pipe(Effect.orElseSucceed(() => false));
|
|
62
62
|
if (jsonExists) {
|
|
63
|
-
refs.push({ key:
|
|
63
|
+
refs.push({ key: "json", label: `${locale}.json` });
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
return refs;
|
|
@@ -68,9 +68,9 @@ export function listLaravelResources(langDir: string, locale: string) {
|
|
|
68
68
|
Effect.mapError(
|
|
69
69
|
(cause) =>
|
|
70
70
|
new AdapterReadErrorClass({
|
|
71
|
-
adapter:
|
|
71
|
+
adapter: "laravel",
|
|
72
72
|
locale,
|
|
73
|
-
resource:
|
|
73
|
+
resource: "",
|
|
74
74
|
cause,
|
|
75
75
|
}) as AdapterReadError,
|
|
76
76
|
),
|
package/src/unused-keys.test.ts
CHANGED
|
@@ -1,77 +1,65 @@
|
|
|
1
|
-
import { describe, expect, it } from
|
|
2
|
-
import { Effect } from
|
|
3
|
-
import { FileSystem, Path } from
|
|
4
|
-
import { NodePlatformLayer } from
|
|
5
|
-
import { findUnusedLaravelKeys } from
|
|
6
|
-
import { mkdirSync, writeFileSync, rmSync } from
|
|
7
|
-
import { join } from
|
|
8
|
-
import { tmpdir } from
|
|
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 { findUnusedLaravelKeys } from "./unused-keys.js";
|
|
6
|
+
import { mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { tmpdir } from "node:os";
|
|
9
9
|
|
|
10
|
-
describe(
|
|
11
|
-
it(
|
|
10
|
+
describe("findUnusedLaravelKeys", () => {
|
|
11
|
+
it("finds keys not referenced in source files", async () => {
|
|
12
12
|
const dir = join(tmpdir(), `laravel-unused-${Date.now()}`);
|
|
13
|
-
mkdirSync(join(dir,
|
|
14
|
-
writeFileSync(
|
|
15
|
-
join(dir, 'views', 'email.blade.php'),
|
|
16
|
-
"<div>{{ __('validation.email') }}</div>",
|
|
17
|
-
);
|
|
13
|
+
mkdirSync(join(dir, "views"), { recursive: true });
|
|
14
|
+
writeFileSync(join(dir, "views", "email.blade.php"), "<div>{{ __('validation.email') }}</div>");
|
|
18
15
|
|
|
19
|
-
const program = findUnusedLaravelKeys([dir],
|
|
16
|
+
const program = findUnusedLaravelKeys([dir], "validation", ["email", "password"]).pipe(
|
|
20
17
|
Effect.provide(NodePlatformLayer),
|
|
21
18
|
);
|
|
22
19
|
const result = await Effect.runPromise(program);
|
|
23
|
-
expect(result).toEqual([
|
|
20
|
+
expect(result).toEqual(["password"]);
|
|
24
21
|
|
|
25
22
|
rmSync(dir, { recursive: true, force: true });
|
|
26
23
|
});
|
|
27
24
|
|
|
28
|
-
it(
|
|
25
|
+
it("finds @lang references too", async () => {
|
|
29
26
|
const dir = join(tmpdir(), `laravel-unused-lang-${Date.now()}`);
|
|
30
|
-
mkdirSync(join(dir,
|
|
31
|
-
writeFileSync(
|
|
32
|
-
join(dir, 'views', 'page.blade.php'),
|
|
33
|
-
"@lang('validation.password')",
|
|
34
|
-
);
|
|
27
|
+
mkdirSync(join(dir, "views"), { recursive: true });
|
|
28
|
+
writeFileSync(join(dir, "views", "page.blade.php"), "@lang('validation.password')");
|
|
35
29
|
|
|
36
|
-
const program = findUnusedLaravelKeys([dir],
|
|
30
|
+
const program = findUnusedLaravelKeys([dir], "validation", ["email", "password"]).pipe(
|
|
37
31
|
Effect.provide(NodePlatformLayer),
|
|
38
32
|
);
|
|
39
33
|
const result = await Effect.runPromise(program);
|
|
40
|
-
expect(result).toEqual([
|
|
34
|
+
expect(result).toEqual(["email"]);
|
|
41
35
|
|
|
42
36
|
rmSync(dir, { recursive: true, force: true });
|
|
43
37
|
});
|
|
44
38
|
|
|
45
|
-
it(
|
|
39
|
+
it("finds trans() references too", async () => {
|
|
46
40
|
const dir = join(tmpdir(), `laravel-unused-trans-${Date.now()}`);
|
|
47
|
-
mkdirSync(join(dir,
|
|
48
|
-
writeFileSync(
|
|
49
|
-
join(dir, 'app', 'Controller.php'),
|
|
50
|
-
"trans('validation.email');",
|
|
51
|
-
);
|
|
41
|
+
mkdirSync(join(dir, "app"), { recursive: true });
|
|
42
|
+
writeFileSync(join(dir, "app", "Controller.php"), "trans('validation.email');");
|
|
52
43
|
|
|
53
|
-
const program = findUnusedLaravelKeys([dir],
|
|
44
|
+
const program = findUnusedLaravelKeys([dir], "validation", ["email", "password"]).pipe(
|
|
54
45
|
Effect.provide(NodePlatformLayer),
|
|
55
46
|
);
|
|
56
47
|
const result = await Effect.runPromise(program);
|
|
57
|
-
expect(result).toEqual([
|
|
48
|
+
expect(result).toEqual(["password"]);
|
|
58
49
|
|
|
59
50
|
rmSync(dir, { recursive: true, force: true });
|
|
60
51
|
});
|
|
61
52
|
|
|
62
|
-
it(
|
|
53
|
+
it("does not treat substrings as matches", async () => {
|
|
63
54
|
const dir = join(tmpdir(), `laravel-unused-substr-${Date.now()}`);
|
|
64
|
-
mkdirSync(join(dir,
|
|
65
|
-
writeFileSync(
|
|
66
|
-
join(dir, 'views', 'page.blade.php'),
|
|
67
|
-
"__('validation.email_longer')",
|
|
68
|
-
);
|
|
55
|
+
mkdirSync(join(dir, "views"), { recursive: true });
|
|
56
|
+
writeFileSync(join(dir, "views", "page.blade.php"), "__('validation.email_longer')");
|
|
69
57
|
|
|
70
|
-
const program = findUnusedLaravelKeys([dir],
|
|
58
|
+
const program = findUnusedLaravelKeys([dir], "validation", ["email", "email_longer"]).pipe(
|
|
71
59
|
Effect.provide(NodePlatformLayer),
|
|
72
60
|
);
|
|
73
61
|
const result = await Effect.runPromise(program);
|
|
74
|
-
expect(result).toEqual([
|
|
62
|
+
expect(result).toEqual(["email"]);
|
|
75
63
|
|
|
76
64
|
rmSync(dir, { recursive: true, force: true });
|
|
77
65
|
});
|
package/src/unused-keys.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { FileSystem, Path } from
|
|
2
|
-
import { Effect } from
|
|
3
|
-
import type { AdapterReadError } from
|
|
4
|
-
import { AdapterReadError as AdapterReadErrorClass } from
|
|
1
|
+
import { FileSystem, Path } from "@effect/platform";
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
import type { AdapterReadError } from "dialekt";
|
|
4
|
+
import { AdapterReadError as AdapterReadErrorClass } from "dialekt";
|
|
5
5
|
|
|
6
6
|
export function findUnusedLaravelKeys(
|
|
7
7
|
scanPaths: readonly string[],
|
|
@@ -19,23 +19,20 @@ export function findUnusedLaravelKeys(
|
|
|
19
19
|
const exists = yield* fs.exists(scanPath).pipe(Effect.orElseSucceed(() => false));
|
|
20
20
|
if (!exists) continue;
|
|
21
21
|
|
|
22
|
-
const entries = yield* fs
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
const entries = yield* fs
|
|
23
|
+
.readDirectory(scanPath, { recursive: true })
|
|
24
|
+
.pipe(Effect.orElseSucceed(() => [] as string[]));
|
|
25
25
|
|
|
26
26
|
for (const relativePath of entries) {
|
|
27
|
-
if (!relativePath.endsWith(
|
|
27
|
+
if (!relativePath.endsWith(".php") && !relativePath.endsWith(".blade.php")) {
|
|
28
28
|
continue;
|
|
29
29
|
}
|
|
30
30
|
const filePath = path.join(scanPath, relativePath);
|
|
31
|
-
const content = yield* fs.readFileString(filePath).pipe(Effect.orElseSucceed(() =>
|
|
31
|
+
const content = yield* fs.readFileString(filePath).pipe(Effect.orElseSucceed(() => ""));
|
|
32
32
|
|
|
33
33
|
// Extract all quoted string literals from the file content.
|
|
34
34
|
const quotedStrings: string[] = [];
|
|
35
|
-
const patterns = [
|
|
36
|
-
/'((?:[^'\\]|\\.)*)'/g,
|
|
37
|
-
/"((?:[^"\\]|\\.)*)"/g,
|
|
38
|
-
];
|
|
35
|
+
const patterns = [/'((?:[^'\\]|\\.)*)'/g, /"((?:[^"\\]|\\.)*)"/g];
|
|
39
36
|
for (const pattern of patterns) {
|
|
40
37
|
let m: RegExpExecArray | null;
|
|
41
38
|
while ((m = pattern.exec(content)) !== null) {
|
|
@@ -60,8 +57,8 @@ export function findUnusedLaravelKeys(
|
|
|
60
57
|
Effect.mapError(
|
|
61
58
|
(cause) =>
|
|
62
59
|
new AdapterReadErrorClass({
|
|
63
|
-
adapter:
|
|
64
|
-
locale:
|
|
60
|
+
adapter: "laravel",
|
|
61
|
+
locale: "",
|
|
65
62
|
resource: domain,
|
|
66
63
|
cause,
|
|
67
64
|
}) as AdapterReadError,
|
package/tsconfig.json
CHANGED
package/tsdown.config.ts
CHANGED
package/vitest.config.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { defineConfig } from
|
|
1
|
+
import { defineConfig } from "vitest/config";
|
|
2
2
|
|
|
3
3
|
export default defineConfig({
|
|
4
4
|
test: {
|
|
5
|
-
include: [
|
|
6
|
-
environment:
|
|
5
|
+
include: ["src/**/*.test.ts"],
|
|
6
|
+
environment: "node",
|
|
7
7
|
},
|
|
8
8
|
});
|