@lunora/cli 1.0.0-alpha.9 → 1.0.0-alpha.90
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/LICENSE.md +6 -0
- package/__assets__/package-og.svg +1 -1
- package/dist/bin.mjs +1 -1
- package/dist/index.d.mts +358 -300
- package/dist/index.d.ts +358 -300
- package/dist/index.mjs +8 -9
- package/dist/packem_chunks/handler.mjs +15 -5
- package/dist/packem_chunks/handler10.mjs +8 -14
- package/dist/packem_chunks/handler11.mjs +20 -189
- package/dist/packem_chunks/handler12.mjs +176 -115
- package/dist/packem_chunks/handler13.mjs +118 -52
- package/dist/packem_chunks/handler14.mjs +50 -43
- package/dist/packem_chunks/handler15.mjs +48 -67
- package/dist/packem_chunks/handler16.mjs +94 -37
- package/dist/packem_chunks/handler17.mjs +39 -100
- package/dist/packem_chunks/handler18.mjs +87 -152
- package/dist/packem_chunks/handler19.mjs +148 -67
- package/dist/packem_chunks/handler2.mjs +6 -4
- package/dist/packem_chunks/handler20.mjs +77 -75
- package/dist/packem_chunks/handler21.mjs +71 -288
- package/dist/packem_chunks/handler3.mjs +8 -4
- package/dist/packem_chunks/handler4.mjs +2 -2
- package/dist/packem_chunks/handler5.mjs +7 -4
- package/dist/packem_chunks/handler6.mjs +10 -7
- package/dist/packem_chunks/handler7.mjs +2 -2
- package/dist/packem_chunks/handler8.mjs +1 -1
- package/dist/packem_chunks/handler9.mjs +330 -12
- package/dist/packem_chunks/planDevCommand.mjs +762 -81
- package/dist/packem_chunks/runCodegenCommand.mjs +5 -4
- package/dist/packem_chunks/runDeployCommand.mjs +137 -22
- package/dist/packem_chunks/runInitCommand.mjs +1648 -188
- package/dist/packem_chunks/runMigrateGenerateCommand.mjs +94 -47
- package/dist/packem_chunks/runResetCommand.mjs +2 -2
- package/dist/packem_chunks/runRpcCommand.mjs +3 -2
- package/dist/packem_shared/{COMMANDS-Dh0bSERi.mjs → COMMANDS-DZ0NnuqI.mjs} +103 -27
- package/dist/packem_shared/{DEFAULT_IMPORT_BATCH_SIZE-Ck-2bU08.mjs → DEFAULT_IMPORT_BATCH_SIZE-D0VOTerB.mjs} +7 -2
- package/dist/packem_shared/{api-spec-CtA6ilu4.mjs → api-spec-Bx0iKbxA.mjs} +3 -1
- package/dist/packem_shared/{buildRegistryIndex-BcYe607_.mjs → buildRegistryIndex-BS5ig822.mjs} +1 -1
- package/dist/packem_shared/codegen-error-DJG-ghs_.mjs +31 -0
- package/dist/packem_shared/{command-BDXcJCCJ.mjs → command-lYnl4QyF.mjs} +6 -1
- package/dist/packem_shared/{commands-CkkATMMx.mjs → commands-D5Yxt9VY.mjs} +199 -20
- package/dist/packem_shared/{createLogger-CHPNjFw2.mjs → createLogger-CIWSHrTL.mjs} +40 -8
- package/dist/packem_shared/{createRecordingSpawner-DxI3mebw.mjs → createRecordingSpawner-WuSn20kb.mjs} +23 -2
- package/dist/packem_shared/detect-package-manager-v4hHpQd0.mjs +62 -0
- package/dist/packem_shared/{insertSchemaExtension-BuzF6-t2.mjs → insertSchemaExtension-DAqbfr9Z.mjs} +15 -10
- package/dist/packem_shared/{open-url-Dfq6fAyT.mjs → open-url-4PBLY9X0.mjs} +3 -2
- package/dist/packem_shared/{output-format-7gyGR3h8.mjs → output-format-B4642rjE.mjs} +1 -1
- package/dist/packem_shared/{parseManifest--vZf2FY1.mjs → parseManifest-Dbp-Q2q3.mjs} +36 -9
- package/dist/packem_shared/prompt-cancelled-APzX1Im-.mjs +9 -0
- package/dist/packem_shared/runAddCommand-D1hgfqFQ.mjs +4 -0
- package/dist/packem_shared/{storage-Bjo35hPa.mjs → storage-BXU4ax4O.mjs} +1 -1
- package/dist/packem_shared/tui-prompts-BjEN8XgP.mjs +658 -0
- package/dist/packem_shared/wrangler-secrets-Coni-mER.mjs +49 -0
- package/package.json +17 -14
- package/skills/lunora-quickstart/SKILL.md +26 -5
- package/dist/packem_shared/detect-package-manager-DYp7n3mJ.mjs +0 -61
- package/dist/packem_shared/parseArgs-YXFuKdEk.mjs +0 -56
- package/dist/packem_shared/runAddCommand-DepS9W9W.mjs +0 -4
- package/dist/packem_shared/tui-prompts-CA9lngSS.mjs +0 -269
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { createLogger } from './createLogger-
|
|
1
|
+
import { createLogger } from './createLogger-CIWSHrTL.mjs';
|
|
2
|
+
import { P as PromptCancelledError, a as PROMPT_CANCEL_EXIT_CODE } from './prompt-cancelled-APzX1Im-.mjs';
|
|
2
3
|
|
|
3
4
|
const defineHandler = (body) => async (toolbox) => {
|
|
4
5
|
const logger = createLogger();
|
|
@@ -6,6 +7,10 @@ const defineHandler = (body) => async (toolbox) => {
|
|
|
6
7
|
const { code } = await body({ argument: toolbox.argument, cwd: toolbox.process.cwd, logger, options: toolbox.options });
|
|
7
8
|
toolbox.process.exit(code);
|
|
8
9
|
} catch (error) {
|
|
10
|
+
if (error instanceof PromptCancelledError) {
|
|
11
|
+
toolbox.process.exit(PROMPT_CANCEL_EXIT_CODE);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
9
14
|
logger.error(error instanceof Error ? error.message : String(error));
|
|
10
15
|
toolbox.process.exit(1);
|
|
11
16
|
}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { existsSync, readFileSync, writeFileSync, mkdirSync, mkdtempSync, rmSync } from 'node:fs';
|
|
2
|
-
import { dirname, join } from '@visulima/path';
|
|
3
|
-
import { DEV_VARS_FILE, parseDevVariableEntries } from '@lunora/config';
|
|
2
|
+
import { dirname, join, relative } from '@visulima/path';
|
|
3
|
+
import { DEV_VARS_FILE, parseDevVariableEntries, findWranglerFile, readWranglerJsonc } from '@lunora/config';
|
|
4
4
|
import { modify, applyEdits, parse } from 'jsonc-parser';
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
6
|
+
import { LunoraError } from '@lunora/errors';
|
|
7
|
+
import { b as tuiConfirm } from './tui-prompts-BjEN8XgP.mjs';
|
|
8
|
+
import { collectCatalog, buildRegistryIndex } from './buildRegistryIndex-BS5ig822.mjs';
|
|
9
|
+
import { insertSchemaExtension } from './insertSchemaExtension-DAqbfr9Z.mjs';
|
|
9
10
|
import { createHash } from 'node:crypto';
|
|
10
11
|
import { tmpdir } from 'node:os';
|
|
11
12
|
import { downloadTemplate } from 'giget';
|
|
12
|
-
import parseManifest from './parseManifest
|
|
13
|
+
import parseManifest from './parseManifest-Dbp-Q2q3.mjs';
|
|
13
14
|
|
|
14
15
|
const DEFAULT_SOURCE_REF_FALLBACK = "alpha";
|
|
15
16
|
const STABLE_BRANCH = "main";
|
|
@@ -54,17 +55,88 @@ const resolveVersionRef = (version) => {
|
|
|
54
55
|
const resolveSourceRef = (ref) => {
|
|
55
56
|
if (ref !== void 0 && ref.length > 0) {
|
|
56
57
|
if (!isSafeRef(ref)) {
|
|
57
|
-
throw new
|
|
58
|
+
throw new LunoraError("INTERNAL", `invalid --ref "${ref}" — a ref may contain letters, digits, ".", "_", "-", "/", "@" and must not contain "..".`);
|
|
58
59
|
}
|
|
59
60
|
return ref;
|
|
60
61
|
}
|
|
61
62
|
return resolveVersionRef(resolveCliVersion());
|
|
62
63
|
};
|
|
64
|
+
const SOURCE_REPO = "anolilab/lunora";
|
|
65
|
+
const COMMIT_SHA = /^[0-9a-f]{40}$/iu;
|
|
66
|
+
const SEMVER_BODY = String.raw`\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)+)?(?:\+[0-9A-Za-z.-]+)?`;
|
|
67
|
+
const LEADING_VERSION_TAG = new RegExp(String.raw`^v?${SEMVER_BODY}$`, "u");
|
|
68
|
+
const PACKAGE_VERSION_TAG = new RegExp(String.raw`^(?:@[\w.-]+\/)?[\w.-]+@${SEMVER_BODY}$`, "u");
|
|
69
|
+
const isImmutableRef = (ref) => COMMIT_SHA.test(ref) || LEADING_VERSION_TAG.test(ref) || PACKAGE_VERSION_TAG.test(ref);
|
|
70
|
+
const githubAuthHeaders = () => {
|
|
71
|
+
const token = process.env["GITHUB_TOKEN"] ?? process.env["GH_TOKEN"];
|
|
72
|
+
return token !== void 0 && token.length > 0 ? { authorization: `Bearer ${token}` } : {};
|
|
73
|
+
};
|
|
74
|
+
const fetchBranchSha = async (branch) => {
|
|
75
|
+
try {
|
|
76
|
+
const response = await fetch(`https://api.github.com/repos/${SOURCE_REPO}/commits/${encodeURIComponent(branch)}`, {
|
|
77
|
+
headers: { accept: "application/vnd.github+json", "user-agent": "lunora-cli", ...githubAuthHeaders() },
|
|
78
|
+
signal: AbortSignal.timeout(1e4)
|
|
79
|
+
});
|
|
80
|
+
if (!response.ok) {
|
|
81
|
+
return void 0;
|
|
82
|
+
}
|
|
83
|
+
const body = await response.json();
|
|
84
|
+
return typeof body.sha === "string" && COMMIT_SHA.test(body.sha) ? body.sha : void 0;
|
|
85
|
+
} catch {
|
|
86
|
+
return void 0;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
const resolvePinnedSourceRef = async (ref, logger) => {
|
|
90
|
+
const resolved = resolveSourceRef(ref);
|
|
91
|
+
if (isImmutableRef(resolved)) {
|
|
92
|
+
return resolved;
|
|
93
|
+
}
|
|
94
|
+
const sha = await fetchBranchSha(resolved);
|
|
95
|
+
if (sha === void 0) {
|
|
96
|
+
logger.warn(`could not pin ${SOURCE_REPO}#${resolved} to a commit — fetching the UNPINNED branch (set GITHUB_TOKEN if rate-limited).`);
|
|
97
|
+
return resolved;
|
|
98
|
+
}
|
|
99
|
+
logger.info(`pinned ${SOURCE_REPO}#${resolved} → ${sha}`);
|
|
100
|
+
return sha;
|
|
101
|
+
};
|
|
63
102
|
const STABLE_DIST_TAG = "latest";
|
|
64
|
-
const resolveDistTag = () => {
|
|
65
|
-
const ref = resolveVersionRef(
|
|
103
|
+
const resolveDistTag = (version = resolveCliVersion()) => {
|
|
104
|
+
const ref = resolveVersionRef(version);
|
|
66
105
|
return ref === STABLE_BRANCH ? STABLE_DIST_TAG : ref;
|
|
67
106
|
};
|
|
107
|
+
const DEFAULT_REGISTRY = "https://registry.npmjs.org";
|
|
108
|
+
const registryBase = () => {
|
|
109
|
+
const configured = process.env["npm_config_registry"];
|
|
110
|
+
const base = configured !== void 0 && configured.length > 0 ? configured : DEFAULT_REGISTRY;
|
|
111
|
+
return base.endsWith("/") ? base.slice(0, -1) : base;
|
|
112
|
+
};
|
|
113
|
+
const resolveTagVersion = async (packageName, tag) => {
|
|
114
|
+
try {
|
|
115
|
+
const response = await fetch(`${registryBase()}/${packageName.replaceAll("/", "%2F")}`, {
|
|
116
|
+
headers: { accept: "application/vnd.npm.install-v1+json" },
|
|
117
|
+
signal: AbortSignal.timeout(1e4)
|
|
118
|
+
});
|
|
119
|
+
if (!response.ok) {
|
|
120
|
+
return void 0;
|
|
121
|
+
}
|
|
122
|
+
const packument = await response.json();
|
|
123
|
+
return packument["dist-tags"]?.[tag];
|
|
124
|
+
} catch {
|
|
125
|
+
return void 0;
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
const resolveTagVersions = async (names, tag) => {
|
|
129
|
+
const resolved = /* @__PURE__ */ new Map();
|
|
130
|
+
await Promise.all(
|
|
131
|
+
[...new Set(names)].map(async (name) => {
|
|
132
|
+
const version = await resolveTagVersion(name, tag);
|
|
133
|
+
if (version !== void 0) {
|
|
134
|
+
resolved.set(name, version);
|
|
135
|
+
}
|
|
136
|
+
})
|
|
137
|
+
);
|
|
138
|
+
return resolved;
|
|
139
|
+
};
|
|
68
140
|
|
|
69
141
|
const resolveDepRange = (range) => {
|
|
70
142
|
if (!range.startsWith("workspace:")) {
|
|
@@ -76,8 +148,8 @@ const resolveDepRange = (range) => {
|
|
|
76
148
|
}
|
|
77
149
|
return rest;
|
|
78
150
|
};
|
|
79
|
-
const UMBRELLA_REEXPORTED_DEPS = /* @__PURE__ */ new Set(["@lunora/client", "@lunora/do", "@lunora/runtime", "@lunora/server", "@lunora/values"]);
|
|
80
|
-
const UMBRELLA_IMPORT_RE = /(['"])@lunora\/(client|do|runtime|server|values)(\/[^'"]*)?\1/gu;
|
|
151
|
+
const UMBRELLA_REEXPORTED_DEPS = /* @__PURE__ */ new Set(["@lunora/client", "@lunora/do", "@lunora/ratelimit", "@lunora/runtime", "@lunora/server", "@lunora/values"]);
|
|
152
|
+
const UMBRELLA_IMPORT_RE = /(['"])@lunora\/(client|do|ratelimit|runtime|server|values)(\/[^'"]*)?\1/gu;
|
|
81
153
|
const projectUsesUmbrella = (projectRoot) => {
|
|
82
154
|
const packageJsonPath = join(projectRoot, "package.json");
|
|
83
155
|
if (!existsSync(packageJsonPath)) {
|
|
@@ -386,11 +458,12 @@ export const schema = defineSchema({});
|
|
|
386
458
|
return { kind: "skipped", path: schemaPath };
|
|
387
459
|
}
|
|
388
460
|
if (result.reason === "invalid-identifier") {
|
|
389
|
-
throw new
|
|
461
|
+
throw new LunoraError(
|
|
462
|
+
"INTERNAL",
|
|
390
463
|
`schema-extension item "${itemKey}" is not a valid JS identifier — it is spliced into lunora/schema.ts as \`import { ${itemKey} }\` / \`.extend(${itemKey}.extension)\`. Rename the item to a valid identifier (no leading digit, no "-").`
|
|
391
464
|
);
|
|
392
465
|
}
|
|
393
|
-
throw new
|
|
466
|
+
throw new LunoraError("INTERNAL", `schema-extension merge failed for "${itemKey}": ${result.reason}`);
|
|
394
467
|
};
|
|
395
468
|
const previewWholeFile = (file, current, incoming, exists, logger) => {
|
|
396
469
|
const lines = renderDiff(current, incoming);
|
|
@@ -449,6 +522,90 @@ const reconcileFile = (file, itemKey, itemDirectory, projectRoot, logger, lock,
|
|
|
449
522
|
}
|
|
450
523
|
return reconcileWholeFile(file, itemKey, itemDirectory, projectRoot, logger, lock, reconcileOptions, useUmbrella);
|
|
451
524
|
};
|
|
525
|
+
const WORKER_ENTRY_FALLBACKS = ["src/server.ts", "src/server/index.ts", "src/server/index.tsx", "src/index.ts", "src/worker.ts"];
|
|
526
|
+
const readWranglerMain = (projectRoot) => {
|
|
527
|
+
const wranglerPath = findWranglerFile(projectRoot);
|
|
528
|
+
if (wranglerPath === void 0) {
|
|
529
|
+
return void 0;
|
|
530
|
+
}
|
|
531
|
+
const { parsed } = readWranglerJsonc(wranglerPath);
|
|
532
|
+
return typeof parsed?.main === "string" ? parsed.main : void 0;
|
|
533
|
+
};
|
|
534
|
+
const findWorkerEntry = (projectRoot) => {
|
|
535
|
+
const main = readWranglerMain(projectRoot);
|
|
536
|
+
const candidates = main === void 0 ? WORKER_ENTRY_FALLBACKS : [main, ...WORKER_ENTRY_FALLBACKS];
|
|
537
|
+
for (const candidate of candidates) {
|
|
538
|
+
const absolute = join(projectRoot, candidate);
|
|
539
|
+
if (!existsSync(absolute)) {
|
|
540
|
+
continue;
|
|
541
|
+
}
|
|
542
|
+
const content = readFileSync(absolute, "utf8");
|
|
543
|
+
if (!content.includes("createShardDO(")) {
|
|
544
|
+
if (candidate === main) {
|
|
545
|
+
break;
|
|
546
|
+
}
|
|
547
|
+
continue;
|
|
548
|
+
}
|
|
549
|
+
return { entryPath: absolute, main: candidate, source: content };
|
|
550
|
+
}
|
|
551
|
+
return void 0;
|
|
552
|
+
};
|
|
553
|
+
const computeRelativeSpecifier = (entryPath, projectRoot, moduleName) => {
|
|
554
|
+
const importPath = relative(dirname(entryPath), join(projectRoot, "lunora", moduleName)).replaceAll("\\", "/");
|
|
555
|
+
return importPath.startsWith(".") ? importPath : `./${importPath}`;
|
|
556
|
+
};
|
|
557
|
+
const logClassAFallback = (entrypointReexports, logger) => {
|
|
558
|
+
for (const reexport of entrypointReexports) {
|
|
559
|
+
const specifier = `./lunora/${reexport.module}.js`;
|
|
560
|
+
const instruction = `Add \`export * from "${specifier}"\` to your worker entry`;
|
|
561
|
+
const suffix = reexport.comment ? ` (${reexport.comment})` : "";
|
|
562
|
+
logger.warn(`${instruction}${suffix}`);
|
|
563
|
+
}
|
|
564
|
+
return 0;
|
|
565
|
+
};
|
|
566
|
+
const buildReexportLines = (entrypointReexports, entryPath, projectRoot, source) => {
|
|
567
|
+
const lines = [];
|
|
568
|
+
for (const reexport of entrypointReexports) {
|
|
569
|
+
const specifier = computeRelativeSpecifier(entryPath, projectRoot, reexport.module);
|
|
570
|
+
const escapedSpecifier = specifier.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
|
|
571
|
+
const existingRe = new RegExp(String.raw`export\s+\*\s+from\s+["']${escapedSpecifier}\.js["']`, "u");
|
|
572
|
+
if (existingRe.test(source)) {
|
|
573
|
+
continue;
|
|
574
|
+
}
|
|
575
|
+
if (reexport.comment) {
|
|
576
|
+
lines.push(`
|
|
577
|
+
// ${reexport.comment}`);
|
|
578
|
+
}
|
|
579
|
+
lines.push(`export * from "${specifier}.js";`);
|
|
580
|
+
}
|
|
581
|
+
return lines;
|
|
582
|
+
};
|
|
583
|
+
const applyEntrypointReexports = (entrypointReexports, projectRoot, logger, diff) => {
|
|
584
|
+
if (entrypointReexports.length === 0) {
|
|
585
|
+
return 0;
|
|
586
|
+
}
|
|
587
|
+
const entry = findWorkerEntry(projectRoot);
|
|
588
|
+
if (entry === void 0) {
|
|
589
|
+
return logClassAFallback(entrypointReexports, logger);
|
|
590
|
+
}
|
|
591
|
+
const linesToAppend = buildReexportLines(entrypointReexports, entry.entryPath, projectRoot, entry.source);
|
|
592
|
+
if (linesToAppend.length === 0) {
|
|
593
|
+
return 0;
|
|
594
|
+
}
|
|
595
|
+
if (diff) {
|
|
596
|
+
for (const line of linesToAppend) {
|
|
597
|
+
if (line !== "") {
|
|
598
|
+
logger.info(`~ entrypoint: ${line}`);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
return linesToAppend.length;
|
|
602
|
+
}
|
|
603
|
+
const separator = entry.source.endsWith("\n") ? "" : "\n";
|
|
604
|
+
writeFileSync(entry.entryPath, `${entry.source}${separator}${linesToAppend.join("\n")}
|
|
605
|
+
`, "utf8");
|
|
606
|
+
logger.success(`wrote ${String(linesToAppend.length)} entrypoint re-export(s) to ${relative(projectRoot, entry.entryPath)}`);
|
|
607
|
+
return linesToAppend.length;
|
|
608
|
+
};
|
|
452
609
|
const reconcileItems = (items, cwd, logger, reconcileOptions = {}) => {
|
|
453
610
|
const written = [];
|
|
454
611
|
const skipped = [];
|
|
@@ -461,6 +618,9 @@ const reconcileItems = (items, cwd, logger, reconcileOptions = {}) => {
|
|
|
461
618
|
const outcome = reconcileFile(file, manifest.name, directory, cwd, logger, lock, reconcileOptions, useUmbrella);
|
|
462
619
|
(outcome.kind === "written" ? written : skipped).push(outcome.path);
|
|
463
620
|
}
|
|
621
|
+
if (manifest.entrypointReexports !== void 0) {
|
|
622
|
+
applyEntrypointReexports(manifest.entrypointReexports, cwd, logger, reconcileOptions.diff === true);
|
|
623
|
+
}
|
|
464
624
|
if (reconcileOptions.diff) {
|
|
465
625
|
continue;
|
|
466
626
|
}
|
|
@@ -478,7 +638,8 @@ const DEFAULT_SOURCE_BASE = "gh:anolilab/lunora/registry";
|
|
|
478
638
|
const VALID_ITEM_NAME = /^[A-Za-z0-9][\w-]*$/u;
|
|
479
639
|
const assertSafeItemName = (name) => {
|
|
480
640
|
if (!VALID_ITEM_NAME.test(name)) {
|
|
481
|
-
throw new
|
|
641
|
+
throw new LunoraError(
|
|
642
|
+
"INTERNAL",
|
|
482
643
|
`invalid registry item name "${name}" — names must match ${VALID_ITEM_NAME.source} (letters, digits, "-", "_"; no path separators or "..")`
|
|
483
644
|
);
|
|
484
645
|
}
|
|
@@ -515,29 +676,39 @@ const fetchToStaging = async (remote, label, logger) => {
|
|
|
515
676
|
throw error;
|
|
516
677
|
}
|
|
517
678
|
};
|
|
679
|
+
const remoteRefCache = /* @__PURE__ */ new WeakMap();
|
|
680
|
+
const resolveRemoteRef = async (options) => {
|
|
681
|
+
const cached = remoteRefCache.get(options);
|
|
682
|
+
if (cached !== void 0) {
|
|
683
|
+
return cached;
|
|
684
|
+
}
|
|
685
|
+
const pending = options.source !== void 0 && options.source.length > 0 ? Promise.resolve(resolveSourceRef(options.ref)) : resolvePinnedSourceRef(options.ref, options.logger);
|
|
686
|
+
remoteRefCache.set(options, pending);
|
|
687
|
+
return pending;
|
|
688
|
+
};
|
|
518
689
|
const resolveItemDirectory = async (name, options) => {
|
|
519
690
|
assertSafeItemName(name);
|
|
520
691
|
if (options.from !== void 0) {
|
|
521
692
|
const directory = join(options.from, name);
|
|
522
693
|
if (!existsSync(directory)) {
|
|
523
|
-
throw new
|
|
694
|
+
throw new LunoraError("INTERNAL", `registry item not found in local source: ${directory}`);
|
|
524
695
|
}
|
|
525
696
|
return { cleanup: () => {
|
|
526
697
|
}, directory };
|
|
527
698
|
}
|
|
528
699
|
const base = options.source ?? DEFAULT_SOURCE_BASE;
|
|
529
|
-
return fetchToStaging(`${base}/${name}#${
|
|
700
|
+
return fetchToStaging(`${base}/${name}#${await resolveRemoteRef(options)}`, "item", options.logger);
|
|
530
701
|
};
|
|
531
702
|
const resolveRegistryRoot = async (options) => {
|
|
532
703
|
if (options.from !== void 0) {
|
|
533
704
|
if (!existsSync(options.from)) {
|
|
534
|
-
throw new
|
|
705
|
+
throw new LunoraError("INTERNAL", `registry root not found: ${options.from}`);
|
|
535
706
|
}
|
|
536
707
|
return { cleanup: () => {
|
|
537
708
|
}, root: options.from };
|
|
538
709
|
}
|
|
539
710
|
const base = options.source ?? DEFAULT_SOURCE_BASE;
|
|
540
|
-
const { cleanup, directory } = await fetchToStaging(`${base}#${
|
|
711
|
+
const { cleanup, directory } = await fetchToStaging(`${base}#${await resolveRemoteRef(options)}`, "registry", options.logger);
|
|
541
712
|
return { cleanup, root: directory };
|
|
542
713
|
};
|
|
543
714
|
const readManifest = (itemDirectory, name) => {
|
|
@@ -554,7 +725,7 @@ const resolvePlan = async (names, options) => {
|
|
|
554
725
|
return;
|
|
555
726
|
}
|
|
556
727
|
if (inProgress.has(name)) {
|
|
557
|
-
throw new
|
|
728
|
+
throw new LunoraError("INTERNAL", `cyclic registry dependency detected at "${name}"`);
|
|
558
729
|
}
|
|
559
730
|
inProgress.add(name);
|
|
560
731
|
const { cleanup, directory } = await resolveItemDirectory(name, options);
|
|
@@ -623,6 +794,11 @@ const printPlan = (logger, manifest) => {
|
|
|
623
794
|
const valueSuffix = variable.secret ? " (secret)" : ` = ${JSON.stringify(variable.value ?? "")}`;
|
|
624
795
|
logger.info(` env ${variable.name}${valueSuffix}`);
|
|
625
796
|
}
|
|
797
|
+
for (const reexport of manifest.entrypointReexports ?? []) {
|
|
798
|
+
const specifier = `./lunora/${reexport.module}`;
|
|
799
|
+
const suffix = reexport.comment ? ` // ${reexport.comment}` : "";
|
|
800
|
+
logger.info(` entry ${specifier}${suffix}`);
|
|
801
|
+
}
|
|
626
802
|
};
|
|
627
803
|
const printJsonPlan = (items) => {
|
|
628
804
|
const planSnapshot = items.map(({ manifest }) => {
|
|
@@ -634,6 +810,9 @@ const printJsonPlan = (items) => {
|
|
|
634
810
|
}),
|
|
635
811
|
deps: Object.keys(manifest.deps ?? {}),
|
|
636
812
|
devDependencies: Object.keys(manifest.devDependencies ?? {}),
|
|
813
|
+
entrypointReexports: (manifest.entrypointReexports ?? []).map((reexport) => {
|
|
814
|
+
return { module: reexport.module, ...reexport.comment ? { comment: reexport.comment } : {} };
|
|
815
|
+
}),
|
|
637
816
|
envVars: (manifest.envVars ?? []).map((variable) => {
|
|
638
817
|
return { name: variable.name, ...variable.secret ? { secret: true } : { value: variable.value ?? "" } };
|
|
639
818
|
}),
|
|
@@ -809,4 +988,4 @@ const runBuildIndexCommand = async (options) => {
|
|
|
809
988
|
return empty;
|
|
810
989
|
};
|
|
811
990
|
|
|
812
|
-
export { runBuildIndexCommand as a, runRegistryViewCommand as b,
|
|
991
|
+
export { runBuildIndexCommand as a, runRegistryViewCommand as b, resolveTagVersions as c, resolveSourceRef as d, resolvePinnedSourceRef as e, resolveDistTag as f, runListCommand as g, runAddCommand as r, setBindingField as s };
|
|
@@ -1,22 +1,51 @@
|
|
|
1
|
+
import { STEP_BADGE_NAMES, LunoraReporter } from '@lunora/config';
|
|
1
2
|
import { JsonReporter } from '@visulima/pail/reporter/json';
|
|
2
|
-
import { PrettyReporter } from '@visulima/pail/reporter/pretty';
|
|
3
3
|
import { createPail } from '@visulima/pail/server';
|
|
4
4
|
|
|
5
|
+
let sharedPail;
|
|
6
|
+
let jsonForced = false;
|
|
7
|
+
let configuredReporters;
|
|
5
8
|
const wantJson = () => {
|
|
9
|
+
if (jsonForced) {
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
6
12
|
const flag = process.env.LUNORA_LOG_JSON;
|
|
7
13
|
return flag === "1" || flag === "true";
|
|
8
14
|
};
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
15
|
+
const constructReporter = (Reporter) => new Reporter();
|
|
16
|
+
const buildReporters = () => {
|
|
17
|
+
if (jsonForced) {
|
|
18
|
+
return [constructReporter(JsonReporter)];
|
|
19
|
+
}
|
|
20
|
+
if (configuredReporters !== void 0 && configuredReporters.length > 0) {
|
|
21
|
+
return configuredReporters;
|
|
22
|
+
}
|
|
23
|
+
return [constructReporter(wantJson() ? JsonReporter : LunoraReporter)];
|
|
12
24
|
};
|
|
13
|
-
|
|
25
|
+
const forceJsonLogging = () => {
|
|
26
|
+
if (jsonForced) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
jsonForced = true;
|
|
30
|
+
sharedPail = void 0;
|
|
31
|
+
};
|
|
32
|
+
const logHandlers = {
|
|
33
|
+
compose: (...reporters) => reporters,
|
|
34
|
+
console: () => constructReporter(LunoraReporter),
|
|
35
|
+
json: () => constructReporter(JsonReporter)
|
|
36
|
+
};
|
|
37
|
+
const configureLogHandlers = (reporters) => {
|
|
38
|
+
configuredReporters = Array.isArray(reporters) ? reporters : [reporters];
|
|
39
|
+
sharedPail = void 0;
|
|
40
|
+
};
|
|
41
|
+
const STEP_LOG_TYPES = Object.fromEntries(STEP_BADGE_NAMES.map((name) => [name, { label: name, logLevel: "informational" }]));
|
|
14
42
|
const getPail = () => {
|
|
15
43
|
sharedPail ??= createPail({
|
|
16
|
-
reporters:
|
|
44
|
+
reporters: buildReporters(),
|
|
17
45
|
scope: ["lunora"],
|
|
18
46
|
stderr: process.stderr,
|
|
19
|
-
stdout: process.stdout
|
|
47
|
+
stdout: process.stdout,
|
|
48
|
+
types: STEP_LOG_TYPES
|
|
20
49
|
});
|
|
21
50
|
return sharedPail;
|
|
22
51
|
};
|
|
@@ -69,5 +98,8 @@ const pail = /* @__PURE__ */ new Proxy({}, {
|
|
|
69
98
|
return typeof value === "function" ? value.bind(instance) : value;
|
|
70
99
|
}
|
|
71
100
|
});
|
|
101
|
+
const logStep = (type, message) => {
|
|
102
|
+
getPail()[type](message);
|
|
103
|
+
};
|
|
72
104
|
|
|
73
|
-
export { createLogger, createStderrLogger, getPail, pail };
|
|
105
|
+
export { configureLogHandlers, createLogger, createStderrLogger, forceJsonLogging, getPail, logHandlers, logStep, pail };
|
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
2
|
|
|
3
|
+
const NEEDS_CMD_QUOTING = /[\s"%&<>^|]/u;
|
|
4
|
+
const BACKSLASH_RUN_BEFORE_QUOTE = /(\\*)"/gu;
|
|
5
|
+
const TRAILING_BACKSLASH_RUN = /(\\+)$/u;
|
|
6
|
+
const spawnShellCompat = (command, args, platform = process.platform) => {
|
|
7
|
+
if (platform !== "win32" || command === process.execPath) {
|
|
8
|
+
return { args: [...args], command, shell: false };
|
|
9
|
+
}
|
|
10
|
+
const quote = (value) => {
|
|
11
|
+
if (value === "") {
|
|
12
|
+
return `""`;
|
|
13
|
+
}
|
|
14
|
+
if (!NEEDS_CMD_QUOTING.test(value)) {
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
const escaped = value.replaceAll(BACKSLASH_RUN_BEFORE_QUOTE, String.raw`$1$1\"`).replace(TRAILING_BACKSLASH_RUN, "$1$1");
|
|
18
|
+
return `"${escaped}"`;
|
|
19
|
+
};
|
|
20
|
+
return { args: args.map((argument) => quote(argument)), command: quote(command), shell: true };
|
|
21
|
+
};
|
|
3
22
|
const defaultSpawner = (descriptor) => new Promise((resolve, reject) => {
|
|
4
23
|
const hasInput = typeof descriptor.input === "string";
|
|
5
24
|
const wantCapture = descriptor.captureStdout === true;
|
|
@@ -9,9 +28,11 @@ const defaultSpawner = (descriptor) => new Promise((resolve, reject) => {
|
|
|
9
28
|
} else if (descriptor.stdoutToStderr) {
|
|
10
29
|
stdout = 2;
|
|
11
30
|
}
|
|
12
|
-
const
|
|
31
|
+
const exec = spawnShellCompat(descriptor.command, descriptor.args);
|
|
32
|
+
const child = spawn(exec.command, exec.args, {
|
|
13
33
|
cwd: descriptor.cwd ?? process.cwd(),
|
|
14
34
|
env: descriptor.env ? { ...process.env, ...descriptor.env } : process.env,
|
|
35
|
+
shell: exec.shell,
|
|
15
36
|
stdio: [hasInput ? "pipe" : "inherit", stdout, "inherit"]
|
|
16
37
|
});
|
|
17
38
|
let captured = "";
|
|
@@ -40,4 +61,4 @@ const createRecordingSpawner = (exitCode = 0) => {
|
|
|
40
61
|
return { calls, spawner };
|
|
41
62
|
};
|
|
42
63
|
|
|
43
|
-
export { createRecordingSpawner, defaultSpawner };
|
|
64
|
+
export { createRecordingSpawner, defaultSpawner, spawnShellCompat };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { LunoraError } from '@lunora/errors';
|
|
3
|
+
import { findPackageManagerSync, identifyInitiatingPackageManager } from '@visulima/package/package-manager';
|
|
4
|
+
|
|
5
|
+
const INSTALL_PREFERENCE = ["pnpm", "bun", "yarn", "npm"];
|
|
6
|
+
const KNOWN_PACKAGE_MANAGERS = /* @__PURE__ */ new Set(["bun", "npm", "pnpm", "yarn"]);
|
|
7
|
+
const isKnownPackageManager = (name) => KNOWN_PACKAGE_MANAGERS.has(name);
|
|
8
|
+
const isManagerInstalled = (manager) => {
|
|
9
|
+
try {
|
|
10
|
+
return spawnSync(manager, ["--version"], { stdio: "ignore", timeout: 5e3 }).status === 0;
|
|
11
|
+
} catch {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const detectInstalledManagers = (probe = isManagerInstalled) => INSTALL_PREFERENCE.filter((manager) => probe(manager));
|
|
16
|
+
const installArgsFor = (manager) => {
|
|
17
|
+
return { args: ["install"], command: manager };
|
|
18
|
+
};
|
|
19
|
+
const detectPackageManager = (startDirectory) => {
|
|
20
|
+
try {
|
|
21
|
+
return findPackageManagerSync(startDirectory).packageManager;
|
|
22
|
+
} catch {
|
|
23
|
+
}
|
|
24
|
+
const initiating = identifyInitiatingPackageManager();
|
|
25
|
+
if (initiating !== void 0) {
|
|
26
|
+
const name = initiating.name === "cnpm" ? "npm" : initiating.name;
|
|
27
|
+
if (isKnownPackageManager(name)) {
|
|
28
|
+
return name;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const [installed] = detectInstalledManagers();
|
|
32
|
+
if (installed !== void 0) {
|
|
33
|
+
return installed;
|
|
34
|
+
}
|
|
35
|
+
throw new LunoraError(
|
|
36
|
+
"INTERNAL",
|
|
37
|
+
"Could not detect a package manager: no lock file or `packageManager` field was found, and none (pnpm, bun, yarn, npm) is installed on PATH."
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
const execArgsFor = (manager, command, args) => {
|
|
41
|
+
if (manager === "yarn") {
|
|
42
|
+
return { args: [command, ...args], command: "yarn" };
|
|
43
|
+
}
|
|
44
|
+
if (manager === "bun") {
|
|
45
|
+
return { args: ["x", command, ...args], command: "bun" };
|
|
46
|
+
}
|
|
47
|
+
if (manager === "npm") {
|
|
48
|
+
return { args: ["--", command, ...args], command: "npx" };
|
|
49
|
+
}
|
|
50
|
+
return { args: ["exec", command, ...args], command: "pnpm" };
|
|
51
|
+
};
|
|
52
|
+
const runScriptCommand = (manager, script) => {
|
|
53
|
+
if (manager === "npm") {
|
|
54
|
+
return `npm run ${script}`;
|
|
55
|
+
}
|
|
56
|
+
if (manager === "bun") {
|
|
57
|
+
return `bun run ${script}`;
|
|
58
|
+
}
|
|
59
|
+
return `${manager} ${script}`;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export { detectInstalledManagers as a, detectPackageManager as d, execArgsFor as e, installArgsFor as i, runScriptCommand as r };
|
package/dist/packem_shared/{insertSchemaExtension-BuzF6-t2.mjs → insertSchemaExtension-DAqbfr9Z.mjs}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Project, SyntaxKind } from 'ts-morph';
|
|
1
|
+
import { Project, SyntaxKind, Node } from 'ts-morph';
|
|
2
2
|
|
|
3
3
|
const VALID_JS_IDENTIFIER = /^[A-Za-z_$][\w$]*$/u;
|
|
4
4
|
const startMarker = (key) => `// lunora:add:${key}:start`;
|
|
@@ -12,6 +12,19 @@ const findDefineSchemaCall = (callExpressions) => {
|
|
|
12
12
|
}
|
|
13
13
|
return void 0;
|
|
14
14
|
};
|
|
15
|
+
const outermostChainExpression = (defineSchemaCall) => {
|
|
16
|
+
let node = defineSchemaCall;
|
|
17
|
+
for (let parent = node.getParent(); parent !== void 0; parent = node.getParent()) {
|
|
18
|
+
if (Node.isPropertyAccessExpression(parent) && parent.getExpression() === node) {
|
|
19
|
+
node = parent;
|
|
20
|
+
} else if (Node.isCallExpression(parent) && parent.getExpression() === node) {
|
|
21
|
+
node = parent;
|
|
22
|
+
} else {
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return node;
|
|
27
|
+
};
|
|
15
28
|
const insertSchemaExtension = (source, key) => {
|
|
16
29
|
if (!VALID_JS_IDENTIFIER.test(key)) {
|
|
17
30
|
return { ok: false, reason: "invalid-identifier" };
|
|
@@ -33,15 +46,7 @@ const insertSchemaExtension = (source, key) => {
|
|
|
33
46
|
if (tablesArgument?.getKind() !== SyntaxKind.ObjectLiteralExpression) {
|
|
34
47
|
return { ok: false, reason: "non-object-argument" };
|
|
35
48
|
}
|
|
36
|
-
const
|
|
37
|
-
if (!variableDeclaration) {
|
|
38
|
-
return { ok: false, reason: "no-define-schema" };
|
|
39
|
-
}
|
|
40
|
-
const initializer = variableDeclaration.getInitializer();
|
|
41
|
-
if (!initializer) {
|
|
42
|
-
return { ok: false, reason: "no-define-schema" };
|
|
43
|
-
}
|
|
44
|
-
const insertAt = initializer.getEnd();
|
|
49
|
+
const insertAt = outermostChainExpression(defineSchemaCall).getEnd();
|
|
45
50
|
const chainText = `
|
|
46
51
|
${startMarker(key)}
|
|
47
52
|
.extend(${key}.extension)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
2
|
import { platform } from 'node:os';
|
|
3
|
+
import { LunoraError } from '@lunora/errors';
|
|
3
4
|
|
|
4
5
|
const platformCommand = () => {
|
|
5
6
|
const os = platform();
|
|
@@ -29,10 +30,10 @@ const openUrl = async (url, options = {}) => {
|
|
|
29
30
|
try {
|
|
30
31
|
parsed = new URL(url);
|
|
31
32
|
} catch {
|
|
32
|
-
throw new
|
|
33
|
+
throw new LunoraError("INTERNAL", `Invalid URL: ${url}`);
|
|
33
34
|
}
|
|
34
35
|
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
35
|
-
throw new
|
|
36
|
+
throw new LunoraError("INTERNAL", `Refusing to open non-http(s) URL: ${url}`);
|
|
36
37
|
}
|
|
37
38
|
const opener = options.opener ?? platformOpener;
|
|
38
39
|
await opener(url);
|