@x18n/node 0.0.3 → 0.0.5
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/index.d.mts +14 -1
- package/dist/index.mjs +365 -6
- package/package.json +9 -9
package/dist/index.d.mts
CHANGED
|
@@ -13,6 +13,19 @@ export declare function loadYamlPlugin(file: string): Promise<Plugin | Preset>;
|
|
|
13
13
|
/** Resolves a plugin specifier relative to the config directory: a YAML file, a module path, or a package name. */
|
|
14
14
|
export declare function createPluginLoader(dir: string): (specifier: string, options: JsonObject | undefined) => Promise<Plugin | Preset>;
|
|
15
15
|
//#endregion
|
|
16
|
+
//#region src/git-history.d.ts
|
|
17
|
+
interface GitHistoryOptions {
|
|
18
|
+
/** Most commits to read, newest first. Default: every commit. */
|
|
19
|
+
readonly maxDepth?: number | undefined;
|
|
20
|
+
/** Only commits after this time: a `git log --since` value such as `1 year ago`, or a Date. */
|
|
21
|
+
readonly since?: string | Date | undefined;
|
|
22
|
+
}
|
|
23
|
+
declare module "@x18n/core" {
|
|
24
|
+
interface HistoryConfigs {
|
|
25
|
+
readonly git?: false | GitHistoryOptions;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
16
29
|
//#region src/host.d.ts
|
|
17
30
|
interface NodeHostOptions {
|
|
18
31
|
/** Directory of the persistent cache, or false to disable it. Default `node_modules/.cache/x18n` under the root. */
|
|
@@ -81,4 +94,4 @@ interface MigrateOptions {
|
|
|
81
94
|
/** Converts i18n-ally settings, custom framework and reviews into x18n files. Never deletes i18n-ally files. */
|
|
82
95
|
export declare function migrateI18nAlly(root: string, options?: MigrateOptions): Promise<MigrationResult>;
|
|
83
96
|
//#endregion
|
|
84
|
-
export type { LoadOptions, LoadedProject, MigrateOptions, MigrationFile, MigrationResult, NodeHost, NodeHostOptions, Workspace };
|
|
97
|
+
export type { GitHistoryOptions, LoadOptions, LoadedProject, MigrateOptions, MigrationFile, MigrationResult, NodeHost, NodeHostOptions, Workspace };
|
package/dist/index.mjs
CHANGED
|
@@ -12,6 +12,8 @@ import process from "node:process";
|
|
|
12
12
|
import { watch } from "chokidar";
|
|
13
13
|
import ignore from "ignore";
|
|
14
14
|
import { createBuiltins } from "@x18n/builtins";
|
|
15
|
+
import { Buffer } from "node:buffer";
|
|
16
|
+
import { execFile, spawn } from "node:child_process";
|
|
15
17
|
import { applyEdits, modify, parse as parse$1 } from "jsonc-parser";
|
|
16
18
|
//#region src/config.ts
|
|
17
19
|
const configFileNames = [
|
|
@@ -41,17 +43,22 @@ function findConfigUpward(cwd) {
|
|
|
41
43
|
dir = parent;
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
function resolveOwn(specifier) {
|
|
47
|
+
try {
|
|
48
|
+
return fileURLToPath(import.meta.resolve(specifier));
|
|
49
|
+
} catch {}
|
|
50
|
+
}
|
|
51
|
+
const core = resolveOwn("@x18n/core");
|
|
52
|
+
const presets = resolveOwn("@x18n/builtins/presets");
|
|
53
|
+
const jiti = createJiti(import.meta.url ?? pathToFileURL(__filename).href, {
|
|
47
54
|
moduleCache: false,
|
|
48
55
|
interopDefault: true,
|
|
49
|
-
alias: {
|
|
56
|
+
alias: core && presets ? {
|
|
50
57
|
"@x18n/core": core,
|
|
51
58
|
"@x18n/cli/presets": presets,
|
|
52
59
|
"@x18n/cli": core,
|
|
53
60
|
"@x18n/builtins/presets": presets
|
|
54
|
-
}
|
|
61
|
+
} : {}
|
|
55
62
|
});
|
|
56
63
|
/** Imports a JS or TS module (config, plugin, executed resource). */
|
|
57
64
|
async function importModule(file) {
|
|
@@ -284,6 +291,354 @@ function createNodeHost(root, options = {}) {
|
|
|
284
291
|
};
|
|
285
292
|
}
|
|
286
293
|
//#endregion
|
|
294
|
+
//#region src/git-history.ts
|
|
295
|
+
const noBlob = /^0+$/;
|
|
296
|
+
function git(cwd, args) {
|
|
297
|
+
return new Promise((resolve, reject) => {
|
|
298
|
+
execFile("git", [
|
|
299
|
+
"-c",
|
|
300
|
+
"core.quotePath=false",
|
|
301
|
+
...args
|
|
302
|
+
], {
|
|
303
|
+
cwd,
|
|
304
|
+
maxBuffer: 1024 ** 3,
|
|
305
|
+
encoding: "utf8"
|
|
306
|
+
}, (error, stdout) => {
|
|
307
|
+
if (error) reject(error);
|
|
308
|
+
else resolve(stdout);
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
/** Blob texts by sha, through one `git cat-file --batch`. */
|
|
313
|
+
function readBlobs(cwd, shas) {
|
|
314
|
+
return new Promise((resolve, reject) => {
|
|
315
|
+
const child = spawn("git", ["cat-file", "--batch"], { cwd });
|
|
316
|
+
const chunks = [];
|
|
317
|
+
child.stdout.on("data", (chunk) => chunks.push(chunk));
|
|
318
|
+
child.on("error", reject);
|
|
319
|
+
child.on("close", () => {
|
|
320
|
+
const data = Buffer.concat(chunks);
|
|
321
|
+
const out = /* @__PURE__ */ new Map();
|
|
322
|
+
let position = 0;
|
|
323
|
+
while (position < data.length) {
|
|
324
|
+
const end = data.indexOf(10, position);
|
|
325
|
+
const [sha, type, size] = data.subarray(position, end).toString("utf8").split(" ");
|
|
326
|
+
position = end + 1;
|
|
327
|
+
if (type !== "blob") continue;
|
|
328
|
+
out.set(sha, data.subarray(position, position + Number(size)).toString("utf8"));
|
|
329
|
+
position += Number(size) + 1;
|
|
330
|
+
}
|
|
331
|
+
resolve(out);
|
|
332
|
+
});
|
|
333
|
+
child.stdin.end(shas.length ? `${shas.join("\n")}\n` : "");
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
/** The path a file added in `commit` was renamed from, with its blob. */
|
|
337
|
+
async function renamedFrom(top, commit, path) {
|
|
338
|
+
const out = await git(top, [
|
|
339
|
+
"diff-tree",
|
|
340
|
+
"-r",
|
|
341
|
+
"-M",
|
|
342
|
+
"--raw",
|
|
343
|
+
"--no-abbrev",
|
|
344
|
+
"--no-commit-id",
|
|
345
|
+
commit
|
|
346
|
+
]);
|
|
347
|
+
for (const line of out.split("\n")) {
|
|
348
|
+
const [meta, from, to] = line.split(" ");
|
|
349
|
+
if (to === path && meta?.split(" ")[4]?.startsWith("R")) return {
|
|
350
|
+
path: from,
|
|
351
|
+
blob: meta.split(" ")[2]
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
/** Parses `git log --raw --format=%x01%H%x00%ct%x00%an`. */
|
|
356
|
+
function parseLog(out) {
|
|
357
|
+
return out.split("").slice(1).map((chunk) => {
|
|
358
|
+
const [header = "", ...lines] = chunk.split("\n");
|
|
359
|
+
const [sha = "", time, author = ""] = header.split("\0");
|
|
360
|
+
const files = lines.filter((line) => line.startsWith(":")).map((line) => {
|
|
361
|
+
const [meta = "", ...paths] = line.split(" ");
|
|
362
|
+
const [, , before = "", after = "", status = ""] = meta.split(" ");
|
|
363
|
+
return {
|
|
364
|
+
path: paths.at(-1) ?? "",
|
|
365
|
+
status,
|
|
366
|
+
before: noBlob.test(before) ? void 0 : before,
|
|
367
|
+
after: noBlob.test(after) ? void 0 : after
|
|
368
|
+
};
|
|
369
|
+
});
|
|
370
|
+
return {
|
|
371
|
+
sha,
|
|
372
|
+
at: Number(time) * 1e3,
|
|
373
|
+
author,
|
|
374
|
+
files
|
|
375
|
+
};
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
async function collectCommits(input) {
|
|
379
|
+
const commits = /* @__PURE__ */ new Map();
|
|
380
|
+
const queue = [{
|
|
381
|
+
from: input.head,
|
|
382
|
+
paths: input.resources
|
|
383
|
+
}];
|
|
384
|
+
for (let item = queue.shift(); item; item = queue.shift()) {
|
|
385
|
+
const out = await git(input.top, [
|
|
386
|
+
"log",
|
|
387
|
+
item.from,
|
|
388
|
+
...input.base ? [`^${input.base}`] : [],
|
|
389
|
+
"--no-merges",
|
|
390
|
+
"--raw",
|
|
391
|
+
"--no-abbrev",
|
|
392
|
+
"--format=%x01%H%x00%ct%x00%an",
|
|
393
|
+
...input.window,
|
|
394
|
+
"--",
|
|
395
|
+
...[...item.paths.keys()].map((path) => `:(literal)${path}`)
|
|
396
|
+
]);
|
|
397
|
+
for (const entry of parseLog(out)) {
|
|
398
|
+
const commit = commits.get(entry.sha) ?? {
|
|
399
|
+
at: entry.at,
|
|
400
|
+
author: entry.author,
|
|
401
|
+
files: []
|
|
402
|
+
};
|
|
403
|
+
commits.set(entry.sha, commit);
|
|
404
|
+
for (const file of entry.files) {
|
|
405
|
+
const resource = item.paths.get(file.path);
|
|
406
|
+
if (!resource) continue;
|
|
407
|
+
const renamed = file.status === "A" ? await renamedFrom(input.top, entry.sha, file.path) : void 0;
|
|
408
|
+
if (renamed) queue.push({
|
|
409
|
+
from: `${entry.sha}^`,
|
|
410
|
+
paths: /* @__PURE__ */ new Map([[renamed.path, resource]])
|
|
411
|
+
});
|
|
412
|
+
commit.files.push({
|
|
413
|
+
resource,
|
|
414
|
+
before: renamed?.blob ?? file.before,
|
|
415
|
+
after: file.after
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
return commits;
|
|
421
|
+
}
|
|
422
|
+
/** Message changes per key and locale: in each commit, the messages of a locale's changed files before and after. */
|
|
423
|
+
async function walk(input) {
|
|
424
|
+
const commits = await collectCommits(input);
|
|
425
|
+
const shas = new Set([...commits.values()].flatMap((commit) => commit.files.flatMap((file) => [file.before, file.after].filter((sha) => sha !== void 0))));
|
|
426
|
+
const blobs = await readBlobs(input.top, [...shas]);
|
|
427
|
+
const parsed = /* @__PURE__ */ new Map();
|
|
428
|
+
const messagesOf = (resource, sha) => {
|
|
429
|
+
if (sha === void 0) return /* @__PURE__ */ new Map();
|
|
430
|
+
const id = `${resource.id}\0${sha}`;
|
|
431
|
+
if (!parsed.has(id)) {
|
|
432
|
+
const text = blobs.get(sha);
|
|
433
|
+
parsed.set(id, text === void 0 ? void 0 : input.ctx.messagesIn(resource, text));
|
|
434
|
+
}
|
|
435
|
+
return parsed.get(id);
|
|
436
|
+
};
|
|
437
|
+
const changes = /* @__PURE__ */ new Map();
|
|
438
|
+
for (const [sha, commit] of commits) {
|
|
439
|
+
const byLocale = Map.groupBy(commit.files, (file) => file.resource.locale);
|
|
440
|
+
for (const [locale, files] of byLocale) {
|
|
441
|
+
const before = /* @__PURE__ */ new Map();
|
|
442
|
+
const after = /* @__PURE__ */ new Map();
|
|
443
|
+
for (const file of files) {
|
|
444
|
+
const old = messagesOf(file.resource, file.before);
|
|
445
|
+
const next = messagesOf(file.resource, file.after);
|
|
446
|
+
if (!old || !next) continue;
|
|
447
|
+
old.forEach((value, key) => before.has(key) || before.set(key, value));
|
|
448
|
+
next.forEach((value, key) => after.has(key) || after.set(key, value));
|
|
449
|
+
}
|
|
450
|
+
for (const [key, value] of after) {
|
|
451
|
+
if (before.has(key) && before.get(key) === value) continue;
|
|
452
|
+
const byKey = changes.get(key) ?? /* @__PURE__ */ new Map();
|
|
453
|
+
changes.set(key, byKey);
|
|
454
|
+
byKey.set(locale, [...byKey.get(locale) ?? [], [
|
|
455
|
+
commit.at,
|
|
456
|
+
sha,
|
|
457
|
+
commit.author,
|
|
458
|
+
value
|
|
459
|
+
]]);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
for (const byKey of changes.values()) for (const list of byKey.values()) list.sort((a, b) => b[0] - a[0]);
|
|
464
|
+
return changes;
|
|
465
|
+
}
|
|
466
|
+
/** Messages at HEAD per locale, to tell uncommitted edits. */
|
|
467
|
+
async function headValues(ctx, top, resources) {
|
|
468
|
+
const files = (await git(top, [
|
|
469
|
+
"ls-tree",
|
|
470
|
+
"-r",
|
|
471
|
+
"HEAD",
|
|
472
|
+
"--",
|
|
473
|
+
...resources.keys()
|
|
474
|
+
])).split("\n").flatMap((line) => {
|
|
475
|
+
const [meta = "", path = ""] = line.split(" ");
|
|
476
|
+
const resource = resources.get(path);
|
|
477
|
+
return resource ? [{
|
|
478
|
+
resource,
|
|
479
|
+
sha: meta.split(" ")[2]
|
|
480
|
+
}] : [];
|
|
481
|
+
});
|
|
482
|
+
const blobs = await readBlobs(top, files.map((file) => file.sha));
|
|
483
|
+
const values = /* @__PURE__ */ new Map();
|
|
484
|
+
for (const { resource, sha } of files) {
|
|
485
|
+
const byKey = values.get(resource.locale) ?? /* @__PURE__ */ new Map();
|
|
486
|
+
values.set(resource.locale, byKey);
|
|
487
|
+
const text = blobs.get(sha);
|
|
488
|
+
if (text !== void 0) ctx.messagesIn(resource, text)?.forEach((value, key) => byKey.has(key) || byKey.set(key, value));
|
|
489
|
+
}
|
|
490
|
+
return values;
|
|
491
|
+
}
|
|
492
|
+
function toHistory(changes, head) {
|
|
493
|
+
const latest = /* @__PURE__ */ new Map();
|
|
494
|
+
for (const [key, byLocale] of changes) {
|
|
495
|
+
const entries = /* @__PURE__ */ new Map();
|
|
496
|
+
latest.set(key, entries);
|
|
497
|
+
for (const [locale, [newest]] of byLocale) if (newest) {
|
|
498
|
+
const value = head.get(locale)?.get(key);
|
|
499
|
+
entries.set(locale, {
|
|
500
|
+
updatedAt: newest[0],
|
|
501
|
+
revision: newest[1],
|
|
502
|
+
author: newest[2],
|
|
503
|
+
value: value === void 0 ? newest[3] : value
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
return {
|
|
508
|
+
changes: latest,
|
|
509
|
+
valueAt: (key, locale, at) => changes.get(key)?.get(locale)?.find((change) => change[0] <= at)?.[3]
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
function fromWalked(walked) {
|
|
513
|
+
return new Map(walked.changes.map(([key, byLocale]) => [key, new Map(byLocale)]));
|
|
514
|
+
}
|
|
515
|
+
function toWalked(head, changes) {
|
|
516
|
+
return {
|
|
517
|
+
head,
|
|
518
|
+
changes: [...changes].map(([key, byLocale]) => [key, [...byLocale]])
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
/** Fresh changes first, so lists stay newest first. */
|
|
522
|
+
function mergeChanges(fresh, older) {
|
|
523
|
+
for (const [key, byLocale] of older) {
|
|
524
|
+
const target = fresh.get(key) ?? /* @__PURE__ */ new Map();
|
|
525
|
+
fresh.set(key, target);
|
|
526
|
+
for (const [locale, list] of byLocale) target.set(locale, [...target.get(locale) ?? [], ...list]);
|
|
527
|
+
}
|
|
528
|
+
return fresh;
|
|
529
|
+
}
|
|
530
|
+
function isNotInstalled(error) {
|
|
531
|
+
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
532
|
+
}
|
|
533
|
+
/** Reads when each message last changed from git: parsed messages per commit, so formatting, sorting and moves do not count. */
|
|
534
|
+
function gitHistory() {
|
|
535
|
+
const warned = /* @__PURE__ */ new Set();
|
|
536
|
+
const warnOnce = (ctx, message) => {
|
|
537
|
+
if (!warned.has(message)) {
|
|
538
|
+
warned.add(message);
|
|
539
|
+
ctx.host.logger?.warn(message);
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
async function load(ctx) {
|
|
543
|
+
const options = ctx.config.history === false ? false : ctx.config.history.git;
|
|
544
|
+
if (options === false) return void 0;
|
|
545
|
+
const run = (args) => git(ctx.host.root, args);
|
|
546
|
+
let top;
|
|
547
|
+
try {
|
|
548
|
+
top = (await run(["rev-parse", "--show-toplevel"])).trim();
|
|
549
|
+
} catch (error) {
|
|
550
|
+
if (isNotInstalled(error)) warnOnce(ctx, "git is not installed, so stale translations are not reported.");
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
if ((await run(["rev-parse", "--is-shallow-repository"])).trim() === "true") {
|
|
554
|
+
warnOnce(ctx, "The git clone is shallow, so stale translations are not reported. Fetch the full history (`fetch-depth: 0` in GitHub Actions).");
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
const head = (await run([
|
|
558
|
+
"rev-parse",
|
|
559
|
+
"--verify",
|
|
560
|
+
"--quiet",
|
|
561
|
+
"HEAD"
|
|
562
|
+
]).catch(() => "")).trim();
|
|
563
|
+
const prefix = (await run(["rev-parse", "--show-prefix"])).trim();
|
|
564
|
+
const resources = new Map(ctx.resources.filter((resource) => !resource.block).map((resource) => [`${prefix}${resource.path}`, resource]));
|
|
565
|
+
if (!head || resources.size === 0) return void 0;
|
|
566
|
+
const window = [...options?.maxDepth === void 0 ? [] : [`--max-count=${options.maxDepth}`], ...options?.since === void 0 ? [] : [`--since=${options.since instanceof Date ? options.since.toISOString() : options.since}`]];
|
|
567
|
+
const cache = window.length === 0 ? ctx.host.cache : void 0;
|
|
568
|
+
const signature = [
|
|
569
|
+
1,
|
|
570
|
+
[...resources].map(([path, r]) => [
|
|
571
|
+
path,
|
|
572
|
+
r.locale,
|
|
573
|
+
r.namespace,
|
|
574
|
+
r.format
|
|
575
|
+
]).sort(),
|
|
576
|
+
ctx.config.namespace,
|
|
577
|
+
ctx.config.keyStyle
|
|
578
|
+
];
|
|
579
|
+
const cacheKey = `git-history:${hashText(JSON.stringify(signature))}`;
|
|
580
|
+
const cachedText = await cache?.get(cacheKey);
|
|
581
|
+
const cached = cachedText === void 0 ? void 0 : JSON.parse(cachedText);
|
|
582
|
+
let changes;
|
|
583
|
+
if (cached?.head === head) changes = fromWalked(cached);
|
|
584
|
+
else {
|
|
585
|
+
const base = cached && await run([
|
|
586
|
+
"merge-base",
|
|
587
|
+
"--is-ancestor",
|
|
588
|
+
cached.head,
|
|
589
|
+
head
|
|
590
|
+
]).then(() => cached, () => void 0);
|
|
591
|
+
const fresh = await walk({
|
|
592
|
+
ctx,
|
|
593
|
+
top,
|
|
594
|
+
resources,
|
|
595
|
+
head,
|
|
596
|
+
base: base?.head,
|
|
597
|
+
window
|
|
598
|
+
});
|
|
599
|
+
changes = base ? mergeChanges(fresh, fromWalked(base)) : fresh;
|
|
600
|
+
await cache?.set(cacheKey, JSON.stringify(toWalked(head, changes)));
|
|
601
|
+
}
|
|
602
|
+
return toHistory(changes, await headValues(ctx, top, resources));
|
|
603
|
+
}
|
|
604
|
+
function watch$1(ctx, onChange) {
|
|
605
|
+
let watcher;
|
|
606
|
+
let timer;
|
|
607
|
+
let disposed = false;
|
|
608
|
+
const run = (args) => git(ctx.host.root, args);
|
|
609
|
+
Promise.all([run(["rev-parse", "--absolute-git-dir"]), run([
|
|
610
|
+
"rev-parse",
|
|
611
|
+
"--path-format=absolute",
|
|
612
|
+
"--git-common-dir"
|
|
613
|
+
])]).then(([dir, common]) => {
|
|
614
|
+
if (disposed) return;
|
|
615
|
+
watcher = watch([
|
|
616
|
+
join(dir.trim(), "HEAD"),
|
|
617
|
+
join(common.trim(), "refs/heads"),
|
|
618
|
+
join(common.trim(), "packed-refs")
|
|
619
|
+
], { ignoreInitial: true });
|
|
620
|
+
watcher.on("all", () => {
|
|
621
|
+
clearTimeout(timer);
|
|
622
|
+
timer = setTimeout(onChange, 100);
|
|
623
|
+
});
|
|
624
|
+
}, () => void 0);
|
|
625
|
+
return { dispose() {
|
|
626
|
+
disposed = true;
|
|
627
|
+
clearTimeout(timer);
|
|
628
|
+
watcher?.close();
|
|
629
|
+
} };
|
|
630
|
+
}
|
|
631
|
+
return {
|
|
632
|
+
name: "x18n:git-history",
|
|
633
|
+
runtime: "node",
|
|
634
|
+
histories: [{
|
|
635
|
+
id: "git",
|
|
636
|
+
load,
|
|
637
|
+
watch: watch$1
|
|
638
|
+
}]
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
//#endregion
|
|
287
642
|
//#region src/migrate.ts
|
|
288
643
|
const frameworkPresets = {
|
|
289
644
|
"vue": "vue-i18n",
|
|
@@ -799,8 +1154,12 @@ async function projectSpecs(rootConfigFile, cwd, upward) {
|
|
|
799
1154
|
async function loadWorkspace(options) {
|
|
800
1155
|
const configFile = options.configFile ? resolve(options.cwd, options.configFile) : options.upward === false ? findConfigFile(resolve(options.cwd)) : findConfigUpward(options.cwd);
|
|
801
1156
|
const { root, specs } = await projectSpecs(configFile, options.cwd, options.upward !== false);
|
|
802
|
-
const builtins = options.builtins ?? createBuiltins();
|
|
803
1157
|
const gitRoot = findGitRoot(root);
|
|
1158
|
+
const defaults = options.builtins ?? createBuiltins();
|
|
1159
|
+
const builtins = gitRoot ? {
|
|
1160
|
+
...defaults,
|
|
1161
|
+
plugins: [...defaults.plugins, gitHistory()]
|
|
1162
|
+
} : defaults;
|
|
804
1163
|
const loaded = [];
|
|
805
1164
|
for (const spec of specs) {
|
|
806
1165
|
const name = spec.config.name ?? (spec.root === root ? relative(dirname(root), root) : relative(root, spec.root)).replace(/\\/g, "/");
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@x18n/node",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.5",
|
|
5
5
|
"description": "Node.js host for x18n: file system access, config and plugin loading",
|
|
6
6
|
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
8
|
-
"homepage": "https://github.com/
|
|
8
|
+
"homepage": "https://github.com/x18n-dev/x18n#readme",
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
11
|
-
"url": "git+https://github.com/
|
|
11
|
+
"url": "git+https://github.com/x18n-dev/x18n.git",
|
|
12
12
|
"directory": "packages/node"
|
|
13
13
|
},
|
|
14
|
-
"bugs": "https://github.com/
|
|
14
|
+
"bugs": "https://github.com/x18n-dev/x18n/issues",
|
|
15
15
|
"sideEffects": false,
|
|
16
16
|
"exports": {
|
|
17
17
|
".": "./dist/index.mjs",
|
|
@@ -25,11 +25,11 @@
|
|
|
25
25
|
"node": ">=22"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@x18n/builtins": "0.0.
|
|
29
|
-
"@x18n/core": "0.0.
|
|
30
|
-
"chokidar": "^
|
|
31
|
-
"ignore": "^7.0.
|
|
32
|
-
"jiti": "^2.
|
|
28
|
+
"@x18n/builtins": "0.0.5",
|
|
29
|
+
"@x18n/core": "0.0.5",
|
|
30
|
+
"chokidar": "^6.0.0",
|
|
31
|
+
"ignore": "^7.0.13",
|
|
32
|
+
"jiti": "^2.7.0",
|
|
33
33
|
"jsonc-parser": "^3.3.1",
|
|
34
34
|
"tinyglobby": "^0.2.17",
|
|
35
35
|
"yaml": "^2.9.1"
|