@lunora/config 1.0.0-alpha.7 → 1.0.0-alpha.71
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/index.d.mts +885 -461
- package/dist/index.d.ts +885 -461
- package/dist/index.mjs +18 -10
- package/dist/packem_shared/AGENT_MODE_ENV-B5R7jpY7.mjs +17 -0
- package/dist/packem_shared/DEV_DAEMON_ENV-FIEtW7Fz.mjs +163 -0
- package/dist/packem_shared/{LUNORA_EVENT_SOURCE-D2fDeGB6.mjs → LUNORA_EVENT_SOURCE-M1KM9_pR.mjs} +28 -2
- package/dist/packem_shared/{PACKAGE_SECRETS_REGISTRY-CySy5vR_.mjs → PACKAGE_SECRETS_REGISTRY-BeRSvrl5.mjs} +45 -1
- package/dist/packem_shared/{POLICY_SCAFFOLD_ENDPOINT-CiC2IGKx.mjs → POLICY_SCAFFOLD_ENDPOINT-CvTZpaZF.mjs} +7 -10
- package/dist/packem_shared/{REMOTE_ELIGIBLE_KEYS-BC7_e9Bz.mjs → REMOTE_ELIGIBLE_KEYS-C-F_Flgy.mjs} +1 -6
- package/dist/packem_shared/{REQUIRED_COMPATIBILITY_DATE-ycqievRl.mjs → REQUIRED_COMPATIBILITY_DATE-DP0SFVy9.mjs} +135 -4
- package/dist/packem_shared/{SCHEMA_EDIT_ENDPOINT-Df-Wrix-.mjs → SCHEMA_EDIT_ENDPOINT-Bt2SNkpV.mjs} +4 -8
- package/dist/packem_shared/{SEED_ENDPOINT-DVCjaGO-.mjs → SEED_ENDPOINT-7izz_Jao.mjs} +1 -1
- package/dist/packem_shared/WORKERS_CACHE_MIN_DATE-CaXbS7CX.mjs +11 -0
- package/dist/packem_shared/assetContentType-ByZjeV3D.mjs +72 -0
- package/dist/packem_shared/{buildPackageSecretsBlock-S74dgmwy.mjs → buildPackageSecretsBlock-B-dWb-Sa.mjs} +115 -21
- package/dist/packem_shared/collectWranglerSecretVariables-p4ezBYQ4.mjs +56 -0
- package/dist/packem_shared/{createConfirm-fvpdgJ9s.mjs → createConfirm-BMikeJC9.mjs} +22 -5
- package/dist/packem_shared/{detectFramework-Br-BcPBq.mjs → detectFramework-U08038Yp.mjs} +3 -3
- package/dist/packem_shared/discoverAgentInfo-eXA3hF4v.mjs +19 -0
- package/dist/packem_shared/{discoverSchemaInfo-DWtypqpP.mjs → discoverSchemaInfo-BB-CKlTK.mjs} +1 -1
- package/dist/packem_shared/{inferLunoraBindings-XNJH4pup.mjs → inferLunoraBindings-BcvvtpSG.mjs} +146 -51
- package/dist/packem_shared/jsonc-edit-SbcD7MAe.mjs +9 -0
- package/dist/packem_shared/parseDevVariable-B0FEvfHC.mjs +21 -0
- package/dist/packem_shared/{policy-scaffold.d-DCmwn7zQ.d.ts → policy-scaffold.d-CFd2FlqG.d.mts} +22 -22
- package/dist/packem_shared/{policy-scaffold.d-DCmwn7zQ.d.mts → policy-scaffold.d-CFd2FlqG.d.ts} +22 -22
- package/dist/packem_shared/{reconcileWranglerBindings-DTHmqTbL.mjs → reconcileWranglerBindings-2Cww5VLa.mjs} +114 -29
- package/dist/packem_shared/reconcileWranglerCompatibilityDate-C8c497ag.mjs +31 -0
- package/dist/packem_shared/reconcileWranglerCrons-DvsceVFz.mjs +29 -0
- package/dist/packem_shared/{serveJsonHandler-B4OLTGLS.mjs → serveJsonHandler-Cl2Wqkv8.mjs} +2 -2
- package/dist/packem_shared/streamContainerLogs-BZ4cOZwH.mjs +157 -0
- package/dist/packem_shared/write-atomic-B2REqapi.mjs +14 -0
- package/dist/studio-host/index.d.mts +134 -92
- package/dist/studio-host/index.d.ts +134 -92
- package/dist/studio-host/index.mjs +6 -6
- package/package.json +11 -8
- package/dist/packem_shared/loadStudioAssets-Csk5RS4E.mjs +0 -28
- package/dist/packem_shared/parseDevVariable-CJiq2IwE.mjs +0 -30
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const WORKERS_CACHE_MIN_DATE = "2026-05-01";
|
|
2
|
+
const isCacheEnabled = (parsed) => {
|
|
3
|
+
if (!parsed) {
|
|
4
|
+
return false;
|
|
5
|
+
}
|
|
6
|
+
const topLevel = typeof parsed.cache === "object" && parsed.cache !== null && parsed.cache.enabled === true;
|
|
7
|
+
const inExports = typeof parsed.exports === "object" && parsed.exports !== null && Object.values(parsed.exports).some((entry) => typeof entry === "object" && entry !== null && entry.cache?.enabled === true);
|
|
8
|
+
return topLevel || inExports;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export { WORKERS_CACHE_MIN_DATE, isCacheEnabled };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { normalize, join, relative, isAbsolute, dirname } from 'node:path';
|
|
4
|
+
|
|
5
|
+
const loadStudioAssets = (logger, resolveFrom = import.meta.url) => {
|
|
6
|
+
try {
|
|
7
|
+
const require = createRequire(resolveFrom);
|
|
8
|
+
return {
|
|
9
|
+
script: readFileSync(require.resolve("@lunora/studio/standalone/studio.js")),
|
|
10
|
+
styles: readFileSync(require.resolve("@lunora/studio/styles.css"))
|
|
11
|
+
};
|
|
12
|
+
} catch (error) {
|
|
13
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
14
|
+
logger?.warnOnce?.(`[lunora] studio assets unavailable (build @lunora/studio?): ${message}`);
|
|
15
|
+
return void 0;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const studioAssetsStamp = (resolveFrom = import.meta.url) => {
|
|
19
|
+
try {
|
|
20
|
+
const require = createRequire(resolveFrom);
|
|
21
|
+
const scriptMtime = statSync(require.resolve("@lunora/studio/standalone/studio.js")).mtimeMs;
|
|
22
|
+
const stylesMtime = statSync(require.resolve("@lunora/studio/styles.css")).mtimeMs;
|
|
23
|
+
return Math.max(scriptMtime, stylesMtime);
|
|
24
|
+
} catch {
|
|
25
|
+
return void 0;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
const resolveStandaloneDirectory = (resolveFrom = import.meta.url) => {
|
|
29
|
+
try {
|
|
30
|
+
return dirname(createRequire(resolveFrom).resolve("@lunora/studio/standalone/studio.js"));
|
|
31
|
+
} catch {
|
|
32
|
+
return void 0;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const resolveContainedFile = (directory, fileName) => {
|
|
36
|
+
if (fileName === "" || fileName === "." || fileName === ".." || fileName.includes("/") || fileName.includes("\\") || fileName.includes("\0")) {
|
|
37
|
+
return void 0;
|
|
38
|
+
}
|
|
39
|
+
const resolved = normalize(join(directory, fileName));
|
|
40
|
+
const relativePath = relative(directory, resolved);
|
|
41
|
+
if (relativePath === "" || relativePath.startsWith("..") || isAbsolute(relativePath) || relativePath.includes("/") || relativePath.includes("\\")) {
|
|
42
|
+
return void 0;
|
|
43
|
+
}
|
|
44
|
+
return resolved;
|
|
45
|
+
};
|
|
46
|
+
const readStandaloneAsset = (fileName, resolveFrom = import.meta.url) => {
|
|
47
|
+
const directory = resolveStandaloneDirectory(resolveFrom);
|
|
48
|
+
if (directory === void 0) {
|
|
49
|
+
return void 0;
|
|
50
|
+
}
|
|
51
|
+
const resolved = resolveContainedFile(directory, fileName);
|
|
52
|
+
if (resolved === void 0) {
|
|
53
|
+
return void 0;
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
return readFileSync(resolved);
|
|
57
|
+
} catch {
|
|
58
|
+
return void 0;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const isStandaloneModulePath = (pathname) => pathname.endsWith(".js") || pathname.endsWith(".js.map");
|
|
62
|
+
const assetContentType = (fileName) => {
|
|
63
|
+
if (fileName.endsWith(".css")) {
|
|
64
|
+
return "text/css; charset=utf-8";
|
|
65
|
+
}
|
|
66
|
+
if (fileName.endsWith(".map")) {
|
|
67
|
+
return "application/json; charset=utf-8";
|
|
68
|
+
}
|
|
69
|
+
return "text/javascript; charset=utf-8";
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export { assetContentType, isStandaloneModulePath, loadStudioAssets, readStandaloneAsset, resolveContainedFile, resolveStandaloneDirectory, studioAssetsStamp };
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { randomBytes } from 'node:crypto';
|
|
2
|
-
import { existsSync, readFileSync, writeFileSync, renameSync, rmSync } from 'node:fs';
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync, renameSync, rmSync, statSync } from 'node:fs';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { LunoraError } from '@lunora/errors';
|
|
5
|
+
import { DEV_VARS_FILE, DEV_VARS_EXAMPLE_FILE, splitDevVariableLine, parseDevVariableEntries, DEV_VARS_NEWLINE, unquoteDevVariable } from './DEV_VARS_EXAMPLE_FILE-dJPNTEnK.mjs';
|
|
6
|
+
import { CORE_SECRETS, PACKAGE_SECRETS_REGISTRY, secretsForPackages } from './PACKAGE_SECRETS_REGISTRY-BeRSvrl5.mjs';
|
|
6
7
|
|
|
8
|
+
const requiredSecrets = (packageNames) => [...CORE_SECRETS, ...secretsForPackages(packageNames)];
|
|
7
9
|
const SECRET_BYTES = 32;
|
|
8
10
|
const SECRET_KEY = /(?:KEY|PASSWORD|SECRET|TOKEN)$/u;
|
|
9
11
|
const PLACEHOLDER_MARKERS = [
|
|
@@ -44,7 +46,12 @@ const isPlaceholderValue = (value) => {
|
|
|
44
46
|
};
|
|
45
47
|
const isPlaceholder = (rawValue) => isPlaceholderValue(unquoteDevVariable(rawValue.trim()));
|
|
46
48
|
const defaultRandomHex = (bytes) => randomBytes(bytes).toString("hex");
|
|
47
|
-
const
|
|
49
|
+
const PROVIDER_SECRET_KEYS = new Set(
|
|
50
|
+
[...CORE_SECRETS, ...Object.values(PACKAGE_SECRETS_REGISTRY).flat()].filter((entry) => SECRET_KEY.test(entry.key) && entry.placeholderValue.startsWith("<")).map((entry) => entry.key)
|
|
51
|
+
);
|
|
52
|
+
const isMintableSecretKey = (key) => SECRET_KEY.test(key) && !PROVIDER_SECRET_KEYS.has(key);
|
|
53
|
+
const generatedSecretFor = (key, rawValue, randomHex) => isMintableSecretKey(key) && isPlaceholder(rawValue) ? randomHex(SECRET_BYTES) : void 0;
|
|
54
|
+
const generateSecretValue = (randomHex = defaultRandomHex) => randomHex(SECRET_BYTES);
|
|
48
55
|
const planDevVariablesScaffold = (input) => {
|
|
49
56
|
if (input.devVarsExists) {
|
|
50
57
|
return { status: "exists" };
|
|
@@ -98,19 +105,48 @@ const atomicCreateDevVariables = (path, content) => {
|
|
|
98
105
|
throw error;
|
|
99
106
|
}
|
|
100
107
|
};
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
const separator = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
|
|
104
|
-
const content = `${existing}${separator}${additions.join("\n")}
|
|
105
|
-
`;
|
|
106
|
-
const temporaryPath = `${path}.tmp-${String(process.pid)}`;
|
|
108
|
+
const APPEND_MAX_ATTEMPTS = 5;
|
|
109
|
+
const fingerprintOf = (path) => {
|
|
107
110
|
try {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
} catch
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
const stats = statSync(path);
|
|
112
|
+
return { mtimeMs: stats.mtimeMs, size: stats.size };
|
|
113
|
+
} catch {
|
|
114
|
+
return void 0;
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
const sameFingerprint = (a, b) => {
|
|
118
|
+
if (a === void 0 || b === void 0) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
return a.mtimeMs === b.mtimeMs && a.size === b.size;
|
|
122
|
+
};
|
|
123
|
+
const appendDevVariables = (path, buildAdditions) => {
|
|
124
|
+
for (let attempt = 0; attempt < APPEND_MAX_ATTEMPTS; attempt += 1) {
|
|
125
|
+
const beforeFingerprint = fingerprintOf(path);
|
|
126
|
+
const existing = readFileSync(path, "utf8");
|
|
127
|
+
const additions = buildAdditions(existing);
|
|
128
|
+
if (additions.length === 0) {
|
|
129
|
+
return [];
|
|
130
|
+
}
|
|
131
|
+
const separator = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
|
|
132
|
+
const content = `${existing}${separator}${additions.join("\n")}
|
|
133
|
+
`;
|
|
134
|
+
const temporaryPath = `${path}.tmp-${String(process.pid)}-${randomBytes(6).toString("hex")}`;
|
|
135
|
+
try {
|
|
136
|
+
writeFileSync(temporaryPath, content, { encoding: "utf8", mode: 384 });
|
|
137
|
+
const beforeRenameFingerprint = fingerprintOf(path);
|
|
138
|
+
if (!sameFingerprint(beforeFingerprint, beforeRenameFingerprint)) {
|
|
139
|
+
rmSync(temporaryPath, { force: true });
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
renameSync(temporaryPath, path);
|
|
143
|
+
return additions;
|
|
144
|
+
} catch (error) {
|
|
145
|
+
rmSync(temporaryPath, { force: true });
|
|
146
|
+
throw error;
|
|
147
|
+
}
|
|
113
148
|
}
|
|
149
|
+
throw new LunoraError("INTERNAL", `Failed to append to ${path} after ${String(APPEND_MAX_ATTEMPTS)} attempts — a concurrent writer kept winning the race.`);
|
|
114
150
|
};
|
|
115
151
|
const ensureDevVariables = async (deps) => {
|
|
116
152
|
const devVariablesPath = join(deps.cwd, DEV_VARS_FILE);
|
|
@@ -146,16 +182,24 @@ const ensureDevVariables = async (deps) => {
|
|
|
146
182
|
deps.info(`Skipped — add ${list} to ${DEV_VARS_FILE} when you're ready.`);
|
|
147
183
|
return { addedKeys: [], generatedKeys: [], status: "declined" };
|
|
148
184
|
}
|
|
149
|
-
appendDevVariables(
|
|
150
|
-
|
|
151
|
-
|
|
185
|
+
const written = appendDevVariables(
|
|
186
|
+
devVariablesPath,
|
|
187
|
+
(currentContent) => planDevVariablesAugment({ existingContent: currentContent, exampleContent, randomHex: deps.randomHex }).additions
|
|
188
|
+
);
|
|
189
|
+
const writtenKeys = written.map((line) => splitDevVariableLine(line)?.key).filter((key) => key !== void 0);
|
|
190
|
+
if (writtenKeys.length === 0) {
|
|
191
|
+
return { addedKeys: [], generatedKeys: [], status: "exists" };
|
|
192
|
+
}
|
|
193
|
+
const writtenGeneratedKeys = augment.generatedKeys.filter((key) => writtenKeys.includes(key));
|
|
194
|
+
deps.info(`Updated ${DEV_VARS_FILE} — added ${writtenKeys.join(", ")}${generatedSuffix(writtenGeneratedKeys)}.`);
|
|
195
|
+
return { addedKeys: writtenKeys, generatedKeys: writtenGeneratedKeys, status: "augmented" };
|
|
152
196
|
};
|
|
153
197
|
const secretEntryBlock = (entry) => {
|
|
154
198
|
const lines = [`# ${entry.description}`, `# Docs: ${entry.docsUrl}`, `${entry.key}="${entry.placeholderValue}"`];
|
|
155
199
|
return lines.join("\n");
|
|
156
200
|
};
|
|
157
201
|
const buildPackageSecretsBlock = (packageNames, existingKeys) => {
|
|
158
|
-
const entries =
|
|
202
|
+
const entries = requiredSecrets(packageNames).filter((entry) => !existingKeys.has(entry.key));
|
|
159
203
|
if (entries.length === 0) {
|
|
160
204
|
return "";
|
|
161
205
|
}
|
|
@@ -181,7 +225,57 @@ ${block}
|
|
|
181
225
|
rmSync(temporaryPath, { force: true });
|
|
182
226
|
throw error;
|
|
183
227
|
}
|
|
184
|
-
return
|
|
228
|
+
return requiredSecrets(packageNames).filter((entry) => !existingKeys.has(entry.key)).map((entry) => entry.key);
|
|
229
|
+
};
|
|
230
|
+
const planDevSecretsFill = (input) => {
|
|
231
|
+
const randomHex = input.randomHex ?? defaultRandomHex;
|
|
232
|
+
const filledKeys = [];
|
|
233
|
+
const lines = input.existingContent.split(DEV_VARS_NEWLINE).map((line) => {
|
|
234
|
+
const parsed = splitDevVariableLine(line);
|
|
235
|
+
const secret = parsed ? generatedSecretFor(parsed.key, parsed.value, randomHex) : void 0;
|
|
236
|
+
if (!parsed || secret === void 0) {
|
|
237
|
+
return line;
|
|
238
|
+
}
|
|
239
|
+
filledKeys.push(parsed.key);
|
|
240
|
+
return `${parsed.key}="${secret}"`;
|
|
241
|
+
});
|
|
242
|
+
const present = new Set(parseDevVariableEntries(input.existingContent).map((entry) => entry.key));
|
|
243
|
+
const addedKeys = [];
|
|
244
|
+
const additions = [];
|
|
245
|
+
for (const entry of CORE_SECRETS) {
|
|
246
|
+
if (present.has(entry.key)) {
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
addedKeys.push(entry.key);
|
|
250
|
+
additions.push(`# ${entry.description}`, `${entry.key}="${randomHex(SECRET_BYTES)}"`);
|
|
251
|
+
}
|
|
252
|
+
const body = lines.join("\n");
|
|
253
|
+
if (additions.length === 0) {
|
|
254
|
+
return { addedKeys, content: body, filledKeys };
|
|
255
|
+
}
|
|
256
|
+
const separator = body === "" || body.endsWith("\n") ? "" : "\n";
|
|
257
|
+
return { addedKeys, content: `${body}${separator}${additions.join("\n")}
|
|
258
|
+
`, filledKeys };
|
|
259
|
+
};
|
|
260
|
+
const fillDevSecrets = (deps) => {
|
|
261
|
+
const devVariablesPath = join(deps.cwd, DEV_VARS_FILE);
|
|
262
|
+
const exists = existsSync(devVariablesPath);
|
|
263
|
+
const existingContent = exists ? readFileSync(devVariablesPath, "utf8") : "";
|
|
264
|
+
const plan = planDevSecretsFill({ existingContent, randomHex: deps.randomHex });
|
|
265
|
+
if (plan.filledKeys.length === 0 && plan.addedKeys.length === 0) {
|
|
266
|
+
return { addedKeys: [], filledKeys: [], status: "unchanged" };
|
|
267
|
+
}
|
|
268
|
+
const temporaryPath = `${devVariablesPath}.tmp-${String(process.pid)}`;
|
|
269
|
+
try {
|
|
270
|
+
writeFileSync(temporaryPath, plan.content, { encoding: "utf8", mode: 384 });
|
|
271
|
+
renameSync(temporaryPath, devVariablesPath);
|
|
272
|
+
} catch (error) {
|
|
273
|
+
rmSync(temporaryPath, { force: true });
|
|
274
|
+
throw error;
|
|
275
|
+
}
|
|
276
|
+
const generated = [...plan.filledKeys, ...plan.addedKeys];
|
|
277
|
+
deps.info?.(`Generated ${String(generated.length)} dev secret(s) in ${DEV_VARS_FILE}: ${generated.join(", ")}`);
|
|
278
|
+
return { addedKeys: plan.addedKeys, filledKeys: plan.filledKeys, status: exists ? "filled" : "created" };
|
|
185
279
|
};
|
|
186
280
|
|
|
187
|
-
export { buildPackageSecretsBlock, ensureDevVariables, ensureDevVariablesExample as ensureDevVarsExample, isPlaceholderValue, planDevVariablesAugment, planDevVariablesScaffold };
|
|
281
|
+
export { buildPackageSecretsBlock, ensureDevVariables, ensureDevVariablesExample as ensureDevVarsExample, fillDevSecrets, generateSecretValue, isMintableSecretKey, isPlaceholderValue, planDevSecretsFill, planDevVariablesAugment, planDevVariablesScaffold, requiredSecrets };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { relative } from 'node:path';
|
|
2
|
+
import { secretKindOf, redact } from '@lunora/codegen';
|
|
3
|
+
import { isPlaceholderValue } from './buildPackageSecretsBlock-B-dWb-Sa.mjs';
|
|
4
|
+
import { findWranglerFile, readWranglerJsonc } from './WRANGLER_FILES-DwSuC-Kn.mjs';
|
|
5
|
+
|
|
6
|
+
const MIN_SECRET_NAMED_VALUE_LENGTH = 8;
|
|
7
|
+
const SECRET_WORD_TOKENS = /* @__PURE__ */ new Set(["CREDENTIAL", "CREDENTIALS", "DSN", "PASSPHRASE", "PASSWD", "PASSWORD", "SECRET", "TOKEN"]);
|
|
8
|
+
const SECRET_KEY_SUFFIXES = ["ACCESS_KEY", "API_KEY", "ENCRYPTION_KEY", "PRIVATE_KEY", "SIGNING_KEY"];
|
|
9
|
+
const PUBLIC_KEY_TOKENS = /* @__PURE__ */ new Set(["PUBLIC", "PUBLISHABLE"]);
|
|
10
|
+
const KEY_SEPARATOR_RE = /[_-]/u;
|
|
11
|
+
const keyTokens = (key) => key.toUpperCase().split(KEY_SEPARATOR_RE);
|
|
12
|
+
const isSecretKeyName = (key) => {
|
|
13
|
+
const normalized = key.toUpperCase().replaceAll("-", "_");
|
|
14
|
+
if (keyTokens(key).some((token) => SECRET_WORD_TOKENS.has(token))) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
return SECRET_KEY_SUFFIXES.some((suffix) => normalized === suffix || normalized.endsWith(`_${suffix}`));
|
|
18
|
+
};
|
|
19
|
+
const isPublicKeyName = (key) => keyTokens(key).some((token) => PUBLIC_KEY_TOKENS.has(token));
|
|
20
|
+
const scanWranglerVariablesForSecrets = (variables, file) => {
|
|
21
|
+
if (variables === void 0) {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
const findings = [];
|
|
25
|
+
for (const [key, rawValue] of Object.entries(variables)) {
|
|
26
|
+
if (typeof rawValue !== "string") {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (isPlaceholderValue(rawValue)) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (isPublicKeyName(key)) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const shapeKind = secretKindOf(rawValue);
|
|
36
|
+
const kind = shapeKind ?? (isSecretKeyName(key) && rawValue.length >= MIN_SECRET_NAMED_VALUE_LENGTH ? "secret_named_var" : void 0);
|
|
37
|
+
if (kind === void 0) {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
findings.push({ file, key, kind, preview: redact(rawValue) });
|
|
41
|
+
}
|
|
42
|
+
return findings;
|
|
43
|
+
};
|
|
44
|
+
const collectWranglerSecretVariables = (projectRoot) => {
|
|
45
|
+
const wranglerPath = findWranglerFile(projectRoot);
|
|
46
|
+
if (wranglerPath === void 0) {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
const { parsed } = readWranglerJsonc(wranglerPath);
|
|
50
|
+
if (parsed === void 0) {
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
return scanWranglerVariablesForSecrets(parsed.vars, relative(projectRoot, wranglerPath));
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export { collectWranglerSecretVariables, scanWranglerVariablesForSecrets };
|
|
@@ -28,13 +28,13 @@ const promptSelect = async (message, options, settings) => {
|
|
|
28
28
|
const lines = options.map(
|
|
29
29
|
(option, index) => ` ${String(index + 1)}) ${option.label}${option.description === void 0 ? "" : ` — ${option.description}`}`
|
|
30
30
|
);
|
|
31
|
-
const
|
|
31
|
+
const promptMessage = `${message}
|
|
32
32
|
${lines.join("\n")}
|
|
33
33
|
> ${defaultIndex >= 0 ? `[${String(defaultIndex + 1)}] ` : ""}`;
|
|
34
34
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
35
35
|
try {
|
|
36
36
|
const answer = await new Promise((resolve) => {
|
|
37
|
-
rl.question(
|
|
37
|
+
rl.question(promptMessage, (input) => {
|
|
38
38
|
resolve(input);
|
|
39
39
|
});
|
|
40
40
|
});
|
|
@@ -52,6 +52,23 @@ ${lines.join("\n")}
|
|
|
52
52
|
rl.close();
|
|
53
53
|
}
|
|
54
54
|
};
|
|
55
|
+
const promptText = async (message, settings) => {
|
|
56
|
+
if (!isInteractive()) {
|
|
57
|
+
return settings?.default;
|
|
58
|
+
}
|
|
59
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
60
|
+
try {
|
|
61
|
+
const answer = await new Promise((resolve) => {
|
|
62
|
+
rl.question(message, (input) => {
|
|
63
|
+
resolve(input);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
const trimmed = answer.trim();
|
|
67
|
+
return trimmed === "" ? settings?.default : trimmed;
|
|
68
|
+
} finally {
|
|
69
|
+
rl.close();
|
|
70
|
+
}
|
|
71
|
+
};
|
|
55
72
|
const promptMultiSelect = async (message, options, settings) => {
|
|
56
73
|
const defaults = settings?.defaults ?? [];
|
|
57
74
|
if (!isInteractive() || options.length === 0) {
|
|
@@ -61,13 +78,13 @@ const promptMultiSelect = async (message, options, settings) => {
|
|
|
61
78
|
(option, index) => ` ${String(index + 1)}) ${option.label}${option.description === void 0 ? "" : ` — ${option.description}`}`
|
|
62
79
|
);
|
|
63
80
|
const defaultHint = defaults.length === 0 ? "" : `[${defaults.join(", ")}] `;
|
|
64
|
-
const
|
|
81
|
+
const promptMessage = `${message} (comma-separated; Enter for default)
|
|
65
82
|
${lines.join("\n")}
|
|
66
83
|
> ${defaultHint}`;
|
|
67
84
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
68
85
|
try {
|
|
69
86
|
const answer = await new Promise((resolve) => {
|
|
70
|
-
rl.question(
|
|
87
|
+
rl.question(promptMessage, (input) => {
|
|
71
88
|
resolve(input);
|
|
72
89
|
});
|
|
73
90
|
});
|
|
@@ -97,4 +114,4 @@ ${lines.join("\n")}
|
|
|
97
114
|
}
|
|
98
115
|
};
|
|
99
116
|
|
|
100
|
-
export { createConfirm, isInteractive, promptMultiSelect, promptSelect, promptYesNo };
|
|
117
|
+
export { createConfirm, isInteractive, promptMultiSelect, promptSelect, promptText, promptYesNo };
|
|
@@ -12,7 +12,7 @@ const FRAMEWORK_SIGNATURES = [
|
|
|
12
12
|
{ class: "B", dependency: "astro", framework: "astro" }
|
|
13
13
|
];
|
|
14
14
|
const STANDALONE = { class: "C", framework: "none" };
|
|
15
|
-
const
|
|
15
|
+
const readProjectDependencyNames = (root) => {
|
|
16
16
|
const packageJsonPath = join(root, "package.json");
|
|
17
17
|
if (!existsSync(packageJsonPath)) {
|
|
18
18
|
return /* @__PURE__ */ new Set();
|
|
@@ -26,7 +26,7 @@ const readDependencyNames = (root) => {
|
|
|
26
26
|
}
|
|
27
27
|
};
|
|
28
28
|
const detectFramework = (root) => {
|
|
29
|
-
const dependencies =
|
|
29
|
+
const dependencies = readProjectDependencyNames(root);
|
|
30
30
|
if (dependencies.size === 0) {
|
|
31
31
|
return STANDALONE;
|
|
32
32
|
}
|
|
@@ -38,4 +38,4 @@ const detectFramework = (root) => {
|
|
|
38
38
|
return STANDALONE;
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
-
export { detectFramework };
|
|
41
|
+
export { detectFramework, readProjectDependencyNames };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { AGENTS_FILENAME, discoverAgents } from '@lunora/codegen';
|
|
3
|
+
import { Project } from 'ts-morph';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
|
|
6
|
+
const discoverAgentInfo = (projectRoot, schemaDirectory) => {
|
|
7
|
+
const agentsPath = join(projectRoot, schemaDirectory, AGENTS_FILENAME);
|
|
8
|
+
if (!existsSync(agentsPath)) {
|
|
9
|
+
return { agents: [] };
|
|
10
|
+
}
|
|
11
|
+
try {
|
|
12
|
+
const project = new Project({ skipAddingFilesFromTsConfig: true, useInMemoryFileSystem: false });
|
|
13
|
+
return { agents: discoverAgents(project, join(projectRoot, schemaDirectory)) };
|
|
14
|
+
} catch (error) {
|
|
15
|
+
return { agents: [], error: error instanceof Error ? error.message : String(error) };
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export { discoverAgentInfo };
|
package/dist/packem_shared/{discoverSchemaInfo-DWtypqpP.mjs → discoverSchemaInfo-BB-CKlTK.mjs}
RENAMED
|
@@ -10,7 +10,7 @@ const discoverSchemaInfo = (projectRoot, schemaDirectory) => {
|
|
|
10
10
|
}
|
|
11
11
|
try {
|
|
12
12
|
const project = new Project({ skipAddingFilesFromTsConfig: true, useInMemoryFileSystem: false });
|
|
13
|
-
const schema = discoverSchema(project, schemaPath);
|
|
13
|
+
const schema = discoverSchema(project, schemaPath, projectRoot);
|
|
14
14
|
return {
|
|
15
15
|
info: {
|
|
16
16
|
hasGlobalTable: schema.tables.some((table) => table.shardMode === "global"),
|