@saykit/config 0.4.0 → 0.5.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/dist/commands/index.cjs +14 -9
- package/dist/commands/index.d.cts +1 -1
- package/dist/commands/index.d.mts +1 -1
- package/dist/commands/index.mjs +15 -9
- package/dist/features/catalogue/index.cjs +3 -4
- package/dist/features/catalogue/index.d.cts +1 -2
- package/dist/features/catalogue/index.d.mts +1 -2
- package/dist/features/catalogue/index.mjs +3 -3
- package/dist/features/loader/index.cjs +1 -1
- package/dist/features/loader/index.d.cts +1 -2
- package/dist/features/loader/index.d.mts +1 -2
- package/dist/features/loader/index.mjs +1 -1
- package/dist/features/messages/index.cjs +17 -1
- package/dist/features/messages/index.mjs +17 -1
- package/dist/{hash-8It7TJpB.cjs → hash-51ce8YiG.cjs} +0 -1
- package/dist/index.cjs +29 -1
- package/dist/index.d.cts +11 -5
- package/dist/index.d.mts +11 -5
- package/dist/index.mjs +29 -0
- package/dist/loader-A1uS7qkK.cjs +92 -0
- package/dist/loader-DLyuZzF2.mjs +87 -0
- package/dist/{shapes-Ba3xS10n.d.cts → shapes-CRlXtss0.d.cts} +48 -2
- package/dist/{shapes-NPfwlInG.d.mts → shapes-CRlXtss0.d.mts} +48 -2
- package/dist/{storage-CqKPYfCR.mjs → storage-B6mn0s3V.mjs} +1 -1
- package/dist/{storage-C4rOvLGi.cjs → storage-DqhzA5H8.cjs} +1 -2
- package/package.json +6 -11
- package/dist/loader-B25O-vF6.cjs +0 -121
- package/dist/loader-C2eolE_1.mjs +0 -115
- /package/dist/{hash-DyC8GzMa.mjs → hash-DvzpieJD.mjs} +0 -0
package/dist/commands/index.cjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
require("../
|
|
3
|
-
const
|
|
4
|
-
const require_loader = require("../loader-B25O-vF6.cjs");
|
|
2
|
+
const require_storage = require("../storage-DqhzA5H8.cjs");
|
|
3
|
+
const require_loader = require("../loader-A1uS7qkK.cjs");
|
|
5
4
|
let _commander_js_extra_typings = require("@commander-js/extra-typings");
|
|
6
5
|
let node_fs_promises = require("node:fs/promises");
|
|
7
6
|
let node_path = require("node:path");
|
|
@@ -79,13 +78,17 @@ async function extractMessagesFromFile(path, bucket) {
|
|
|
79
78
|
//#region src/features/watch.ts
|
|
80
79
|
/**
|
|
81
80
|
* Expand a buckets include and exclude patterns into a flat list of file paths.
|
|
81
|
+
*
|
|
82
|
+
* We stat each match instead of using `glob`'s `withFileTypes` option, which
|
|
83
|
+
* Bun's `node:fs/promises` compatibility layer does not yet support.
|
|
82
84
|
*/
|
|
83
85
|
async function globBucket(bucket) {
|
|
84
86
|
const paths = [];
|
|
85
|
-
for await (const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
for await (const path of (0, node_fs_promises.glob)(bucket.include, { exclude: bucket.exclude })) try {
|
|
88
|
+
if ((await (0, node_fs_promises.stat)(path)).isFile()) paths.push(path);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (error.code !== "ENOENT") throw error;
|
|
91
|
+
}
|
|
89
92
|
return paths;
|
|
90
93
|
}
|
|
91
94
|
/**
|
|
@@ -141,7 +144,7 @@ function exists(path) {
|
|
|
141
144
|
var BucketExtractWorker = class extends BucketWorker {
|
|
142
145
|
#indexedMessagesByPath = /* @__PURE__ */ new Map();
|
|
143
146
|
get #indexedMessages() {
|
|
144
|
-
return Array.from(this.#indexedMessagesByPath.values()).flat();
|
|
147
|
+
return [...this.bucket.messages, ...Array.from(this.#indexedMessagesByPath.values()).flat()];
|
|
145
148
|
}
|
|
146
149
|
async #indexPath(path) {
|
|
147
150
|
const relativePath = normalisePathForLogs(path);
|
|
@@ -163,8 +166,10 @@ var BucketExtractWorker = class extends BucketWorker {
|
|
|
163
166
|
this.logger.info(`Scanning bucket: ${this.bucket.include}`);
|
|
164
167
|
const paths = await globBucket(this.bucket);
|
|
165
168
|
this.logger.step(`Found ${paths.length} file(s)`);
|
|
169
|
+
if (this.bucket.messages.length) this.logger.step(`Including ${this.bucket.messages.length} message(s) declared in the config`);
|
|
166
170
|
await Promise.all(paths.map((p) => this.#indexPath(p)));
|
|
167
|
-
|
|
171
|
+
const extracted = Array.from(this.#indexedMessagesByPath.values()).flat().length;
|
|
172
|
+
this.logger.info(`Total extracted messages: ${extracted}`);
|
|
168
173
|
}
|
|
169
174
|
async write() {
|
|
170
175
|
const mergedMessages = require_storage.mergeExtractedMessages(this.#indexedMessages);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {}
|
package/dist/commands/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as mergeExtractedMessages, i as expandBucketOutputPath, n as writeCatalogueMessages, o as pruneLocaleMessages, t as readCatalogueMessages } from "../storage-
|
|
3
|
-
import { t as resolveConfig } from "../loader-
|
|
2
|
+
import { a as mergeExtractedMessages, i as expandBucketOutputPath, n as writeCatalogueMessages, o as pruneLocaleMessages, t as readCatalogueMessages } from "../storage-B6mn0s3V.mjs";
|
|
3
|
+
import { t as resolveConfig } from "../loader-DLyuZzF2.mjs";
|
|
4
4
|
import { Command, program } from "@commander-js/extra-typings";
|
|
5
|
-
import { access, glob, readFile, watch } from "node:fs/promises";
|
|
5
|
+
import { access, glob, readFile, stat, watch } from "node:fs/promises";
|
|
6
6
|
import { join, relative } from "node:path";
|
|
7
7
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
8
8
|
//#region src/features/logger.ts
|
|
@@ -78,13 +78,17 @@ async function extractMessagesFromFile(path, bucket) {
|
|
|
78
78
|
//#region src/features/watch.ts
|
|
79
79
|
/**
|
|
80
80
|
* Expand a buckets include and exclude patterns into a flat list of file paths.
|
|
81
|
+
*
|
|
82
|
+
* We stat each match instead of using `glob`'s `withFileTypes` option, which
|
|
83
|
+
* Bun's `node:fs/promises` compatibility layer does not yet support.
|
|
81
84
|
*/
|
|
82
85
|
async function globBucket(bucket) {
|
|
83
86
|
const paths = [];
|
|
84
|
-
for await (const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
87
|
+
for await (const path of glob(bucket.include, { exclude: bucket.exclude })) try {
|
|
88
|
+
if ((await stat(path)).isFile()) paths.push(path);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (error.code !== "ENOENT") throw error;
|
|
91
|
+
}
|
|
88
92
|
return paths;
|
|
89
93
|
}
|
|
90
94
|
/**
|
|
@@ -140,7 +144,7 @@ function exists(path) {
|
|
|
140
144
|
var BucketExtractWorker = class extends BucketWorker {
|
|
141
145
|
#indexedMessagesByPath = /* @__PURE__ */ new Map();
|
|
142
146
|
get #indexedMessages() {
|
|
143
|
-
return Array.from(this.#indexedMessagesByPath.values()).flat();
|
|
147
|
+
return [...this.bucket.messages, ...Array.from(this.#indexedMessagesByPath.values()).flat()];
|
|
144
148
|
}
|
|
145
149
|
async #indexPath(path) {
|
|
146
150
|
const relativePath = normalisePathForLogs(path);
|
|
@@ -162,8 +166,10 @@ var BucketExtractWorker = class extends BucketWorker {
|
|
|
162
166
|
this.logger.info(`Scanning bucket: ${this.bucket.include}`);
|
|
163
167
|
const paths = await globBucket(this.bucket);
|
|
164
168
|
this.logger.step(`Found ${paths.length} file(s)`);
|
|
169
|
+
if (this.bucket.messages.length) this.logger.step(`Including ${this.bucket.messages.length} message(s) declared in the config`);
|
|
165
170
|
await Promise.all(paths.map((p) => this.#indexPath(p)));
|
|
166
|
-
|
|
171
|
+
const extracted = Array.from(this.#indexedMessagesByPath.values()).flat().length;
|
|
172
|
+
this.logger.info(`Total extracted messages: ${extracted}`);
|
|
167
173
|
}
|
|
168
174
|
async write() {
|
|
169
175
|
const mergedMessages = mergeExtractedMessages(this.#indexedMessages);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
require("../../
|
|
3
|
-
const
|
|
4
|
-
const require_storage = require("../../storage-C4rOvLGi.cjs");
|
|
2
|
+
const require_hash = require("../../hash-51ce8YiG.cjs");
|
|
3
|
+
const require_storage = require("../../storage-DqhzA5H8.cjs");
|
|
5
4
|
let node_path = require("node:path");
|
|
6
5
|
//#region src/features/catalogue/record.ts
|
|
7
6
|
/**
|
|
@@ -13,7 +12,7 @@ function resolveFallbackChain(config, locale) {
|
|
|
13
12
|
const source = config.locales[0];
|
|
14
13
|
const configured = config.fallbackLocales?.[locale];
|
|
15
14
|
const fallbacks = configured ? Array.isArray(configured) ? configured : [configured] : [];
|
|
16
|
-
return Array.from(new Set([
|
|
15
|
+
return Array.from(/* @__PURE__ */ new Set([
|
|
17
16
|
locale,
|
|
18
17
|
...fallbacks,
|
|
19
18
|
source
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { a as Message, n as Config, t as Bucket } from "../../shapes-CRlXtss0.cjs";
|
|
3
2
|
//#region src/features/catalogue/merge.d.ts
|
|
4
3
|
declare function mergeExtractedMessages(messages: Message[]): {
|
|
5
4
|
message: string;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { a as Message, n as Config, t as Bucket } from "../../shapes-CRlXtss0.mjs";
|
|
3
2
|
//#region src/features/catalogue/merge.d.ts
|
|
4
3
|
declare function mergeExtractedMessages(messages: Message[]): {
|
|
5
4
|
message: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as generateHash } from "../../hash-
|
|
2
|
-
import { a as mergeExtractedMessages, i as expandBucketOutputPath, n as writeCatalogueMessages, o as pruneLocaleMessages, r as declarationPathFor, t as readCatalogueMessages } from "../../storage-
|
|
1
|
+
import { t as generateHash } from "../../hash-DvzpieJD.mjs";
|
|
2
|
+
import { a as mergeExtractedMessages, i as expandBucketOutputPath, n as writeCatalogueMessages, o as pruneLocaleMessages, r as declarationPathFor, t as readCatalogueMessages } from "../../storage-B6mn0s3V.mjs";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
//#region src/features/catalogue/record.ts
|
|
5
5
|
/**
|
|
@@ -11,7 +11,7 @@ function resolveFallbackChain(config, locale) {
|
|
|
11
11
|
const source = config.locales[0];
|
|
12
12
|
const configured = config.fallbackLocales?.[locale];
|
|
13
13
|
const fallbacks = configured ? Array.isArray(configured) ? configured : [configured] : [];
|
|
14
|
-
return Array.from(new Set([
|
|
14
|
+
return Array.from(/* @__PURE__ */ new Set([
|
|
15
15
|
locale,
|
|
16
16
|
...fallbacks,
|
|
17
17
|
source
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as resolveConfig } from "../../loader-
|
|
1
|
+
import { t as resolveConfig } from "../../loader-DLyuZzF2.mjs";
|
|
2
2
|
export { resolveConfig };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_hash = require("../../hash-
|
|
2
|
+
const require_hash = require("../../hash-51ce8YiG.cjs");
|
|
3
3
|
//#region src/features/messages/identifier.ts
|
|
4
4
|
const AUTO_INCREMENT_IDENTIFIER = Symbol("auto-increment");
|
|
5
5
|
function assignSequenceIdentifiers(message, sequence = { current: 0 }) {
|
|
@@ -24,12 +24,15 @@ var Base = class {
|
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
26
|
var LiteralMessage = class extends Base {
|
|
27
|
+
text;
|
|
27
28
|
constructor(text) {
|
|
28
29
|
super();
|
|
29
30
|
this.text = text;
|
|
30
31
|
}
|
|
31
32
|
};
|
|
32
33
|
var ArgumentMessage = class extends Base {
|
|
34
|
+
identifier;
|
|
35
|
+
expression;
|
|
33
36
|
constructor(identifier, expression) {
|
|
34
37
|
super();
|
|
35
38
|
this.identifier = identifier;
|
|
@@ -37,6 +40,9 @@ var ArgumentMessage = class extends Base {
|
|
|
37
40
|
}
|
|
38
41
|
};
|
|
39
42
|
var ElementMessage = class extends Base {
|
|
43
|
+
identifier;
|
|
44
|
+
children;
|
|
45
|
+
expression;
|
|
40
46
|
constructor(identifier, children, expression) {
|
|
41
47
|
super();
|
|
42
48
|
this.identifier = identifier;
|
|
@@ -45,6 +51,10 @@ var ElementMessage = class extends Base {
|
|
|
45
51
|
}
|
|
46
52
|
};
|
|
47
53
|
var ChoiceMessage = class extends Base {
|
|
54
|
+
kind;
|
|
55
|
+
identifier;
|
|
56
|
+
branches;
|
|
57
|
+
expression;
|
|
48
58
|
constructor(kind, identifier, branches, expression) {
|
|
49
59
|
super();
|
|
50
60
|
this.kind = kind;
|
|
@@ -54,6 +64,12 @@ var ChoiceMessage = class extends Base {
|
|
|
54
64
|
}
|
|
55
65
|
};
|
|
56
66
|
var CompositeMessage = class extends Base {
|
|
67
|
+
descriptor;
|
|
68
|
+
comments;
|
|
69
|
+
references;
|
|
70
|
+
children;
|
|
71
|
+
accessor;
|
|
72
|
+
whitespace;
|
|
57
73
|
constructor(descriptor, comments, references, children, accessor, whitespace) {
|
|
58
74
|
super();
|
|
59
75
|
this.descriptor = descriptor;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as generateHash } from "../../hash-
|
|
1
|
+
import { t as generateHash } from "../../hash-DvzpieJD.mjs";
|
|
2
2
|
//#region src/features/messages/identifier.ts
|
|
3
3
|
const AUTO_INCREMENT_IDENTIFIER = Symbol("auto-increment");
|
|
4
4
|
function assignSequenceIdentifiers(message, sequence = { current: 0 }) {
|
|
@@ -23,12 +23,15 @@ var Base = class {
|
|
|
23
23
|
}
|
|
24
24
|
};
|
|
25
25
|
var LiteralMessage = class extends Base {
|
|
26
|
+
text;
|
|
26
27
|
constructor(text) {
|
|
27
28
|
super();
|
|
28
29
|
this.text = text;
|
|
29
30
|
}
|
|
30
31
|
};
|
|
31
32
|
var ArgumentMessage = class extends Base {
|
|
33
|
+
identifier;
|
|
34
|
+
expression;
|
|
32
35
|
constructor(identifier, expression) {
|
|
33
36
|
super();
|
|
34
37
|
this.identifier = identifier;
|
|
@@ -36,6 +39,9 @@ var ArgumentMessage = class extends Base {
|
|
|
36
39
|
}
|
|
37
40
|
};
|
|
38
41
|
var ElementMessage = class extends Base {
|
|
42
|
+
identifier;
|
|
43
|
+
children;
|
|
44
|
+
expression;
|
|
39
45
|
constructor(identifier, children, expression) {
|
|
40
46
|
super();
|
|
41
47
|
this.identifier = identifier;
|
|
@@ -44,6 +50,10 @@ var ElementMessage = class extends Base {
|
|
|
44
50
|
}
|
|
45
51
|
};
|
|
46
52
|
var ChoiceMessage = class extends Base {
|
|
53
|
+
kind;
|
|
54
|
+
identifier;
|
|
55
|
+
branches;
|
|
56
|
+
expression;
|
|
47
57
|
constructor(kind, identifier, branches, expression) {
|
|
48
58
|
super();
|
|
49
59
|
this.kind = kind;
|
|
@@ -53,6 +63,12 @@ var ChoiceMessage = class extends Base {
|
|
|
53
63
|
}
|
|
54
64
|
};
|
|
55
65
|
var CompositeMessage = class extends Base {
|
|
66
|
+
descriptor;
|
|
67
|
+
comments;
|
|
68
|
+
references;
|
|
69
|
+
children;
|
|
70
|
+
accessor;
|
|
71
|
+
whitespace;
|
|
56
72
|
constructor(descriptor, comments, references, children, accessor, whitespace) {
|
|
57
73
|
super();
|
|
58
74
|
this.descriptor = descriptor;
|
package/dist/index.cjs
CHANGED
|
@@ -43,6 +43,16 @@ const Transformer = zod.object({
|
|
|
43
43
|
extract: zod.custom((v) => typeof v === "function"),
|
|
44
44
|
transform: zod.custom((v) => typeof v === "function")
|
|
45
45
|
});
|
|
46
|
+
/**
|
|
47
|
+
* A message declared in the config rather than found in source. The shorthand
|
|
48
|
+
* is the source string; the object form adds the metadata a descriptor would
|
|
49
|
+
* otherwise carry.
|
|
50
|
+
*/
|
|
51
|
+
const DeclaredMessage = zod.string().or(zod.object({
|
|
52
|
+
message: zod.string(),
|
|
53
|
+
context: zod.string().optional(),
|
|
54
|
+
comments: zod.string().array().optional()
|
|
55
|
+
}));
|
|
46
56
|
const Bucket = zod.object({
|
|
47
57
|
include: zod.string().array(),
|
|
48
58
|
exclude: zod.string().array().optional(),
|
|
@@ -52,6 +62,14 @@ const Bucket = zod.object({
|
|
|
52
62
|
zod.string(),
|
|
53
63
|
".{extension}"
|
|
54
64
|
]),
|
|
65
|
+
/**
|
|
66
|
+
* Messages that belong in the catalogue but have no call site to extract
|
|
67
|
+
* them from — strings owned by a non-JavaScript artefact such as a manifest,
|
|
68
|
+
* a store listing, or an email subject. Keyed by id, so the id is stable and
|
|
69
|
+
* hand-written by definition, and merged into every extraction alongside
|
|
70
|
+
* whatever the transformers find.
|
|
71
|
+
*/
|
|
72
|
+
messages: zod.record(zod.string(), DeclaredMessage).optional(),
|
|
55
73
|
formatter: Formatter,
|
|
56
74
|
transformer: Transformer.transform((t) => [t]).or(Transformer.array()).transform((t) => ({
|
|
57
75
|
match: (id) => t.some((t) => t.match(id)),
|
|
@@ -60,6 +78,17 @@ const Bucket = zod.object({
|
|
|
60
78
|
}))
|
|
61
79
|
}).transform((v) => ({
|
|
62
80
|
...v,
|
|
81
|
+
messages: Object.entries(v.messages ?? {}).map(([id, declared]) => {
|
|
82
|
+
const entry = typeof declared === "string" ? { message: declared } : declared;
|
|
83
|
+
return {
|
|
84
|
+
id,
|
|
85
|
+
message: entry.message,
|
|
86
|
+
translation: entry.message,
|
|
87
|
+
context: "context" in entry ? entry.context : void 0,
|
|
88
|
+
comments: ("comments" in entry ? entry.comments : void 0) ?? [],
|
|
89
|
+
references: []
|
|
90
|
+
};
|
|
91
|
+
}),
|
|
63
92
|
match: (0, picomatch.default)(v.include, { ignore: v.exclude }),
|
|
64
93
|
output: Object.assign(v.output, { match: (0, picomatch.default)(v.output.replace("{locale}", "*").replace("{extension}", v.formatter.extension.slice(1))) })
|
|
65
94
|
}));
|
|
@@ -80,5 +109,4 @@ function defineConfig(config) {
|
|
|
80
109
|
return Config.parse(config);
|
|
81
110
|
}
|
|
82
111
|
//#endregion
|
|
83
|
-
exports.__toESM = __toESM;
|
|
84
112
|
exports.defineConfig = defineConfig;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as Message, i as Formatter, n as Config, o as Transformer, r as DeclaredMessage, t as Bucket } from "./shapes-CRlXtss0.cjs";
|
|
2
2
|
import { input } from "zod";
|
|
3
|
-
import * as _$picomatch_lib_picomatch_js0 from "picomatch/lib/picomatch.js";
|
|
4
|
-
|
|
5
3
|
//#region src/index.d.ts
|
|
6
4
|
declare function defineConfig<C extends input<typeof Config>>(config: C): {
|
|
7
5
|
locales: [string, ...string[]];
|
|
8
6
|
buckets: {
|
|
7
|
+
messages: {
|
|
8
|
+
message: string;
|
|
9
|
+
comments: string[];
|
|
10
|
+
references: string[];
|
|
11
|
+
translation?: string | undefined;
|
|
12
|
+
id?: string | undefined;
|
|
13
|
+
context?: string | undefined;
|
|
14
|
+
}[];
|
|
9
15
|
match: (id: string) => boolean;
|
|
10
16
|
output: `${string}{locale}${string}.{extension}` & {
|
|
11
|
-
match:
|
|
17
|
+
match: import("picomatch/lib/picomatch.js").Matcher;
|
|
12
18
|
};
|
|
13
19
|
include: string[];
|
|
14
20
|
formatter: {
|
|
@@ -36,4 +42,4 @@ declare function defineConfig<C extends input<typeof Config>>(config: C): {
|
|
|
36
42
|
fallbackLocales?: Record<string, string | string[]> | undefined;
|
|
37
43
|
};
|
|
38
44
|
//#endregion
|
|
39
|
-
export { Bucket, Config, Formatter, Message, Transformer, defineConfig };
|
|
45
|
+
export { type Bucket, type Config, type DeclaredMessage, type Formatter, type Message, type Transformer, defineConfig };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as Message, i as Formatter, n as Config, o as Transformer, r as DeclaredMessage, t as Bucket } from "./shapes-CRlXtss0.mjs";
|
|
2
2
|
import { input } from "zod";
|
|
3
|
-
import * as _$picomatch_lib_picomatch_js0 from "picomatch/lib/picomatch.js";
|
|
4
|
-
|
|
5
3
|
//#region src/index.d.ts
|
|
6
4
|
declare function defineConfig<C extends input<typeof Config>>(config: C): {
|
|
7
5
|
locales: [string, ...string[]];
|
|
8
6
|
buckets: {
|
|
7
|
+
messages: {
|
|
8
|
+
message: string;
|
|
9
|
+
comments: string[];
|
|
10
|
+
references: string[];
|
|
11
|
+
translation?: string | undefined;
|
|
12
|
+
id?: string | undefined;
|
|
13
|
+
context?: string | undefined;
|
|
14
|
+
}[];
|
|
9
15
|
match: (id: string) => boolean;
|
|
10
16
|
output: `${string}{locale}${string}.{extension}` & {
|
|
11
|
-
match:
|
|
17
|
+
match: import("picomatch/lib/picomatch.js").Matcher;
|
|
12
18
|
};
|
|
13
19
|
include: string[];
|
|
14
20
|
formatter: {
|
|
@@ -36,4 +42,4 @@ declare function defineConfig<C extends input<typeof Config>>(config: C): {
|
|
|
36
42
|
fallbackLocales?: Record<string, string | string[]> | undefined;
|
|
37
43
|
};
|
|
38
44
|
//#endregion
|
|
39
|
-
export { Bucket, Config, Formatter, Message, Transformer, defineConfig };
|
|
45
|
+
export { type Bucket, type Config, type DeclaredMessage, type Formatter, type Message, type Transformer, defineConfig };
|
package/dist/index.mjs
CHANGED
|
@@ -18,6 +18,16 @@ const Transformer = z.object({
|
|
|
18
18
|
extract: z.custom((v) => typeof v === "function"),
|
|
19
19
|
transform: z.custom((v) => typeof v === "function")
|
|
20
20
|
});
|
|
21
|
+
/**
|
|
22
|
+
* A message declared in the config rather than found in source. The shorthand
|
|
23
|
+
* is the source string; the object form adds the metadata a descriptor would
|
|
24
|
+
* otherwise carry.
|
|
25
|
+
*/
|
|
26
|
+
const DeclaredMessage = z.string().or(z.object({
|
|
27
|
+
message: z.string(),
|
|
28
|
+
context: z.string().optional(),
|
|
29
|
+
comments: z.string().array().optional()
|
|
30
|
+
}));
|
|
21
31
|
const Bucket = z.object({
|
|
22
32
|
include: z.string().array(),
|
|
23
33
|
exclude: z.string().array().optional(),
|
|
@@ -27,6 +37,14 @@ const Bucket = z.object({
|
|
|
27
37
|
z.string(),
|
|
28
38
|
".{extension}"
|
|
29
39
|
]),
|
|
40
|
+
/**
|
|
41
|
+
* Messages that belong in the catalogue but have no call site to extract
|
|
42
|
+
* them from — strings owned by a non-JavaScript artefact such as a manifest,
|
|
43
|
+
* a store listing, or an email subject. Keyed by id, so the id is stable and
|
|
44
|
+
* hand-written by definition, and merged into every extraction alongside
|
|
45
|
+
* whatever the transformers find.
|
|
46
|
+
*/
|
|
47
|
+
messages: z.record(z.string(), DeclaredMessage).optional(),
|
|
30
48
|
formatter: Formatter,
|
|
31
49
|
transformer: Transformer.transform((t) => [t]).or(Transformer.array()).transform((t) => ({
|
|
32
50
|
match: (id) => t.some((t) => t.match(id)),
|
|
@@ -35,6 +53,17 @@ const Bucket = z.object({
|
|
|
35
53
|
}))
|
|
36
54
|
}).transform((v) => ({
|
|
37
55
|
...v,
|
|
56
|
+
messages: Object.entries(v.messages ?? {}).map(([id, declared]) => {
|
|
57
|
+
const entry = typeof declared === "string" ? { message: declared } : declared;
|
|
58
|
+
return {
|
|
59
|
+
id,
|
|
60
|
+
message: entry.message,
|
|
61
|
+
translation: entry.message,
|
|
62
|
+
context: "context" in entry ? entry.context : void 0,
|
|
63
|
+
comments: ("comments" in entry ? entry.comments : void 0) ?? [],
|
|
64
|
+
references: []
|
|
65
|
+
};
|
|
66
|
+
}),
|
|
38
67
|
match: picomatch(v.include, { ignore: v.exclude }),
|
|
39
68
|
output: Object.assign(v.output, { match: picomatch(v.output.replace("{locale}", "*").replace("{extension}", v.formatter.extension.slice(1))) })
|
|
40
69
|
}));
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
let node_path = require("node:path");
|
|
2
|
+
let node_fs = require("node:fs");
|
|
3
|
+
let node_module = require("node:module");
|
|
4
|
+
//#region src/features/loader/files.ts
|
|
5
|
+
const SUPPORTED_CONFIG_FILES = [
|
|
6
|
+
"saykit.config.js",
|
|
7
|
+
"saykit.config.cjs",
|
|
8
|
+
"saykit.config.mjs",
|
|
9
|
+
"saykit.config.ts",
|
|
10
|
+
"saykit.config.mts",
|
|
11
|
+
"saykit.config.cts"
|
|
12
|
+
];
|
|
13
|
+
function getConfigFileCandidates(name) {
|
|
14
|
+
return SUPPORTED_CONFIG_FILES.map((file) => file.replace("saykit", name));
|
|
15
|
+
}
|
|
16
|
+
function findConfigFile(moduleName, projectDir) {
|
|
17
|
+
for (const fileName of getConfigFileCandidates(moduleName)) {
|
|
18
|
+
const id = (0, node_path.join)(projectDir, fileName);
|
|
19
|
+
if ((0, node_fs.existsSync)(id)) return { id };
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/features/loader/module.ts
|
|
25
|
+
/** Requires `path` without leaving it in (or reading it from) the require cache. */
|
|
26
|
+
function requireFresh(require, path) {
|
|
27
|
+
const resolved = require.resolve(path);
|
|
28
|
+
delete require.cache[resolved];
|
|
29
|
+
const module = require(path);
|
|
30
|
+
delete require.cache[resolved];
|
|
31
|
+
return module?.default ?? module;
|
|
32
|
+
}
|
|
33
|
+
const TYPESCRIPT = /* @__PURE__ */ new Set([
|
|
34
|
+
".ts",
|
|
35
|
+
".mts",
|
|
36
|
+
".cts"
|
|
37
|
+
]);
|
|
38
|
+
/**
|
|
39
|
+
* Adds what the runtime cannot: why a config it could not read is one it will
|
|
40
|
+
* never read. Everything else is the config's own problem, and its error
|
|
41
|
+
* already describes that better than we could.
|
|
42
|
+
*/
|
|
43
|
+
function diagnose(error, path) {
|
|
44
|
+
const code = error?.code;
|
|
45
|
+
if (code === "ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX") return "Enums, namespaces and parameter properties are not erasable, so no runtime will read them.";
|
|
46
|
+
if (code === "ERR_REQUIRE_ASYNC_MODULE") return "The config is loaded synchronously, so it cannot use top-level await.";
|
|
47
|
+
if ((code === "ERR_UNKNOWN_FILE_EXTENSION" || !code && error instanceof SyntaxError) && TYPESCRIPT.has((0, node_path.extname)(path).toLowerCase())) return "Reading this config needs Node 22.18+, or a runtime that loads TypeScript itself (Bun, Deno, tsx).";
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Loads a config file as it sits on disk, leaving the runtime to deal with the
|
|
52
|
+
* extension. Nothing is copied or rewritten, so `__dirname`,
|
|
53
|
+
* `import.meta.dirname`, relative specifiers and `require.resolve` all resolve
|
|
54
|
+
* against the config's own directory.
|
|
55
|
+
*/
|
|
56
|
+
function loadModule(path) {
|
|
57
|
+
try {
|
|
58
|
+
return requireFresh((0, node_module.createRequire)(path), path);
|
|
59
|
+
} catch (error) {
|
|
60
|
+
const hint = diagnose(error, path);
|
|
61
|
+
throw new Error(hint ? `Failed to import module. ${hint}` : "Failed to import module", { cause: error });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const js = loadModule;
|
|
65
|
+
const ts = loadModule;
|
|
66
|
+
const configLoaders = Object.freeze({
|
|
67
|
+
".js": js,
|
|
68
|
+
".mjs": js,
|
|
69
|
+
".cjs": js,
|
|
70
|
+
".ts": ts,
|
|
71
|
+
".mts": ts,
|
|
72
|
+
".cts": ts
|
|
73
|
+
});
|
|
74
|
+
//#endregion
|
|
75
|
+
//#region src/features/loader/resolve.ts
|
|
76
|
+
function resolveConfig(name = "saykit") {
|
|
77
|
+
const file = findConfigFile(name, process.cwd());
|
|
78
|
+
if (!file) throw new Error(`Could not find config file for "${name}"`);
|
|
79
|
+
const ext = (0, node_path.extname)(file.id).toLowerCase();
|
|
80
|
+
const load = ext in configLoaders ? configLoaders[ext] : null;
|
|
81
|
+
if (!load) throw new Error(`Unsupported config file type "${ext}" for "${name}"`);
|
|
82
|
+
const config = load(file.id);
|
|
83
|
+
if (!config || typeof config !== "object") throw new Error(`Invalid config file for "${name}"`);
|
|
84
|
+
return config;
|
|
85
|
+
}
|
|
86
|
+
//#endregion
|
|
87
|
+
Object.defineProperty(exports, "resolveConfig", {
|
|
88
|
+
enumerable: true,
|
|
89
|
+
get: function() {
|
|
90
|
+
return resolveConfig;
|
|
91
|
+
}
|
|
92
|
+
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { extname, join } from "node:path";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
//#region src/features/loader/files.ts
|
|
5
|
+
const SUPPORTED_CONFIG_FILES = [
|
|
6
|
+
"saykit.config.js",
|
|
7
|
+
"saykit.config.cjs",
|
|
8
|
+
"saykit.config.mjs",
|
|
9
|
+
"saykit.config.ts",
|
|
10
|
+
"saykit.config.mts",
|
|
11
|
+
"saykit.config.cts"
|
|
12
|
+
];
|
|
13
|
+
function getConfigFileCandidates(name) {
|
|
14
|
+
return SUPPORTED_CONFIG_FILES.map((file) => file.replace("saykit", name));
|
|
15
|
+
}
|
|
16
|
+
function findConfigFile(moduleName, projectDir) {
|
|
17
|
+
for (const fileName of getConfigFileCandidates(moduleName)) {
|
|
18
|
+
const id = join(projectDir, fileName);
|
|
19
|
+
if (existsSync(id)) return { id };
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/features/loader/module.ts
|
|
25
|
+
/** Requires `path` without leaving it in (or reading it from) the require cache. */
|
|
26
|
+
function requireFresh(require, path) {
|
|
27
|
+
const resolved = require.resolve(path);
|
|
28
|
+
delete require.cache[resolved];
|
|
29
|
+
const module = require(path);
|
|
30
|
+
delete require.cache[resolved];
|
|
31
|
+
return module?.default ?? module;
|
|
32
|
+
}
|
|
33
|
+
const TYPESCRIPT = /* @__PURE__ */ new Set([
|
|
34
|
+
".ts",
|
|
35
|
+
".mts",
|
|
36
|
+
".cts"
|
|
37
|
+
]);
|
|
38
|
+
/**
|
|
39
|
+
* Adds what the runtime cannot: why a config it could not read is one it will
|
|
40
|
+
* never read. Everything else is the config's own problem, and its error
|
|
41
|
+
* already describes that better than we could.
|
|
42
|
+
*/
|
|
43
|
+
function diagnose(error, path) {
|
|
44
|
+
const code = error?.code;
|
|
45
|
+
if (code === "ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX") return "Enums, namespaces and parameter properties are not erasable, so no runtime will read them.";
|
|
46
|
+
if (code === "ERR_REQUIRE_ASYNC_MODULE") return "The config is loaded synchronously, so it cannot use top-level await.";
|
|
47
|
+
if ((code === "ERR_UNKNOWN_FILE_EXTENSION" || !code && error instanceof SyntaxError) && TYPESCRIPT.has(extname(path).toLowerCase())) return "Reading this config needs Node 22.18+, or a runtime that loads TypeScript itself (Bun, Deno, tsx).";
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Loads a config file as it sits on disk, leaving the runtime to deal with the
|
|
52
|
+
* extension. Nothing is copied or rewritten, so `__dirname`,
|
|
53
|
+
* `import.meta.dirname`, relative specifiers and `require.resolve` all resolve
|
|
54
|
+
* against the config's own directory.
|
|
55
|
+
*/
|
|
56
|
+
function loadModule(path) {
|
|
57
|
+
try {
|
|
58
|
+
return requireFresh(createRequire(path), path);
|
|
59
|
+
} catch (error) {
|
|
60
|
+
const hint = diagnose(error, path);
|
|
61
|
+
throw new Error(hint ? `Failed to import module. ${hint}` : "Failed to import module", { cause: error });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const js = loadModule;
|
|
65
|
+
const ts = loadModule;
|
|
66
|
+
const configLoaders = Object.freeze({
|
|
67
|
+
".js": js,
|
|
68
|
+
".mjs": js,
|
|
69
|
+
".cjs": js,
|
|
70
|
+
".ts": ts,
|
|
71
|
+
".mts": ts,
|
|
72
|
+
".cts": ts
|
|
73
|
+
});
|
|
74
|
+
//#endregion
|
|
75
|
+
//#region src/features/loader/resolve.ts
|
|
76
|
+
function resolveConfig(name = "saykit") {
|
|
77
|
+
const file = findConfigFile(name, process.cwd());
|
|
78
|
+
if (!file) throw new Error(`Could not find config file for "${name}"`);
|
|
79
|
+
const ext = extname(file.id).toLowerCase();
|
|
80
|
+
const load = ext in configLoaders ? configLoaders[ext] : null;
|
|
81
|
+
if (!load) throw new Error(`Unsupported config file type "${ext}" for "${name}"`);
|
|
82
|
+
const config = load(file.id);
|
|
83
|
+
if (!config || typeof config !== "object") throw new Error(`Invalid config file for "${name}"`);
|
|
84
|
+
return config;
|
|
85
|
+
}
|
|
86
|
+
//#endregion
|
|
87
|
+
export { resolveConfig as t };
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import picomatch from "picomatch";
|
|
2
2
|
import * as z from "zod";
|
|
3
|
-
|
|
4
3
|
//#region src/shapes.d.ts
|
|
5
4
|
declare const Message: z.ZodObject<{
|
|
6
5
|
message: z.ZodString;
|
|
@@ -29,10 +28,26 @@ declare const Transformer: z.ZodObject<{
|
|
|
29
28
|
transform: z.ZodCustom<(code: string, id: string) => string, (code: string, id: string) => string>;
|
|
30
29
|
}, z.core.$strip>;
|
|
31
30
|
type Transformer = z.infer<typeof Transformer>;
|
|
31
|
+
/**
|
|
32
|
+
* A message declared in the config rather than found in source. The shorthand
|
|
33
|
+
* is the source string; the object form adds the metadata a descriptor would
|
|
34
|
+
* otherwise carry.
|
|
35
|
+
*/
|
|
36
|
+
declare const DeclaredMessage: z.ZodUnion<[z.ZodString, z.ZodObject<{
|
|
37
|
+
message: z.ZodString;
|
|
38
|
+
context: z.ZodOptional<z.ZodString>;
|
|
39
|
+
comments: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
40
|
+
}, z.core.$strip>]>;
|
|
41
|
+
type DeclaredMessage = z.infer<typeof DeclaredMessage>;
|
|
32
42
|
declare const Bucket: z.ZodPipe<z.ZodObject<{
|
|
33
43
|
include: z.ZodArray<z.ZodString>;
|
|
34
44
|
exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
35
45
|
output: z.ZodTemplateLiteral<`${string}{locale}${string}.{extension}`>;
|
|
46
|
+
messages: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodString, z.ZodObject<{
|
|
47
|
+
message: z.ZodString;
|
|
48
|
+
context: z.ZodOptional<z.ZodString>;
|
|
49
|
+
comments: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
50
|
+
}, z.core.$strip>]>>>;
|
|
36
51
|
formatter: z.ZodObject<{
|
|
37
52
|
extension: z.ZodTemplateLiteral<`.${string}`>;
|
|
38
53
|
parse: z.ZodCustom<(content: string) => Message[], (content: string) => Message[]>;
|
|
@@ -77,6 +92,14 @@ declare const Bucket: z.ZodPipe<z.ZodObject<{
|
|
|
77
92
|
transform: (code: string, id: string) => string;
|
|
78
93
|
}[]>>;
|
|
79
94
|
}, z.core.$strip>, z.ZodTransform<{
|
|
95
|
+
messages: {
|
|
96
|
+
message: string;
|
|
97
|
+
comments: string[];
|
|
98
|
+
references: string[];
|
|
99
|
+
translation?: string | undefined;
|
|
100
|
+
id?: string | undefined;
|
|
101
|
+
context?: string | undefined;
|
|
102
|
+
}[];
|
|
80
103
|
match: (id: string) => boolean;
|
|
81
104
|
output: `${string}{locale}${string}.{extension}` & {
|
|
82
105
|
match: picomatch.Matcher;
|
|
@@ -127,6 +150,11 @@ declare const Bucket: z.ZodPipe<z.ZodObject<{
|
|
|
127
150
|
transform: (code: string, id: string) => string;
|
|
128
151
|
};
|
|
129
152
|
exclude?: string[] | undefined;
|
|
153
|
+
messages?: Record<string, string | {
|
|
154
|
+
message: string;
|
|
155
|
+
context?: string | undefined;
|
|
156
|
+
comments?: string[] | undefined;
|
|
157
|
+
}> | undefined;
|
|
130
158
|
}>>;
|
|
131
159
|
type Bucket = z.infer<typeof Bucket>;
|
|
132
160
|
declare const Config: z.ZodObject<{
|
|
@@ -136,6 +164,11 @@ declare const Config: z.ZodObject<{
|
|
|
136
164
|
include: z.ZodArray<z.ZodString>;
|
|
137
165
|
exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
138
166
|
output: z.ZodTemplateLiteral<`${string}{locale}${string}.{extension}`>;
|
|
167
|
+
messages: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodString, z.ZodObject<{
|
|
168
|
+
message: z.ZodString;
|
|
169
|
+
context: z.ZodOptional<z.ZodString>;
|
|
170
|
+
comments: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
171
|
+
}, z.core.$strip>]>>>;
|
|
139
172
|
formatter: z.ZodObject<{
|
|
140
173
|
extension: z.ZodTemplateLiteral<`.${string}`>;
|
|
141
174
|
parse: z.ZodCustom<(content: string) => Message[], (content: string) => Message[]>;
|
|
@@ -180,6 +213,14 @@ declare const Config: z.ZodObject<{
|
|
|
180
213
|
transform: (code: string, id: string) => string;
|
|
181
214
|
}[]>>;
|
|
182
215
|
}, z.core.$strip>, z.ZodTransform<{
|
|
216
|
+
messages: {
|
|
217
|
+
message: string;
|
|
218
|
+
comments: string[];
|
|
219
|
+
references: string[];
|
|
220
|
+
translation?: string | undefined;
|
|
221
|
+
id?: string | undefined;
|
|
222
|
+
context?: string | undefined;
|
|
223
|
+
}[];
|
|
183
224
|
match: (id: string) => boolean;
|
|
184
225
|
output: `${string}{locale}${string}.{extension}` & {
|
|
185
226
|
match: picomatch.Matcher;
|
|
@@ -230,8 +271,13 @@ declare const Config: z.ZodObject<{
|
|
|
230
271
|
transform: (code: string, id: string) => string;
|
|
231
272
|
};
|
|
232
273
|
exclude?: string[] | undefined;
|
|
274
|
+
messages?: Record<string, string | {
|
|
275
|
+
message: string;
|
|
276
|
+
context?: string | undefined;
|
|
277
|
+
comments?: string[] | undefined;
|
|
278
|
+
}> | undefined;
|
|
233
279
|
}>>>;
|
|
234
280
|
}, z.core.$strip>;
|
|
235
281
|
type Config = z.infer<typeof Config>;
|
|
236
282
|
//#endregion
|
|
237
|
-
export {
|
|
283
|
+
export { Message as a, Formatter as i, Config as n, Transformer as o, DeclaredMessage as r, Bucket as t };
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import picomatch from "picomatch";
|
|
2
2
|
import * as z from "zod";
|
|
3
|
-
|
|
4
3
|
//#region src/shapes.d.ts
|
|
5
4
|
declare const Message: z.ZodObject<{
|
|
6
5
|
message: z.ZodString;
|
|
@@ -29,10 +28,26 @@ declare const Transformer: z.ZodObject<{
|
|
|
29
28
|
transform: z.ZodCustom<(code: string, id: string) => string, (code: string, id: string) => string>;
|
|
30
29
|
}, z.core.$strip>;
|
|
31
30
|
type Transformer = z.infer<typeof Transformer>;
|
|
31
|
+
/**
|
|
32
|
+
* A message declared in the config rather than found in source. The shorthand
|
|
33
|
+
* is the source string; the object form adds the metadata a descriptor would
|
|
34
|
+
* otherwise carry.
|
|
35
|
+
*/
|
|
36
|
+
declare const DeclaredMessage: z.ZodUnion<[z.ZodString, z.ZodObject<{
|
|
37
|
+
message: z.ZodString;
|
|
38
|
+
context: z.ZodOptional<z.ZodString>;
|
|
39
|
+
comments: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
40
|
+
}, z.core.$strip>]>;
|
|
41
|
+
type DeclaredMessage = z.infer<typeof DeclaredMessage>;
|
|
32
42
|
declare const Bucket: z.ZodPipe<z.ZodObject<{
|
|
33
43
|
include: z.ZodArray<z.ZodString>;
|
|
34
44
|
exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
35
45
|
output: z.ZodTemplateLiteral<`${string}{locale}${string}.{extension}`>;
|
|
46
|
+
messages: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodString, z.ZodObject<{
|
|
47
|
+
message: z.ZodString;
|
|
48
|
+
context: z.ZodOptional<z.ZodString>;
|
|
49
|
+
comments: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
50
|
+
}, z.core.$strip>]>>>;
|
|
36
51
|
formatter: z.ZodObject<{
|
|
37
52
|
extension: z.ZodTemplateLiteral<`.${string}`>;
|
|
38
53
|
parse: z.ZodCustom<(content: string) => Message[], (content: string) => Message[]>;
|
|
@@ -77,6 +92,14 @@ declare const Bucket: z.ZodPipe<z.ZodObject<{
|
|
|
77
92
|
transform: (code: string, id: string) => string;
|
|
78
93
|
}[]>>;
|
|
79
94
|
}, z.core.$strip>, z.ZodTransform<{
|
|
95
|
+
messages: {
|
|
96
|
+
message: string;
|
|
97
|
+
comments: string[];
|
|
98
|
+
references: string[];
|
|
99
|
+
translation?: string | undefined;
|
|
100
|
+
id?: string | undefined;
|
|
101
|
+
context?: string | undefined;
|
|
102
|
+
}[];
|
|
80
103
|
match: (id: string) => boolean;
|
|
81
104
|
output: `${string}{locale}${string}.{extension}` & {
|
|
82
105
|
match: picomatch.Matcher;
|
|
@@ -127,6 +150,11 @@ declare const Bucket: z.ZodPipe<z.ZodObject<{
|
|
|
127
150
|
transform: (code: string, id: string) => string;
|
|
128
151
|
};
|
|
129
152
|
exclude?: string[] | undefined;
|
|
153
|
+
messages?: Record<string, string | {
|
|
154
|
+
message: string;
|
|
155
|
+
context?: string | undefined;
|
|
156
|
+
comments?: string[] | undefined;
|
|
157
|
+
}> | undefined;
|
|
130
158
|
}>>;
|
|
131
159
|
type Bucket = z.infer<typeof Bucket>;
|
|
132
160
|
declare const Config: z.ZodObject<{
|
|
@@ -136,6 +164,11 @@ declare const Config: z.ZodObject<{
|
|
|
136
164
|
include: z.ZodArray<z.ZodString>;
|
|
137
165
|
exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
138
166
|
output: z.ZodTemplateLiteral<`${string}{locale}${string}.{extension}`>;
|
|
167
|
+
messages: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodString, z.ZodObject<{
|
|
168
|
+
message: z.ZodString;
|
|
169
|
+
context: z.ZodOptional<z.ZodString>;
|
|
170
|
+
comments: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
171
|
+
}, z.core.$strip>]>>>;
|
|
139
172
|
formatter: z.ZodObject<{
|
|
140
173
|
extension: z.ZodTemplateLiteral<`.${string}`>;
|
|
141
174
|
parse: z.ZodCustom<(content: string) => Message[], (content: string) => Message[]>;
|
|
@@ -180,6 +213,14 @@ declare const Config: z.ZodObject<{
|
|
|
180
213
|
transform: (code: string, id: string) => string;
|
|
181
214
|
}[]>>;
|
|
182
215
|
}, z.core.$strip>, z.ZodTransform<{
|
|
216
|
+
messages: {
|
|
217
|
+
message: string;
|
|
218
|
+
comments: string[];
|
|
219
|
+
references: string[];
|
|
220
|
+
translation?: string | undefined;
|
|
221
|
+
id?: string | undefined;
|
|
222
|
+
context?: string | undefined;
|
|
223
|
+
}[];
|
|
183
224
|
match: (id: string) => boolean;
|
|
184
225
|
output: `${string}{locale}${string}.{extension}` & {
|
|
185
226
|
match: picomatch.Matcher;
|
|
@@ -230,8 +271,13 @@ declare const Config: z.ZodObject<{
|
|
|
230
271
|
transform: (code: string, id: string) => string;
|
|
231
272
|
};
|
|
232
273
|
exclude?: string[] | undefined;
|
|
274
|
+
messages?: Record<string, string | {
|
|
275
|
+
message: string;
|
|
276
|
+
context?: string | undefined;
|
|
277
|
+
comments?: string[] | undefined;
|
|
278
|
+
}> | undefined;
|
|
233
279
|
}>>>;
|
|
234
280
|
}, z.core.$strip>;
|
|
235
281
|
type Config = z.infer<typeof Config>;
|
|
236
282
|
//#endregion
|
|
237
|
-
export {
|
|
283
|
+
export { Message as a, Formatter as i, Config as n, Transformer as o, DeclaredMessage as r, Bucket as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as generateHash } from "./hash-
|
|
1
|
+
import { t as generateHash } from "./hash-DvzpieJD.mjs";
|
|
2
2
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
3
|
import { dirname, parse, resolve } from "node:path";
|
|
4
4
|
//#region src/features/catalogue/merge.ts
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
require("./
|
|
2
|
-
const require_hash = require("./hash-8It7TJpB.cjs");
|
|
1
|
+
const require_hash = require("./hash-51ce8YiG.cjs");
|
|
3
2
|
let node_fs_promises = require("node:fs/promises");
|
|
4
3
|
let node_path = require("node:path");
|
|
5
4
|
//#region src/features/catalogue/merge.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saykit/config",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "CLI and configuration tooling for saykit",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -73,22 +73,17 @@
|
|
|
73
73
|
"provenance": true
|
|
74
74
|
},
|
|
75
75
|
"dependencies": {
|
|
76
|
-
"@commander-js/extra-typings": "^
|
|
77
|
-
"commander": "^
|
|
78
|
-
"js-sha256": "^0.
|
|
76
|
+
"@commander-js/extra-typings": "^15.0.0",
|
|
77
|
+
"commander": "^15.0.0",
|
|
78
|
+
"js-sha256": "^0.12.0",
|
|
79
79
|
"picomatch": "^4.0.5",
|
|
80
80
|
"zod": "^4.4.3"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
83
|
"@types/picomatch": "^4.0.3"
|
|
84
84
|
},
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
},
|
|
88
|
-
"peerDependenciesMeta": {
|
|
89
|
-
"typescript": {
|
|
90
|
-
"optional": true
|
|
91
|
-
}
|
|
85
|
+
"engines": {
|
|
86
|
+
"node": ">=22.18"
|
|
92
87
|
},
|
|
93
88
|
"scripts": {
|
|
94
89
|
"check": "tsc --noEmit",
|
package/dist/loader-B25O-vF6.cjs
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
require("./index.cjs");
|
|
2
|
-
let node_path = require("node:path");
|
|
3
|
-
let node_fs = require("node:fs");
|
|
4
|
-
let node_crypto = require("node:crypto");
|
|
5
|
-
let node_module = require("node:module");
|
|
6
|
-
let node_os = require("node:os");
|
|
7
|
-
//#region src/features/loader/files.ts
|
|
8
|
-
const SUPPORTED_CONFIG_FILES = [
|
|
9
|
-
"saykit.config.js",
|
|
10
|
-
"saykit.config.cjs",
|
|
11
|
-
"saykit.config.mjs",
|
|
12
|
-
"saykit.config.ts",
|
|
13
|
-
"saykit.config.mts",
|
|
14
|
-
"saykit.config.cts"
|
|
15
|
-
];
|
|
16
|
-
function getConfigFileCandidates(name) {
|
|
17
|
-
return SUPPORTED_CONFIG_FILES.map((file) => file.replace("saykit", name));
|
|
18
|
-
}
|
|
19
|
-
function findConfigFile(moduleName, projectDir) {
|
|
20
|
-
for (const fileName of getConfigFileCandidates(moduleName)) {
|
|
21
|
-
const id = (0, node_path.join)(projectDir, fileName);
|
|
22
|
-
if ((0, node_fs.existsSync)(id)) return { id };
|
|
23
|
-
}
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
//#endregion
|
|
27
|
-
//#region src/features/loader/module.ts
|
|
28
|
-
function findNearestTsConfig(fromPath) {
|
|
29
|
-
let dir = (0, node_path.dirname)(fromPath);
|
|
30
|
-
const { root } = (0, node_path.parse)(dir);
|
|
31
|
-
while (true) {
|
|
32
|
-
const candidate = (0, node_path.join)(dir, "tsconfig.json");
|
|
33
|
-
if ((0, node_fs.existsSync)(candidate)) return candidate;
|
|
34
|
-
if (dir === root) return null;
|
|
35
|
-
dir = (0, node_path.dirname)(dir);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
function findCacheDir(fromPath) {
|
|
39
|
-
let dir = (0, node_path.dirname)(fromPath);
|
|
40
|
-
const { root } = (0, node_path.parse)(dir);
|
|
41
|
-
while (true) {
|
|
42
|
-
const nm = (0, node_path.join)(dir, "node_modules");
|
|
43
|
-
if ((0, node_fs.existsSync)(nm)) return (0, node_path.join)(nm, ".cache", "saykit", "config");
|
|
44
|
-
if (dir === root) return (0, node_path.join)((0, node_os.tmpdir)(), "saykit", "config");
|
|
45
|
-
dir = (0, node_path.dirname)(dir);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
function transpile(path, tsConfigPath, require) {
|
|
49
|
-
const ts = require("typescript");
|
|
50
|
-
const { config: tsConfig, error } = tsConfigPath ? ts.readConfigFile(tsConfigPath, ts.sys.readFile) : {
|
|
51
|
-
config: {},
|
|
52
|
-
error: null
|
|
53
|
-
};
|
|
54
|
-
if (error) throw error;
|
|
55
|
-
tsConfig.compilerOptions = {
|
|
56
|
-
...tsConfig.compilerOptions,
|
|
57
|
-
allowJs: true,
|
|
58
|
-
esModuleInterop: true,
|
|
59
|
-
module: ts.ModuleKind.CommonJS,
|
|
60
|
-
moduleResolution: ts.ModuleResolutionKind.NodeJs,
|
|
61
|
-
target: ts.ScriptTarget.ES2022,
|
|
62
|
-
noEmit: false
|
|
63
|
-
};
|
|
64
|
-
return ts.transpileModule((0, node_fs.readFileSync)(path, "utf8"), tsConfig).outputText;
|
|
65
|
-
}
|
|
66
|
-
function loadWithCache(path) {
|
|
67
|
-
const require = (0, node_module.createRequire)(path);
|
|
68
|
-
const mtimeMs = (0, node_fs.statSync)(path).mtimeMs;
|
|
69
|
-
const tsConfigPath = findNearestTsConfig(path);
|
|
70
|
-
const tsConfigMtimeMs = tsConfigPath ? (0, node_fs.statSync)(tsConfigPath).mtimeMs : 0;
|
|
71
|
-
const hash = (0, node_crypto.createHash)("sha1").update(`${path}\0${tsConfigPath ?? ""}\0${tsConfigMtimeMs}`).digest("hex").slice(0, 16);
|
|
72
|
-
const cacheDir = findCacheDir(path);
|
|
73
|
-
const cachePath = (0, node_path.join)(cacheDir, `${hash}.${mtimeMs}.cjs`);
|
|
74
|
-
try {
|
|
75
|
-
if (!(0, node_fs.existsSync)(cachePath)) {
|
|
76
|
-
(0, node_fs.mkdirSync)(cacheDir, { recursive: true });
|
|
77
|
-
(0, node_fs.writeFileSync)(cachePath, transpile(path, tsConfigPath, require));
|
|
78
|
-
if ((0, node_fs.existsSync)(cacheDir)) {
|
|
79
|
-
for (const entry of (0, node_fs.readdirSync)(cacheDir)) if (entry.startsWith(`${hash}.`) && entry !== `${hash}.${mtimeMs}.cjs`) try {
|
|
80
|
-
(0, node_fs.unlinkSync)((0, node_path.join)(cacheDir, entry));
|
|
81
|
-
} catch {}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
const resolved = require.resolve(cachePath);
|
|
85
|
-
delete require.cache[resolved];
|
|
86
|
-
const module = require(cachePath);
|
|
87
|
-
delete require.cache[resolved];
|
|
88
|
-
return module?.default ?? module;
|
|
89
|
-
} catch (error) {
|
|
90
|
-
throw new Error("Failed to import module", { cause: error });
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
const js = (path) => loadWithCache(path);
|
|
94
|
-
const ts = (path) => loadWithCache(path);
|
|
95
|
-
const configLoaders = Object.freeze({
|
|
96
|
-
".js": js,
|
|
97
|
-
".mjs": js,
|
|
98
|
-
".cjs": js,
|
|
99
|
-
".ts": ts,
|
|
100
|
-
".mts": ts,
|
|
101
|
-
".cts": ts
|
|
102
|
-
});
|
|
103
|
-
//#endregion
|
|
104
|
-
//#region src/features/loader/resolve.ts
|
|
105
|
-
function resolveConfig(name = "saykit") {
|
|
106
|
-
const file = findConfigFile(name, process.cwd());
|
|
107
|
-
if (!file) throw new Error(`Could not find config file for "${name}"`);
|
|
108
|
-
const ext = (0, node_path.extname)(file.id).toLowerCase();
|
|
109
|
-
const load = ext in configLoaders ? configLoaders[ext] : null;
|
|
110
|
-
if (!load) throw new Error(`Unsupported config file type "${ext}" for "${name}"`);
|
|
111
|
-
const config = load(file.id);
|
|
112
|
-
if (!config || typeof config !== "object") throw new Error(`Invalid config file for "${name}"`);
|
|
113
|
-
return config;
|
|
114
|
-
}
|
|
115
|
-
//#endregion
|
|
116
|
-
Object.defineProperty(exports, "resolveConfig", {
|
|
117
|
-
enumerable: true,
|
|
118
|
-
get: function() {
|
|
119
|
-
return resolveConfig;
|
|
120
|
-
}
|
|
121
|
-
});
|
package/dist/loader-C2eolE_1.mjs
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { createRequire } from "node:module";
|
|
2
|
-
import { dirname, extname, join, parse } from "node:path";
|
|
3
|
-
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
4
|
-
import { createHash } from "node:crypto";
|
|
5
|
-
import { tmpdir } from "node:os";
|
|
6
|
-
//#region src/features/loader/files.ts
|
|
7
|
-
const SUPPORTED_CONFIG_FILES = [
|
|
8
|
-
"saykit.config.js",
|
|
9
|
-
"saykit.config.cjs",
|
|
10
|
-
"saykit.config.mjs",
|
|
11
|
-
"saykit.config.ts",
|
|
12
|
-
"saykit.config.mts",
|
|
13
|
-
"saykit.config.cts"
|
|
14
|
-
];
|
|
15
|
-
function getConfigFileCandidates(name) {
|
|
16
|
-
return SUPPORTED_CONFIG_FILES.map((file) => file.replace("saykit", name));
|
|
17
|
-
}
|
|
18
|
-
function findConfigFile(moduleName, projectDir) {
|
|
19
|
-
for (const fileName of getConfigFileCandidates(moduleName)) {
|
|
20
|
-
const id = join(projectDir, fileName);
|
|
21
|
-
if (existsSync(id)) return { id };
|
|
22
|
-
}
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
|
-
//#endregion
|
|
26
|
-
//#region src/features/loader/module.ts
|
|
27
|
-
function findNearestTsConfig(fromPath) {
|
|
28
|
-
let dir = dirname(fromPath);
|
|
29
|
-
const { root } = parse(dir);
|
|
30
|
-
while (true) {
|
|
31
|
-
const candidate = join(dir, "tsconfig.json");
|
|
32
|
-
if (existsSync(candidate)) return candidate;
|
|
33
|
-
if (dir === root) return null;
|
|
34
|
-
dir = dirname(dir);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
function findCacheDir(fromPath) {
|
|
38
|
-
let dir = dirname(fromPath);
|
|
39
|
-
const { root } = parse(dir);
|
|
40
|
-
while (true) {
|
|
41
|
-
const nm = join(dir, "node_modules");
|
|
42
|
-
if (existsSync(nm)) return join(nm, ".cache", "saykit", "config");
|
|
43
|
-
if (dir === root) return join(tmpdir(), "saykit", "config");
|
|
44
|
-
dir = dirname(dir);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
function transpile(path, tsConfigPath, require) {
|
|
48
|
-
const ts = require("typescript");
|
|
49
|
-
const { config: tsConfig, error } = tsConfigPath ? ts.readConfigFile(tsConfigPath, ts.sys.readFile) : {
|
|
50
|
-
config: {},
|
|
51
|
-
error: null
|
|
52
|
-
};
|
|
53
|
-
if (error) throw error;
|
|
54
|
-
tsConfig.compilerOptions = {
|
|
55
|
-
...tsConfig.compilerOptions,
|
|
56
|
-
allowJs: true,
|
|
57
|
-
esModuleInterop: true,
|
|
58
|
-
module: ts.ModuleKind.CommonJS,
|
|
59
|
-
moduleResolution: ts.ModuleResolutionKind.NodeJs,
|
|
60
|
-
target: ts.ScriptTarget.ES2022,
|
|
61
|
-
noEmit: false
|
|
62
|
-
};
|
|
63
|
-
return ts.transpileModule(readFileSync(path, "utf8"), tsConfig).outputText;
|
|
64
|
-
}
|
|
65
|
-
function loadWithCache(path) {
|
|
66
|
-
const require = createRequire(path);
|
|
67
|
-
const mtimeMs = statSync(path).mtimeMs;
|
|
68
|
-
const tsConfigPath = findNearestTsConfig(path);
|
|
69
|
-
const tsConfigMtimeMs = tsConfigPath ? statSync(tsConfigPath).mtimeMs : 0;
|
|
70
|
-
const hash = createHash("sha1").update(`${path}\0${tsConfigPath ?? ""}\0${tsConfigMtimeMs}`).digest("hex").slice(0, 16);
|
|
71
|
-
const cacheDir = findCacheDir(path);
|
|
72
|
-
const cachePath = join(cacheDir, `${hash}.${mtimeMs}.cjs`);
|
|
73
|
-
try {
|
|
74
|
-
if (!existsSync(cachePath)) {
|
|
75
|
-
mkdirSync(cacheDir, { recursive: true });
|
|
76
|
-
writeFileSync(cachePath, transpile(path, tsConfigPath, require));
|
|
77
|
-
if (existsSync(cacheDir)) {
|
|
78
|
-
for (const entry of readdirSync(cacheDir)) if (entry.startsWith(`${hash}.`) && entry !== `${hash}.${mtimeMs}.cjs`) try {
|
|
79
|
-
unlinkSync(join(cacheDir, entry));
|
|
80
|
-
} catch {}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
const resolved = require.resolve(cachePath);
|
|
84
|
-
delete require.cache[resolved];
|
|
85
|
-
const module = require(cachePath);
|
|
86
|
-
delete require.cache[resolved];
|
|
87
|
-
return module?.default ?? module;
|
|
88
|
-
} catch (error) {
|
|
89
|
-
throw new Error("Failed to import module", { cause: error });
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
const js = (path) => loadWithCache(path);
|
|
93
|
-
const ts = (path) => loadWithCache(path);
|
|
94
|
-
const configLoaders = Object.freeze({
|
|
95
|
-
".js": js,
|
|
96
|
-
".mjs": js,
|
|
97
|
-
".cjs": js,
|
|
98
|
-
".ts": ts,
|
|
99
|
-
".mts": ts,
|
|
100
|
-
".cts": ts
|
|
101
|
-
});
|
|
102
|
-
//#endregion
|
|
103
|
-
//#region src/features/loader/resolve.ts
|
|
104
|
-
function resolveConfig(name = "saykit") {
|
|
105
|
-
const file = findConfigFile(name, process.cwd());
|
|
106
|
-
if (!file) throw new Error(`Could not find config file for "${name}"`);
|
|
107
|
-
const ext = extname(file.id).toLowerCase();
|
|
108
|
-
const load = ext in configLoaders ? configLoaders[ext] : null;
|
|
109
|
-
if (!load) throw new Error(`Unsupported config file type "${ext}" for "${name}"`);
|
|
110
|
-
const config = load(file.id);
|
|
111
|
-
if (!config || typeof config !== "object") throw new Error(`Invalid config file for "${name}"`);
|
|
112
|
-
return config;
|
|
113
|
-
}
|
|
114
|
-
//#endregion
|
|
115
|
-
export { resolveConfig as t };
|
|
File without changes
|