@evertondgn/solid-tooling 0.5.0 → 0.6.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.
- package/README.md +193 -634
- package/app-env.d.ts +7 -0
- package/dist/architecture-plugin.mjs +1 -1
- package/dist/backend-plugin.mjs +139 -4
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +42 -0
- package/dist/{constants-Jqvtbvxu.mjs → constants-BZJm7ouk.mjs} +1 -1
- package/dist/css-filename-CEHQd2gz.mjs +40 -0
- package/dist/css-filename.mjs +1 -40
- package/dist/fmt-9dlUYOMk.mjs +34 -0
- package/dist/fmt.mjs +1 -34
- package/dist/i18n-generate.d.mts +1 -0
- package/dist/i18n-generate.mjs +23 -0
- package/dist/i18nPlugin-CS7Gob6R.mjs +109 -0
- package/dist/knip.d.mts +2 -1
- package/dist/knip.mjs +7 -2
- package/dist/{lint-UTfyg7AR.mjs → lint-ehdtTKfw.mjs} +33 -86
- package/dist/lint.mjs +1 -1
- package/dist/playwright-teardown.mjs +1 -1
- package/dist/playwright.d.mts +2 -1
- package/dist/playwright.mjs +4 -3
- package/dist/prepareMessages-BXmY6Ko2.mjs +222 -0
- package/dist/project-plugin.mjs +2 -2
- package/dist/protocol-DSNNUYja.mjs +18 -0
- package/dist/publication/read-llms-index.d.mts +12 -0
- package/dist/publication/read-llms-index.mjs +1 -0
- package/dist/publication-CRUTOB0B.mjs +885 -0
- package/dist/readLlmsIndex-Gj4iTxAk.mjs +27 -0
- package/dist/stylelint.mjs +2 -2
- package/dist/test-locale--tuH0Np5.mjs +3 -0
- package/dist/types-DHu2Z_ot.d.mts +49 -0
- package/dist/vite.d.mts +33 -7
- package/dist/vite.mjs +415 -88
- package/dist/vitest-BjLr7iLf.mjs +362 -0
- package/dist/vitest.d.mts +3 -7
- package/dist/vitest.mjs +1 -129
- package/lefthook.yml +3 -1
- package/node-env.d.ts +1 -0
- package/package.json +32 -39
- package/tsconfig.app.json +4 -9
- package/virtual-modules.d.ts +90 -0
|
@@ -1,54 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { t as RELATIVE_IMPORT_RESTRICTION } from "./constants-BZJm7ouk.mjs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { cwd } from "node:process";
|
|
2
5
|
// src/backendPolicy/index.ts
|
|
3
|
-
const
|
|
6
|
+
const RESTRICTED_GLOBALS = [...[
|
|
4
7
|
"fetch",
|
|
5
8
|
"XMLHttpRequest",
|
|
6
9
|
"WebSocket",
|
|
7
10
|
"EventSource"
|
|
8
|
-
];
|
|
9
|
-
const RESTRICTED_GLOBALS = [...NETWORK, "console"];
|
|
11
|
+
], "console"];
|
|
10
12
|
const GLOBALS = [
|
|
11
13
|
"globalThis",
|
|
12
14
|
"window",
|
|
13
15
|
"self",
|
|
14
16
|
"global"
|
|
15
17
|
];
|
|
16
|
-
const SAFE_ERRORS = {
|
|
17
|
-
name: "@solidjs/web",
|
|
18
|
-
importNames: ["markSafeError", "SAFE_ERROR"],
|
|
19
|
-
message: "Use createPublicError; only publicErrors may mark an error as public."
|
|
20
|
-
};
|
|
21
|
-
const SERVER_ERROR_HOOK = {
|
|
22
|
-
name: "@solidjs/web",
|
|
23
|
-
importNames: ["configureServerErrors"],
|
|
24
|
-
message: "Only src/infra/server/configureServerErrors/index.ts may import this: server error handling is configured in that module."
|
|
25
|
-
};
|
|
26
|
-
const SERVER_CONFIG = ["@solidjs/web/server-functions", "@solidjs/web/server-functions/server"].map((name) => ({
|
|
27
|
-
name,
|
|
28
|
-
message: "Only src/infra/server/configureServerErrors/index.ts may import this: server error handling is configured in that module."
|
|
29
|
-
}));
|
|
30
|
-
const RENDER_OBSERVER = {
|
|
31
|
-
regex: RENDER_INTEGRITY_MODULE,
|
|
32
|
-
importNames: ["observeRenderFailures"],
|
|
33
|
-
message: "Only configureServerErrors may declare that render failures are observed."
|
|
34
|
-
};
|
|
35
|
-
const TRANSPORTS = [
|
|
36
|
-
"http",
|
|
37
|
-
"https",
|
|
38
|
-
"http2",
|
|
39
|
-
"net",
|
|
40
|
-
"tls",
|
|
41
|
-
"undici"
|
|
42
|
-
].flatMap((name) => [name, `node:${name}`]).map((name) => ({
|
|
43
|
-
name,
|
|
44
|
-
message: "Node transports cannot be imported in src/. Use requestJson for HTTP, or an adapter in src/infra/server/ wrapped in protectServerOperation."
|
|
45
|
-
}));
|
|
46
|
-
function imports({ paths, patterns = [] }) {
|
|
47
|
-
return { "eslint/no-restricted-imports": ["error", {
|
|
48
|
-
paths,
|
|
49
|
-
patterns: [RELATIVE_IMPORT_RESTRICTION, ...patterns]
|
|
50
|
-
}] };
|
|
51
|
-
}
|
|
52
18
|
function globals({ names, properties = names }) {
|
|
53
19
|
return {
|
|
54
20
|
"eslint/no-restricted-globals": ["error", {
|
|
@@ -71,45 +37,20 @@ const backendPolicy = [
|
|
|
71
37
|
"backend/static-render-integrity-imports": "error",
|
|
72
38
|
"eslint/no-console": ["error", { allow: [] }],
|
|
73
39
|
...globals({ names: RESTRICTED_GLOBALS }),
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
SAFE_ERRORS,
|
|
77
|
-
SERVER_ERROR_HOOK,
|
|
78
|
-
...SERVER_CONFIG,
|
|
79
|
-
...TRANSPORTS
|
|
80
|
-
],
|
|
81
|
-
patterns: [RENDER_OBSERVER]
|
|
82
|
-
})
|
|
83
|
-
}
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
files: ["src/infra/server/logServerFailure/index.ts"],
|
|
87
|
-
rules: {
|
|
88
|
-
...globals({
|
|
89
|
-
names: NETWORK,
|
|
90
|
-
properties: RESTRICTED_GLOBALS
|
|
91
|
-
}),
|
|
92
|
-
"eslint/no-console": ["error", { allow: ["error"] }]
|
|
40
|
+
"eslint/no-restricted-imports": "off",
|
|
41
|
+
"backend/restricted-imports": "error"
|
|
93
42
|
}
|
|
94
43
|
},
|
|
95
44
|
{
|
|
96
45
|
files: ["src/infra/server/requestJson/index.ts"],
|
|
97
46
|
rules: globals({ names: RESTRICTED_GLOBALS.filter((name) => name !== "fetch") })
|
|
98
47
|
},
|
|
99
|
-
{
|
|
100
|
-
files: ["src/infra/server/publicErrors/index.ts"],
|
|
101
|
-
rules: imports({
|
|
102
|
-
paths: [
|
|
103
|
-
SERVER_ERROR_HOOK,
|
|
104
|
-
...SERVER_CONFIG,
|
|
105
|
-
...TRANSPORTS
|
|
106
|
-
],
|
|
107
|
-
patterns: [RENDER_OBSERVER]
|
|
108
|
-
})
|
|
109
|
-
},
|
|
110
48
|
{
|
|
111
49
|
files: ["src/infra/server/configureServerErrors/index.ts"],
|
|
112
|
-
rules:
|
|
50
|
+
rules: {
|
|
51
|
+
"backend/restricted-imports": ["error", { allowServerConfiguration: true }],
|
|
52
|
+
"backend/no-setup-exports": "error"
|
|
53
|
+
}
|
|
113
54
|
},
|
|
114
55
|
{
|
|
115
56
|
files: [
|
|
@@ -123,7 +64,7 @@ const backendPolicy = [
|
|
|
123
64
|
"eslint/no-console": "off",
|
|
124
65
|
"eslint/no-restricted-globals": "off",
|
|
125
66
|
"eslint/no-restricted-properties": "off",
|
|
126
|
-
|
|
67
|
+
"backend/restricted-imports": ["error", { testFile: true }]
|
|
127
68
|
}
|
|
128
69
|
}
|
|
129
70
|
];
|
|
@@ -205,7 +146,6 @@ const environmentRules = {
|
|
|
205
146
|
"oxc/number-arg-out-of-range": "error",
|
|
206
147
|
"oxc/only-used-in-recursion": "error",
|
|
207
148
|
"oxc/uninvoked-array-callback": "error",
|
|
208
|
-
"paraglide/no-dynamic-message-access": ["error", { messageModules: ["@paraglide/messages.js", "@paraglide/messages/_index.js"] }],
|
|
209
149
|
"promise/always-return": "error",
|
|
210
150
|
"promise/avoid-new": "error",
|
|
211
151
|
"promise/catch-or-return": ["error", {
|
|
@@ -807,6 +747,21 @@ const TEST_FILES = [
|
|
|
807
747
|
"**/*.test-d.{ts,tsx}",
|
|
808
748
|
"**/tests/**"
|
|
809
749
|
];
|
|
750
|
+
const PARAGLIDE_PLUGIN = "@inlang/paraglide-js/eslint";
|
|
751
|
+
function resolvesFromApplication(specifier) {
|
|
752
|
+
try {
|
|
753
|
+
createRequire(path.join(cwd(), "package.json")).resolve(specifier);
|
|
754
|
+
return true;
|
|
755
|
+
} catch {
|
|
756
|
+
return false;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
const hasParaglide = resolvesFromApplication(PARAGLIDE_PLUGIN);
|
|
760
|
+
const paraglidePlugins = hasParaglide ? [{
|
|
761
|
+
name: "paraglide",
|
|
762
|
+
specifier: PARAGLIDE_PLUGIN
|
|
763
|
+
}] : [];
|
|
764
|
+
const paraglideRules = hasParaglide ? { "paraglide/no-dynamic-message-access": ["error", { messageModules: ["@paraglide/messages.js", "@paraglide/messages/_index.js"] }] } : {};
|
|
810
765
|
const lint = {
|
|
811
766
|
ignorePatterns: [
|
|
812
767
|
"public/**",
|
|
@@ -837,10 +792,7 @@ const lint = {
|
|
|
837
792
|
name: "architecture",
|
|
838
793
|
specifier: "@evertondgn/solid-tooling/architecture-plugin"
|
|
839
794
|
},
|
|
840
|
-
|
|
841
|
-
name: "paraglide",
|
|
842
|
-
specifier: "@inlang/paraglide-js/eslint"
|
|
843
|
-
},
|
|
795
|
+
...paraglidePlugins,
|
|
844
796
|
{
|
|
845
797
|
name: "solid",
|
|
846
798
|
specifier: "@evertondgn/solid-tooling/solid-plugin"
|
|
@@ -867,8 +819,7 @@ const lint = {
|
|
|
867
819
|
"src/**/*.node.test.{ts,tsx}",
|
|
868
820
|
"src/tests/pages/**/*.e2e.test.ts",
|
|
869
821
|
"src/tests/helpers/readSiteOrigin/index.ts",
|
|
870
|
-
"src/tests/fixtures/e2e/routes/publication-probe/metrics.ts"
|
|
871
|
-
"src/infra/server/publicationScope/index.ts"
|
|
822
|
+
"src/tests/fixtures/e2e/routes/publication-probe/metrics.ts"
|
|
872
823
|
],
|
|
873
824
|
rules: { "import/no-nodejs-modules": "off" }
|
|
874
825
|
},
|
|
@@ -885,7 +836,6 @@ const lint = {
|
|
|
885
836
|
"src/**/*.test.{ts,tsx}",
|
|
886
837
|
"src/tests/**/*.{ts,tsx}",
|
|
887
838
|
"tooling/**/__tests__/**/*.ts",
|
|
888
|
-
"tooling/i18n/i18nPlugin/index.ts",
|
|
889
839
|
"vite.config.ts"
|
|
890
840
|
],
|
|
891
841
|
rules: { "eslint/max-params": "off" }
|
|
@@ -899,11 +849,7 @@ const lint = {
|
|
|
899
849
|
rules: { "typescript/explicit-module-boundary-types": "off" }
|
|
900
850
|
},
|
|
901
851
|
{
|
|
902
|
-
files: [
|
|
903
|
-
"src/@types/solid.d.ts",
|
|
904
|
-
"src/@types/env.d.ts",
|
|
905
|
-
"src/@types/router.d.ts"
|
|
906
|
-
],
|
|
852
|
+
files: ["src/@types/solid.d.ts", "src/@types/env.d.ts"],
|
|
907
853
|
rules: {
|
|
908
854
|
"import/no-unassigned-import": "off",
|
|
909
855
|
"typescript/consistent-type-definitions": "off"
|
|
@@ -973,7 +919,8 @@ const lint = {
|
|
|
973
919
|
...importRules,
|
|
974
920
|
...typescriptRules,
|
|
975
921
|
...unicornRules,
|
|
976
|
-
...testRules
|
|
922
|
+
...testRules,
|
|
923
|
+
...paraglideRules
|
|
977
924
|
},
|
|
978
925
|
settings: {
|
|
979
926
|
"jsx-a11y": { attributes: { for: ["htmlFor", "for"] } },
|
package/dist/lint.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { t as lint } from "./lint-
|
|
1
|
+
export { t as lint } from "./lint-ehdtTKfw.mjs";
|
package/dist/playwright.d.mts
CHANGED
|
@@ -13,6 +13,7 @@ type PlaywrightOptions = {
|
|
|
13
13
|
testDir?: string;
|
|
14
14
|
fixtureServers?: FixtureServer[];
|
|
15
15
|
suites?: SerialSuites;
|
|
16
|
+
locale?: string;
|
|
16
17
|
};
|
|
17
|
-
export declare function definePlaywrightConfig({ root, testDir, fixtureServers, suites }: PlaywrightOptions): PlaywrightTestConfig;
|
|
18
|
+
export declare function definePlaywrightConfig({ root, testDir, fixtureServers, suites, locale }: PlaywrightOptions): PlaywrightTestConfig;
|
|
18
19
|
export {};
|
package/dist/playwright.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { t as TEST_LOCALE } from "./test-locale--tuH0Np5.mjs";
|
|
1
2
|
import path from "node:path";
|
|
2
|
-
import { fileURLToPath } from "node:url";
|
|
3
3
|
import { env, loadEnvFile } from "node:process";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
4
5
|
import { loadEnv } from "vite-plus";
|
|
5
6
|
import { defineConfig as defineConfig$1, devices } from "@playwright/test";
|
|
6
7
|
// src/playwright/index.ts
|
|
@@ -108,7 +109,7 @@ function buildServers({ root, mode, fixtureServers, baseUrl, serverLog }) {
|
|
|
108
109
|
}] : []
|
|
109
110
|
];
|
|
110
111
|
}
|
|
111
|
-
function definePlaywrightConfig({ root, testDir = "src/tests/pages", fixtureServers = [], suites = {} }) {
|
|
112
|
+
function definePlaywrightConfig({ root, testDir = "src/tests/pages", fixtureServers = [], suites = {}, locale = TEST_LOCALE }) {
|
|
112
113
|
loadEnvFile(path.join(root, ".env.test"));
|
|
113
114
|
const mode = readRunMode(suites);
|
|
114
115
|
const buildMode = mode.isProduction ? "production" : "e2e";
|
|
@@ -138,7 +139,7 @@ function definePlaywrightConfig({ root, testDir = "src/tests/pages", fixtureServ
|
|
|
138
139
|
...devices["Desktop Chrome"],
|
|
139
140
|
channel: env.CI ? "chrome" : void 0,
|
|
140
141
|
baseURL: baseUrl,
|
|
141
|
-
locale
|
|
142
|
+
locale,
|
|
142
143
|
screenshot: "only-on-failure",
|
|
143
144
|
trace: "retain-on-failure"
|
|
144
145
|
},
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
4
|
+
import { glob, mkdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
5
|
+
import * as v from "valibot";
|
|
6
|
+
import { randomUUID } from "node:crypto";
|
|
7
|
+
import { checkBundle } from "@inlang/sdk";
|
|
8
|
+
// src/i18n/readCatalogs/constants.ts
|
|
9
|
+
const CATALOGS_MAX_BYTES = 8388608;
|
|
10
|
+
// src/i18n/readCatalogs/index.ts
|
|
11
|
+
const CATALOG_GLOB = "src/**/i18n/*.json";
|
|
12
|
+
const CATALOG_EXCLUDES = ["src/tests/**", "src/**/__tests__/**"];
|
|
13
|
+
const CATALOG_PATH = /^src\/(?:[^/]+\/)*i18n\/[^/]+\.json$/u;
|
|
14
|
+
const EXCLUDED_PATH = /^src\/tests\/|\/__tests__\//u;
|
|
15
|
+
const ParserModuleSchema = v.object({ default: v.custom((value) => value !== null && typeof value === "object" && "importFiles" in value && typeof value.importFiles === "function", "Message format parser unavailable") });
|
|
16
|
+
function claimMessages({ keys, directory, owners }) {
|
|
17
|
+
for (const key of keys) {
|
|
18
|
+
const owner = owners.get(key);
|
|
19
|
+
if (owner) throw new Error(`[i18n] Duplicate message "${key}" in ${directory} and ${owner}`);
|
|
20
|
+
owners.set(key, directory);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function assertBudget({ bytes, maxBytes, file }) {
|
|
24
|
+
if (bytes <= maxBytes) return;
|
|
25
|
+
throw new Error(`[i18n] Catalogs exceed the ${maxBytes} byte budget at ${file}. Raise CATALOGS_MAX_BYTES only after measuring the build memory.`);
|
|
26
|
+
}
|
|
27
|
+
const TextSchema = v.string();
|
|
28
|
+
const StringsSchema = v.array(v.string());
|
|
29
|
+
const VariantsSchema = v.pipe(v.record(v.string(), TextSchema), v.minEntries(1));
|
|
30
|
+
const ComplexSchema = v.strictObject({
|
|
31
|
+
declarations: v.optional(StringsSchema),
|
|
32
|
+
selectors: v.optional(StringsSchema),
|
|
33
|
+
match: VariantsSchema
|
|
34
|
+
});
|
|
35
|
+
const MessageSchema = v.union([TextSchema, v.pipe(v.array(ComplexSchema), v.length(1))]);
|
|
36
|
+
const MessageIdSchema = v.pipe(v.string(), v.regex(/^[a-z][a-zA-Z0-9]*_[a-zA-Z0-9_]+$/u));
|
|
37
|
+
const CatalogSchema = v.pipe(v.record(MessageIdSchema, MessageSchema), v.minEntries(1, "Empty catalog"));
|
|
38
|
+
function assertUniqueProperties({ file, source }) {
|
|
39
|
+
const scopes = [];
|
|
40
|
+
const tokens = source.match(/"(?:\\.|[^"\\])*"|[{}:[\],]/gu) ?? [];
|
|
41
|
+
for (const [index, token] of tokens.entries()) if (token === "{") scopes.push(/* @__PURE__ */ new Set());
|
|
42
|
+
else if (token === "}") scopes.pop();
|
|
43
|
+
else if (token.startsWith("\"") && tokens[index + 1] === ":") {
|
|
44
|
+
const key = v.parse(v.string(), JSON.parse(token));
|
|
45
|
+
const scope = scopes.at(-1);
|
|
46
|
+
if (scope?.has(key)) throw new Error(`[i18n] ${file}: duplicate key "${key}"`);
|
|
47
|
+
scope?.add(key);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function parseCatalog({ file, source }) {
|
|
51
|
+
try {
|
|
52
|
+
const json = JSON.parse(source);
|
|
53
|
+
assertUniqueProperties({
|
|
54
|
+
file,
|
|
55
|
+
source
|
|
56
|
+
});
|
|
57
|
+
return v.parse(CatalogSchema, json);
|
|
58
|
+
} catch (error) {
|
|
59
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
60
|
+
throw new Error(`[i18n] Invalid catalog ${file}: ${detail}`, { cause: error });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async function validateMessages({ parser, directory, catalogs, baseLocale }) {
|
|
64
|
+
if (!parser.importFiles) throw new Error("Message format parser unavailable");
|
|
65
|
+
const locales = Object.keys(catalogs);
|
|
66
|
+
let parsed;
|
|
67
|
+
try {
|
|
68
|
+
parsed = await parser.importFiles({
|
|
69
|
+
files: Object.entries(catalogs).map(([locale, catalog]) => ({
|
|
70
|
+
locale,
|
|
71
|
+
content: new TextEncoder().encode(JSON.stringify(catalog))
|
|
72
|
+
})),
|
|
73
|
+
settings: {
|
|
74
|
+
baseLocale,
|
|
75
|
+
locales,
|
|
76
|
+
modules: []
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
} catch (error) {
|
|
80
|
+
throw new Error(`[i18n] Invalid message syntax in ${directory}`, { cause: error });
|
|
81
|
+
}
|
|
82
|
+
const messagesByBundle = Map.groupBy(parsed.messages, (message) => message.bundleId);
|
|
83
|
+
const variantsByBundle = Map.groupBy(parsed.variants, (variant) => variant.messageBundleId);
|
|
84
|
+
for (const bundle of parsed.bundles) {
|
|
85
|
+
if (!bundle.id) throw new Error(`[i18n] Message without ID in ${directory}`);
|
|
86
|
+
const messages = (messagesByBundle.get(bundle.id) ?? []).map((message) => ({
|
|
87
|
+
locale: message.locale,
|
|
88
|
+
id: message.locale,
|
|
89
|
+
selectors: message.selectors ?? [],
|
|
90
|
+
variants: (variantsByBundle.get(bundle.id) ?? []).filter((variant) => variant.messageLocale === message.locale).map((variant, index) => ({
|
|
91
|
+
id: String(index),
|
|
92
|
+
matches: variant.matches ?? [],
|
|
93
|
+
pattern: variant.pattern ?? []
|
|
94
|
+
}))
|
|
95
|
+
}));
|
|
96
|
+
const diagnostics = checkBundle({
|
|
97
|
+
bundle: {
|
|
98
|
+
id: bundle.id,
|
|
99
|
+
declarations: bundle.declarations ?? [],
|
|
100
|
+
messages
|
|
101
|
+
},
|
|
102
|
+
locales,
|
|
103
|
+
referenceLocale: baseLocale
|
|
104
|
+
});
|
|
105
|
+
if (diagnostics.length > 0) throw new Error(diagnostics.map((diagnostic) => `[i18n] ${directory}/${diagnostic.locale}.json: ${diagnostic.checkId}: ${diagnostic.message}`).join("\n"));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
async function readCatalogs({ root, locales, baseLocale, maxBytes = CATALOGS_MAX_BYTES }) {
|
|
109
|
+
if (!locales.includes(baseLocale) || new Set(locales).size !== locales.length) throw new Error("[i18n] Invalid locale configuration");
|
|
110
|
+
const discovered = [];
|
|
111
|
+
for await (const file of glob(CATALOG_GLOB, {
|
|
112
|
+
cwd: root,
|
|
113
|
+
exclude: CATALOG_EXCLUDES
|
|
114
|
+
})) discovered.push(file);
|
|
115
|
+
const files = discovered.toSorted();
|
|
116
|
+
if (files.length === 0) throw new Error("[i18n] No colocated catalogs found");
|
|
117
|
+
const filesByDirectory = Map.groupBy(files, (file) => path.dirname(file));
|
|
118
|
+
const catalogs = Object.fromEntries(locales.map((locale) => [locale, {}]));
|
|
119
|
+
const owners = /* @__PURE__ */ new Map();
|
|
120
|
+
let totalBytes = 0;
|
|
121
|
+
const resolveFromApp = createRequire(path.join(root, "package.json"));
|
|
122
|
+
const loaded = await import(pathToFileURL(resolveFromApp.resolve("@inlang/plugin-message-format")).href);
|
|
123
|
+
const parserModule = v.parse(ParserModuleSchema, loaded);
|
|
124
|
+
for (const [directory, entries] of filesByDirectory) {
|
|
125
|
+
const present = entries.map((file) => path.basename(file, ".json"));
|
|
126
|
+
const missing = locales.filter((locale) => !present.includes(locale));
|
|
127
|
+
const extra = present.filter((locale) => !locales.includes(locale));
|
|
128
|
+
if (missing.length > 0 || extra.length > 0) throw new Error(`[i18n] ${directory}: missing locales [${missing.join(", ")}], unexpected [${extra.join(", ")}]`);
|
|
129
|
+
const current = {};
|
|
130
|
+
for (const locale of [baseLocale, ...locales.filter((item) => item !== baseLocale)]) {
|
|
131
|
+
const file = path.join(directory, `${locale}.json`);
|
|
132
|
+
const location = path.join(root, file);
|
|
133
|
+
const { size } = await stat(location);
|
|
134
|
+
assertBudget({
|
|
135
|
+
bytes: totalBytes + size,
|
|
136
|
+
maxBytes,
|
|
137
|
+
file
|
|
138
|
+
});
|
|
139
|
+
const content = await readFile(location);
|
|
140
|
+
totalBytes += content.byteLength;
|
|
141
|
+
assertBudget({
|
|
142
|
+
bytes: totalBytes,
|
|
143
|
+
maxBytes,
|
|
144
|
+
file
|
|
145
|
+
});
|
|
146
|
+
const catalog = parseCatalog({
|
|
147
|
+
file,
|
|
148
|
+
source: content.toString("utf8")
|
|
149
|
+
});
|
|
150
|
+
current[locale] = catalog;
|
|
151
|
+
Object.assign(catalogs[locale] ?? {}, catalog);
|
|
152
|
+
}
|
|
153
|
+
await validateMessages({
|
|
154
|
+
directory,
|
|
155
|
+
catalogs: current,
|
|
156
|
+
baseLocale,
|
|
157
|
+
parser: parserModule.default
|
|
158
|
+
});
|
|
159
|
+
claimMessages({
|
|
160
|
+
keys: Object.keys(current[baseLocale] ?? {}),
|
|
161
|
+
directory,
|
|
162
|
+
owners
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
return catalogs;
|
|
166
|
+
}
|
|
167
|
+
function isCatalogFile({ root, file }) {
|
|
168
|
+
const relative = path.relative(root, file).split(path.sep).join("/");
|
|
169
|
+
return CATALOG_PATH.test(relative) && !EXCLUDED_PATH.test(relative);
|
|
170
|
+
}
|
|
171
|
+
function canContainCatalogs({ root, file }) {
|
|
172
|
+
const relative = `${path.relative(root, file).split(path.sep).join("/")}/`;
|
|
173
|
+
return relative.startsWith("src/") && !EXCLUDED_PATH.test(relative);
|
|
174
|
+
}
|
|
175
|
+
// src/i18n/prepareMessages/index.ts
|
|
176
|
+
const SETTINGS_FILE = "project.inlang/settings.json";
|
|
177
|
+
const TEMPORARY_DIRECTORY = ".paraglide";
|
|
178
|
+
const AGGREGATE_DIRECTORY = ".paraglide/messages";
|
|
179
|
+
const JSON_INDENT = 2;
|
|
180
|
+
const LocalesSchema = v.pipe(v.array(v.string()), v.minLength(1));
|
|
181
|
+
const SettingsSchema = v.object({
|
|
182
|
+
baseLocale: v.string(),
|
|
183
|
+
locales: LocalesSchema
|
|
184
|
+
});
|
|
185
|
+
function isMissing(error) {
|
|
186
|
+
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
187
|
+
}
|
|
188
|
+
async function readExisting(file) {
|
|
189
|
+
try {
|
|
190
|
+
return await readFile(file, "utf8");
|
|
191
|
+
} catch (error) {
|
|
192
|
+
if (isMissing(error)) return void 0;
|
|
193
|
+
throw error;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
async function writeIfChanged({ root, file, content }) {
|
|
197
|
+
if (await readExisting(file) === content) return;
|
|
198
|
+
const temporary = path.join(root, TEMPORARY_DIRECTORY, `.${path.basename(file)}.${randomUUID()}.tmp`);
|
|
199
|
+
await writeFile(temporary, content);
|
|
200
|
+
try {
|
|
201
|
+
await rename(temporary, file);
|
|
202
|
+
} catch (error) {
|
|
203
|
+
await rm(temporary, { force: true });
|
|
204
|
+
throw error;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
async function prepareMessages(root = process.cwd()) {
|
|
208
|
+
const resolved = path.resolve(root);
|
|
209
|
+
const source = await readFile(path.join(resolved, SETTINGS_FILE), "utf8");
|
|
210
|
+
const settings = v.parse(SettingsSchema, JSON.parse(source));
|
|
211
|
+
const catalogs = await readCatalogs({
|
|
212
|
+
root: resolved,
|
|
213
|
+
...settings
|
|
214
|
+
});
|
|
215
|
+
await mkdir(path.join(resolved, AGGREGATE_DIRECTORY), { recursive: true });
|
|
216
|
+
for (const locale of settings.locales) await writeIfChanged({
|
|
217
|
+
root: resolved,
|
|
218
|
+
file: path.join(resolved, AGGREGATE_DIRECTORY, `${locale}.json`),
|
|
219
|
+
content: `${JSON.stringify(catalogs[locale] ?? {}, null, JSON_INDENT)}\n`
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
export { canContainCatalogs as n, isCatalogFile as r, prepareMessages as t };
|
package/dist/project-plugin.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { cssFilename } from "./css-filename.mjs";
|
|
1
|
+
import { t as cssFilename } from "./css-filename-CEHQd2gz.mjs";
|
|
2
2
|
import { n as resolveProjectPath, t as readStaticSpecifier } from "./import-specifier-C7HWhMXB.mjs";
|
|
3
|
-
import { definePlugin, defineRule } from "vite-plus/lint/plugins";
|
|
4
3
|
import path from "node:path";
|
|
4
|
+
import { definePlugin, defineRule } from "vite-plus/lint/plugins";
|
|
5
5
|
// src/noExportList/index.ts
|
|
6
6
|
const noExportList = defineRule({
|
|
7
7
|
meta: {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// ../solid-runtime/src/infra/server/publication/protocol.js
|
|
2
|
+
const PUBLICATION_PHASE_ENV = "PUBLICATION_BUILD_PHASE";
|
|
3
|
+
const PUBLICATION_PRERENDER_PHASE = "prerender";
|
|
4
|
+
const PUBLICATION_ARTIFACT_DIR = "publication";
|
|
5
|
+
const SITEMAP_MANIFEST_FILE = "sitemap-manifest.json";
|
|
6
|
+
const SITEMAP_IDENTITIES_FILE = "sitemap-identities.json";
|
|
7
|
+
const SITEMAP_MANIFEST_MAX_BYTES = 1048576;
|
|
8
|
+
const SITEMAP_IDENTITIES_MAX_BYTES = 33554432;
|
|
9
|
+
const MARKDOWN_PRERENDER_PATH = "/_markdown/static.json";
|
|
10
|
+
const MAX_MARKDOWN_BYTES = 2097152;
|
|
11
|
+
const MAX_HTML_BYTES = 2097152;
|
|
12
|
+
const MARKDOWN_TIMEOUT_MS = 15e3;
|
|
13
|
+
const LLMS_PATH = "/llms.txt";
|
|
14
|
+
const LLMS_FULL_PATH = "/llms-full.txt";
|
|
15
|
+
const LLMS_DESCRIBEDBY_LINK = "</llms.txt>; rel=\"describedby\"";
|
|
16
|
+
const LLMS_MAX_BYTES = 1048576;
|
|
17
|
+
const LLMS_FULL_MAX_BYTES = 10485760;
|
|
18
|
+
export { LLMS_PATH as a, MAX_HTML_BYTES as c, PUBLICATION_PHASE_ENV as d, PUBLICATION_PRERENDER_PHASE as f, SITEMAP_MANIFEST_MAX_BYTES as g, SITEMAP_MANIFEST_FILE as h, LLMS_MAX_BYTES as i, MAX_MARKDOWN_BYTES as l, SITEMAP_IDENTITIES_MAX_BYTES as m, LLMS_FULL_MAX_BYTES as n, MARKDOWN_PRERENDER_PATH as o, SITEMAP_IDENTITIES_FILE as p, LLMS_FULL_PATH as r, MARKDOWN_TIMEOUT_MS as s, LLMS_DESCRIBEDBY_LINK as t, PUBLICATION_ARTIFACT_DIR as u };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { t as readLlmsIndex } from "../readLlmsIndex-Gj4iTxAk.mjs";
|