@lunora/config 1.0.0-alpha.35 → 1.0.0-alpha.351
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 +135 -0
- package/README.md +3 -3
- package/dist/cloudflare/index.d.mts +1252 -0
- package/dist/cloudflare/index.d.ts +1252 -0
- package/dist/cloudflare/index.mjs +1 -0
- package/dist/index.d.mts +1048 -917
- package/dist/index.d.ts +1048 -917
- package/dist/index.mjs +1 -23
- package/dist/packem_shared/ACCENT-CotPTfv7.mjs +7 -0
- package/dist/packem_shared/AGENT_MODE_ENV-D8MvSwPE.mjs +1 -0
- package/dist/packem_shared/AGENT_RULES_DIR-HrrbNZPy.mjs +1 -0
- package/dist/packem_shared/ALLOW_FORWARDED_ENV-BUndghJx.mjs +1 -0
- package/dist/packem_shared/BINDING_MANIFEST_VERSION-CfXEYG8e.mjs +1 -0
- package/dist/packem_shared/CLOUDFLARE_CLI_CONFIG_WARNING_ENV-BKMrOuXV.mjs +1 -0
- package/dist/packem_shared/CLOUDFLARE_DRIVER-CULavrYO.mjs +1 -0
- package/dist/packem_shared/CLOUDFLARE_TOOLCHAIN_VERSIONS-DV5E_f_q.mjs +1 -0
- package/dist/packem_shared/CODEGEN_ENV-ZsCxV1kP.mjs +1 -0
- package/dist/packem_shared/COMPOSED_WORKER_ENTRY-Ciiba5g_.mjs +1 -0
- package/dist/packem_shared/DEFAULT_DEPLOY_TARGET-rR7buNQw.mjs +1 -0
- package/dist/packem_shared/DEFAULT_OBSERVABILITY-bN6UkTMx.mjs +1 -0
- package/dist/packem_shared/DEV_BINDINGS_FILE-C0ZN_XlP.mjs +4 -0
- package/dist/packem_shared/DEV_VARS_EXAMPLE_FILE-CqLorAxT.mjs +6 -0
- package/dist/packem_shared/DEV_WORKER_ENV_VALUE-2XFXmRrP.mjs +1 -0
- package/dist/packem_shared/GLOBAL_FETCH_STRICTLY_PUBLIC_FLAG-f8CnJha3.mjs +1 -0
- package/dist/packem_shared/LINKED_PROJECT_DIR-Ba5qPEwo.mjs +2 -0
- package/dist/packem_shared/LUNORA_EVENT_SOURCE-B9ZVohjO.mjs +1 -0
- package/dist/packem_shared/LUNORA_IGNORED_PATHS-U93uPxrW.mjs +19 -0
- package/dist/packem_shared/LUNORA_TAG-CiQM3BkI.mjs +1 -0
- package/dist/packem_shared/LunoraReporter-f277GLNT.mjs +6 -0
- package/dist/packem_shared/PACKAGE_SECRETS_REGISTRY-38Plje8b.mjs +1 -0
- package/dist/packem_shared/POLICY_SCAFFOLD_ENDPOINT-BmJYwAy2.mjs +1 -0
- package/dist/packem_shared/REMOTE_ELIGIBLE_KEYS-PLeh_74E.mjs +1 -0
- package/dist/packem_shared/REQUIRED_COMPATIBILITY_DATE-OLQlG0oj.mjs +1 -0
- package/dist/packem_shared/SCHEMA_EDIT_ENDPOINT-BeTxqCuQ.mjs +1 -0
- package/dist/packem_shared/SEED_ENDPOINT-2B56PN_H.mjs +1 -0
- package/dist/packem_shared/STUDIO_PATH-CSx_psKS.mjs +1 -0
- package/dist/packem_shared/UNEXPORTED_CLASS_MARKER-DwJCN8fX.mjs +1 -0
- package/dist/packem_shared/WORKERS_CACHE_MIN_DATE-0k9ABJtF.mjs +1 -0
- package/dist/packem_shared/WRANGLER_FILES-UNW-xY5u.mjs +1 -0
- package/dist/packem_shared/acceptsConnection-DHhUYGjT.mjs +2 -0
- package/dist/packem_shared/addArgsFor-CYZKhNIo.mjs +1 -0
- package/dist/packem_shared/applyAdditiveEdit-CH0VhMJ2.mjs +6 -0
- package/dist/packem_shared/applyModify-DKP2l6S9.mjs +1 -0
- package/dist/packem_shared/applyStudioAssetCache-DHQEJuuv.mjs +1 -0
- package/dist/packem_shared/assertWranglerSatisfiesSchema-Dd7ZPhw7.mjs +3 -0
- package/dist/packem_shared/assetContentType-CUb5bpbI.mjs +1 -0
- package/dist/packem_shared/buildPackageSecretsBlock-BWV_VxqV.mjs +19 -0
- package/dist/packem_shared/celld-config-D-L6uskI.mjs +3 -0
- package/dist/packem_shared/classifyPolicyEdit-DJi9Fk8G.mjs +24 -0
- package/dist/packem_shared/collectExportGaps-BPuhGH2J.mjs +2 -0
- package/dist/packem_shared/createConfirm-D5mKTMHj.mjs +7 -0
- package/dist/packem_shared/createDiscoveryCache-npJI4uej.mjs +1 -0
- package/dist/packem_shared/describePreservedCrons-C5KPuPy3.mjs +1 -0
- package/dist/packem_shared/describeWithheldWorkersAi-IIxe3TuI.mjs +1 -0
- package/dist/packem_shared/detectFramework-Dfpvu6rD.mjs +1 -0
- package/dist/packem_shared/discover-info-DC2MrAIM.mjs +1 -0
- package/dist/packem_shared/discoverAgentInfo-pqFMJBtJ.mjs +1 -0
- package/dist/packem_shared/discoverContainerInfo-DzXr7Vm3.mjs +1 -0
- package/dist/packem_shared/discoverSchemaInfo-BBRlXZop.mjs +1 -0
- package/dist/packem_shared/discoverWorkflowInfo-zW7Tt0Tn.mjs +1 -0
- package/dist/packem_shared/guards-Buu_E7mP.mjs +1 -0
- package/dist/packem_shared/hasCloudflareCredentials-byvHpEiD.mjs +1 -0
- package/dist/packem_shared/infer-bindings-C1NFOdMi.mjs +1 -0
- package/dist/packem_shared/infer-bindings.d-CFxssIAC.d.mts +480 -0
- package/dist/packem_shared/infer-bindings.d-CFxssIAC.d.ts +480 -0
- package/dist/packem_shared/inferLunoraBindings-Gp_7yyIo.mjs +1 -0
- package/dist/packem_shared/interpretRemote-CcmGeGZ_.mjs +1 -0
- package/dist/packem_shared/lunora-manifest-DuH_Cmyu.mjs +6 -0
- package/dist/packem_shared/materializeServiceDevConfigs-DLUHefD-.mjs +1 -0
- package/dist/packem_shared/mergeWranglerEnvironment-DXiB-HcS.mjs +1 -0
- package/dist/packem_shared/package-secrets-registry-BeheNwsP.mjs +1 -0
- package/dist/packem_shared/parseDevVariable-teAAahVD.mjs +1 -0
- package/dist/packem_shared/parseSchema-D1Wbr1qv.mjs +1 -0
- package/dist/packem_shared/policy-scaffold.d-D2H4_G01.d.mts +86 -0
- package/dist/packem_shared/policy-scaffold.d-D2H4_G01.d.ts +86 -0
- package/dist/packem_shared/process-tree-once-Ou4SfxKM.mjs +1 -0
- package/dist/packem_shared/readProjectDependencies-l3uhUKjo.mjs +1 -0
- package/dist/packem_shared/reconcile-services-DFqH4eMQ.mjs +1 -0
- package/dist/packem_shared/reconcileBindingsSafely-7IJ58Uit.mjs +1 -0
- package/dist/packem_shared/reconcileWranglerCompatibilityDate-hocXEuRA.mjs +1 -0
- package/dist/packem_shared/renderStudioHtml-ByowDtMl.mjs +15 -0
- package/dist/packem_shared/resolveSchemaDirectory-Ca5P6KuP.mjs +1 -0
- package/dist/packem_shared/runPostCodegenHook-Dx3yTsYZ.mjs +1 -0
- package/dist/packem_shared/scanWranglerVariablesForSecrets-BFTVje1q.mjs +1 -0
- package/dist/packem_shared/serveJsonHandler-Dv0EdCb9.mjs +1 -0
- package/dist/packem_shared/startCelldDevSession-BLFsd6jG.mjs +1 -0
- package/dist/packem_shared/streamContainerLogs-0nko1qpv.mjs +2 -0
- package/dist/packem_shared/validate-bindings-CvNBF3U4.mjs +1 -0
- package/dist/packem_shared/withTailConsumer-DngzpJMK.mjs +1 -0
- package/dist/packem_shared/worker-entry-checks-AIASCYl7.mjs +1 -0
- package/dist/packem_shared/wranglerCodegenInputs-CbisphsH.mjs +1 -0
- package/dist/packem_shared/wranglerToAlchemy-CBO2ucRm.mjs +6 -0
- package/dist/packem_shared/write-atomic-CK6VZaPI.mjs +1 -0
- package/dist/studio-host/index.d.mts +314 -110
- package/dist/studio-host/index.d.ts +314 -110
- package/dist/studio-host/index.mjs +1 -7
- package/package.json +16 -7
- package/dist/packem_shared/ACCENT-DW1XJn8i.mjs +0 -40
- package/dist/packem_shared/AGENT_RULES_DIR-lcgC08aE.mjs +0 -40
- package/dist/packem_shared/DEV_VARS_EXAMPLE_FILE-dJPNTEnK.mjs +0 -37
- package/dist/packem_shared/LINKED_PROJECT_DIR-CXwXzV_C.mjs +0 -52
- package/dist/packem_shared/LUNORA_CONFIG_FILE-CtcIcB5-.mjs +0 -34
- package/dist/packem_shared/LUNORA_EVENT_SOURCE-D2fDeGB6.mjs +0 -86
- package/dist/packem_shared/LunoraReporter-Ci-bDCK9.mjs +0 -70
- package/dist/packem_shared/PACKAGE_SECRETS_REGISTRY-B8t_SdoZ.mjs +0 -70
- package/dist/packem_shared/POLICY_SCAFFOLD_ENDPOINT-CiC2IGKx.mjs +0 -103
- package/dist/packem_shared/REMOTE_ELIGIBLE_KEYS-BC7_e9Bz.mjs +0 -105
- package/dist/packem_shared/REQUIRED_COMPATIBILITY_DATE-2YYyWJUq.mjs +0 -561
- package/dist/packem_shared/SCHEMA_EDIT_ENDPOINT-Df-Wrix-.mjs +0 -99
- package/dist/packem_shared/SEED_ENDPOINT-DVCjaGO-.mjs +0 -61
- package/dist/packem_shared/WRANGLER_FILES-DwSuC-Kn.mjs +0 -25
- package/dist/packem_shared/applyAdditiveEdit-C-snTFEV.mjs +0 -228
- package/dist/packem_shared/buildPackageSecretsBlock-DWDKHViT.mjs +0 -243
- package/dist/packem_shared/classifyPolicyEdit-BHeAqF8P.mjs +0 -99
- package/dist/packem_shared/createConfirm-fvpdgJ9s.mjs +0 -100
- package/dist/packem_shared/detectFramework-Br-BcPBq.mjs +0 -41
- package/dist/packem_shared/discoverContainerInfo-BXFs6Wav.mjs +0 -19
- package/dist/packem_shared/discoverSchemaInfo-BB-CKlTK.mjs +0 -25
- package/dist/packem_shared/discoverWorkflowInfo-CedvR0mn.mjs +0 -19
- package/dist/packem_shared/inferLunoraBindings-ByMwG-gH.mjs +0 -352
- package/dist/packem_shared/loadStudioAssets-Csk5RS4E.mjs +0 -28
- package/dist/packem_shared/parseDevVariable-CJiq2IwE.mjs +0 -30
- package/dist/packem_shared/parseSchema-DSeyktvG.mjs +0 -107
- package/dist/packem_shared/policy-scaffold.d-DCmwn7zQ.d.mts +0 -74
- package/dist/packem_shared/policy-scaffold.d-DCmwn7zQ.d.ts +0 -74
- package/dist/packem_shared/reconcileWranglerBindings-Cruwwx1M.mjs +0 -334
- package/dist/packem_shared/renderStudioHtml-449Ysn75.mjs +0 -37
- package/dist/packem_shared/serveJsonHandler-B4OLTGLS.mjs +0 -86
- package/dist/packem_shared/streamContainerLogs-BZ4cOZwH.mjs +0 -157
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import { Project, SyntaxKind } from 'ts-morph';
|
|
2
|
-
|
|
3
|
-
const OPTIONAL_VALIDATOR_PATTERN = /^v\s*\.\s*optional\s*\(/u;
|
|
4
|
-
const SHARD_BY_PATTERN = /\.shardBy\(\s*["']([^"']+)["']\s*\)/u;
|
|
5
|
-
const GLOBAL_PATTERN = /\.global\(\s*\)/u;
|
|
6
|
-
const QUOTE_PATTERN = /["']/gu;
|
|
7
|
-
const collectCalls = (node) => {
|
|
8
|
-
const calls = node.getDescendantsOfKind(SyntaxKind.CallExpression);
|
|
9
|
-
if (node.getKind() === SyntaxKind.CallExpression) {
|
|
10
|
-
calls.push(node.asKindOrThrow(SyntaxKind.CallExpression));
|
|
11
|
-
}
|
|
12
|
-
return calls;
|
|
13
|
-
};
|
|
14
|
-
const isOptionalValidator = (validatorText) => OPTIONAL_VALIDATOR_PATTERN.test(validatorText.trim());
|
|
15
|
-
const readStringArray = (node) => {
|
|
16
|
-
if (node?.getKind() !== SyntaxKind.ArrayLiteralExpression) {
|
|
17
|
-
return [];
|
|
18
|
-
}
|
|
19
|
-
return node.asKindOrThrow(SyntaxKind.ArrayLiteralExpression).getElements().filter((element) => element.getKind() === SyntaxKind.StringLiteral).map((element) => element.asKindOrThrow(SyntaxKind.StringLiteral).getLiteralText());
|
|
20
|
-
};
|
|
21
|
-
const readUnique = (node) => {
|
|
22
|
-
if (node?.getKind() !== SyntaxKind.ObjectLiteralExpression) {
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
|
-
const property = node.asKindOrThrow(SyntaxKind.ObjectLiteralExpression).getProperty("unique");
|
|
26
|
-
return property?.getKind() === SyntaxKind.PropertyAssignment && property.getInitializer()?.getText() === "true";
|
|
27
|
-
};
|
|
28
|
-
const parseIndexCall = (call) => {
|
|
29
|
-
const expression = call.getExpression();
|
|
30
|
-
if (expression.getKind() !== SyntaxKind.PropertyAccessExpression || expression.asKindOrThrow(SyntaxKind.PropertyAccessExpression).getName() !== "index") {
|
|
31
|
-
return void 0;
|
|
32
|
-
}
|
|
33
|
-
const [nameArgument, fieldsArgument, optionsArgument] = call.getArguments();
|
|
34
|
-
if (nameArgument?.getKind() !== SyntaxKind.StringLiteral) {
|
|
35
|
-
return void 0;
|
|
36
|
-
}
|
|
37
|
-
return {
|
|
38
|
-
fields: readStringArray(fieldsArgument),
|
|
39
|
-
name: nameArgument.asKindOrThrow(SyntaxKind.StringLiteral).getLiteralText(),
|
|
40
|
-
unique: readUnique(optionsArgument)
|
|
41
|
-
};
|
|
42
|
-
};
|
|
43
|
-
const parseIndexes = (initializer) => {
|
|
44
|
-
const initializerNode = initializer.getInitializer();
|
|
45
|
-
if (initializerNode === void 0) {
|
|
46
|
-
return [];
|
|
47
|
-
}
|
|
48
|
-
const indexes = [];
|
|
49
|
-
for (const call of collectCalls(initializerNode)) {
|
|
50
|
-
const index = parseIndexCall(call);
|
|
51
|
-
if (index !== void 0) {
|
|
52
|
-
indexes.push(index);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return indexes;
|
|
56
|
-
};
|
|
57
|
-
const parseColumns = (initializer) => {
|
|
58
|
-
const columns = [];
|
|
59
|
-
const defineTableCall = initializer.getInitializer()?.getDescendantsOfKind(SyntaxKind.CallExpression).find((call) => call.getExpression().getText() === "defineTable");
|
|
60
|
-
const tableShape = defineTableCall?.getArguments()[0];
|
|
61
|
-
if (tableShape?.getKind() !== SyntaxKind.ObjectLiteralExpression) {
|
|
62
|
-
return columns;
|
|
63
|
-
}
|
|
64
|
-
for (const property of tableShape.getProperties()) {
|
|
65
|
-
if (property.getKind() !== SyntaxKind.PropertyAssignment) {
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
const assignment = property;
|
|
69
|
-
const name = assignment.getName().replaceAll(QUOTE_PATTERN, "");
|
|
70
|
-
const validator = assignment.getInitializer()?.getText() ?? "";
|
|
71
|
-
columns.push({ name, optional: isOptionalValidator(validator), validator });
|
|
72
|
-
}
|
|
73
|
-
return columns;
|
|
74
|
-
};
|
|
75
|
-
const parseSchema = (source) => {
|
|
76
|
-
const project = new Project({ compilerOptions: { allowJs: true }, useInMemoryFileSystem: true });
|
|
77
|
-
const sourceFile = project.createSourceFile("schema.ts", source, { overwrite: true });
|
|
78
|
-
const defineSchemaCall = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression).find((call) => call.getExpression().getText() === "defineSchema");
|
|
79
|
-
if (defineSchemaCall === void 0) {
|
|
80
|
-
const aliased = sourceFile.getImportDeclarations().some((declaration) => declaration.getNamedImports().some((named) => named.getName() === "defineSchema" && named.getAliasNode() !== void 0));
|
|
81
|
-
return { ok: false, reason: aliased ? "aliased-define-schema" : "no-define-schema" };
|
|
82
|
-
}
|
|
83
|
-
const tablesArgument = defineSchemaCall.getArguments()[0];
|
|
84
|
-
if (tablesArgument?.getKind() !== SyntaxKind.ObjectLiteralExpression) {
|
|
85
|
-
return { ok: false, reason: "non-object-argument" };
|
|
86
|
-
}
|
|
87
|
-
const tables = [];
|
|
88
|
-
for (const property of tablesArgument.getProperties()) {
|
|
89
|
-
if (property.getKind() !== SyntaxKind.PropertyAssignment) {
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
const assignment = property;
|
|
93
|
-
const name = assignment.getName().replaceAll(QUOTE_PATTERN, "");
|
|
94
|
-
const initializerText = assignment.getInitializer()?.getText() ?? "";
|
|
95
|
-
const shardMatch = SHARD_BY_PATTERN.exec(initializerText);
|
|
96
|
-
tables.push({
|
|
97
|
-
columns: parseColumns(assignment),
|
|
98
|
-
global: GLOBAL_PATTERN.test(initializerText),
|
|
99
|
-
indexes: parseIndexes(assignment),
|
|
100
|
-
name,
|
|
101
|
-
...shardMatch?.[1] === void 0 ? {} : { shardBy: shardMatch[1] }
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
return { ok: true, tables };
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
export { collectCalls, parseSchema };
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
/** Scaffold a new policy/role/permission stub file under `lunora/`. */
|
|
2
|
-
interface ScaffoldPolicyEdit {
|
|
3
|
-
readonly kind: "scaffoldPolicy";
|
|
4
|
-
/**
|
|
5
|
-
* Base name for the generated file and its exported policy-set identifier,
|
|
6
|
-
* e.g. `invoices` → `lunora/invoices.policies.ts` exporting `invoicesPolicies`.
|
|
7
|
-
*/
|
|
8
|
-
readonly name: string;
|
|
9
|
-
/** Logical table the scaffolded policy guards (used in the stub body). */
|
|
10
|
-
readonly table: string;
|
|
11
|
-
}
|
|
12
|
-
/** Append `.use(rls(<policies>))` to an existing procedure's builder chain. */
|
|
13
|
-
interface WireRlsEdit {
|
|
14
|
-
/** Exported procedure name to wire, e.g. `listInvoices`. */
|
|
15
|
-
readonly exportName: string;
|
|
16
|
-
readonly kind: "wireRls";
|
|
17
|
-
/** Identifier of the policy set passed to `rls(...)`, e.g. `invoicesPolicies`. */
|
|
18
|
-
readonly policies: string;
|
|
19
|
-
}
|
|
20
|
-
/** Additive scaffolder edits — the only requests the scaffolder applies. */
|
|
21
|
-
type AdditivePolicyEdit = ScaffoldPolicyEdit | WireRlsEdit;
|
|
22
|
-
/**
|
|
23
|
-
* Destructive scaffolder requests — never applied. Rewriting an existing `when`
|
|
24
|
-
* body changes evaluation semantics silently, so it is refused (STOP condition
|
|
25
|
-
* in plan 025); carried as data so the editor can describe the request.
|
|
26
|
-
*/
|
|
27
|
-
interface DestructivePolicyEdit {
|
|
28
|
-
readonly exportName?: string;
|
|
29
|
-
readonly kind: "rewritePolicyWhen";
|
|
30
|
-
readonly table?: string;
|
|
31
|
-
}
|
|
32
|
-
/** Any request the scaffolder can receive. */
|
|
33
|
-
type PolicyEdit = AdditivePolicyEdit | DestructivePolicyEdit;
|
|
34
|
-
/**
|
|
35
|
-
* Classify a scaffolder request. Additive requests ({@link AdditivePolicyEdit})
|
|
36
|
-
* apply directly; everything else (rewriting an existing predicate) changes
|
|
37
|
-
* evaluation semantics and is destructive.
|
|
38
|
-
*/
|
|
39
|
-
declare const classifyPolicyEdit: (edit: PolicyEdit) => "additive" | "destructive";
|
|
40
|
-
/** Failure reasons a scaffolder request can report. */
|
|
41
|
-
type PolicyScaffoldFailureReason = "already-wired" | "destructive" | "invalid-identifier" | "unknown-procedure" | "unsupported-procedure-shape";
|
|
42
|
-
/** Tagged result of generating a stub file. */
|
|
43
|
-
type ScaffoldFileResult = {
|
|
44
|
-
fileName: string;
|
|
45
|
-
ok: true;
|
|
46
|
-
source: string;
|
|
47
|
-
} | {
|
|
48
|
-
ok: false;
|
|
49
|
-
reason: PolicyScaffoldFailureReason;
|
|
50
|
-
};
|
|
51
|
-
/** Tagged result of wiring a procedure. */
|
|
52
|
-
type WireResult = {
|
|
53
|
-
ok: false;
|
|
54
|
-
reason: PolicyScaffoldFailureReason;
|
|
55
|
-
} | {
|
|
56
|
-
ok: true;
|
|
57
|
-
text: string;
|
|
58
|
-
};
|
|
59
|
-
/**
|
|
60
|
-
* Generate the source of a new policy/role/permission stub file. The `when`
|
|
61
|
-
* predicate is a `() => false` skeleton with a TODO — the scaffolder never
|
|
62
|
-
* authors real logic, the developer fills it in. Pure (no I/O); the handler
|
|
63
|
-
* writes the returned source and refuses to overwrite an existing file.
|
|
64
|
-
*/
|
|
65
|
-
declare const scaffoldPolicyFile: (edit: ScaffoldPolicyEdit) => ScaffoldFileResult;
|
|
66
|
-
/**
|
|
67
|
-
* Append `.use(rls(<policies>))` to a procedure's builder chain, preserving the
|
|
68
|
-
* terminal `.query(handler)` (and its handler body) byte-for-byte. Only the
|
|
69
|
-
* **builder** form can be wired; the bare-factory form (`query({ handler })`)
|
|
70
|
-
* has no chain and is reported `unsupported-procedure-shape` so the editor can
|
|
71
|
-
* tell the developer to convert it rather than silently rewriting their code.
|
|
72
|
-
*/
|
|
73
|
-
declare const wireRlsIntoProcedure: (source: string, edit: WireRlsEdit) => WireResult;
|
|
74
|
-
export { AdditivePolicyEdit as A, DestructivePolicyEdit as D, PolicyEdit as P, ScaffoldPolicyEdit as S, WireRlsEdit as W, PolicyScaffoldFailureReason as a, ScaffoldFileResult as b, WireResult as c, classifyPolicyEdit as d, scaffoldPolicyFile as s, wireRlsIntoProcedure as w };
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
/** Scaffold a new policy/role/permission stub file under `lunora/`. */
|
|
2
|
-
interface ScaffoldPolicyEdit {
|
|
3
|
-
readonly kind: "scaffoldPolicy";
|
|
4
|
-
/**
|
|
5
|
-
* Base name for the generated file and its exported policy-set identifier,
|
|
6
|
-
* e.g. `invoices` → `lunora/invoices.policies.ts` exporting `invoicesPolicies`.
|
|
7
|
-
*/
|
|
8
|
-
readonly name: string;
|
|
9
|
-
/** Logical table the scaffolded policy guards (used in the stub body). */
|
|
10
|
-
readonly table: string;
|
|
11
|
-
}
|
|
12
|
-
/** Append `.use(rls(<policies>))` to an existing procedure's builder chain. */
|
|
13
|
-
interface WireRlsEdit {
|
|
14
|
-
/** Exported procedure name to wire, e.g. `listInvoices`. */
|
|
15
|
-
readonly exportName: string;
|
|
16
|
-
readonly kind: "wireRls";
|
|
17
|
-
/** Identifier of the policy set passed to `rls(...)`, e.g. `invoicesPolicies`. */
|
|
18
|
-
readonly policies: string;
|
|
19
|
-
}
|
|
20
|
-
/** Additive scaffolder edits — the only requests the scaffolder applies. */
|
|
21
|
-
type AdditivePolicyEdit = ScaffoldPolicyEdit | WireRlsEdit;
|
|
22
|
-
/**
|
|
23
|
-
* Destructive scaffolder requests — never applied. Rewriting an existing `when`
|
|
24
|
-
* body changes evaluation semantics silently, so it is refused (STOP condition
|
|
25
|
-
* in plan 025); carried as data so the editor can describe the request.
|
|
26
|
-
*/
|
|
27
|
-
interface DestructivePolicyEdit {
|
|
28
|
-
readonly exportName?: string;
|
|
29
|
-
readonly kind: "rewritePolicyWhen";
|
|
30
|
-
readonly table?: string;
|
|
31
|
-
}
|
|
32
|
-
/** Any request the scaffolder can receive. */
|
|
33
|
-
type PolicyEdit = AdditivePolicyEdit | DestructivePolicyEdit;
|
|
34
|
-
/**
|
|
35
|
-
* Classify a scaffolder request. Additive requests ({@link AdditivePolicyEdit})
|
|
36
|
-
* apply directly; everything else (rewriting an existing predicate) changes
|
|
37
|
-
* evaluation semantics and is destructive.
|
|
38
|
-
*/
|
|
39
|
-
declare const classifyPolicyEdit: (edit: PolicyEdit) => "additive" | "destructive";
|
|
40
|
-
/** Failure reasons a scaffolder request can report. */
|
|
41
|
-
type PolicyScaffoldFailureReason = "already-wired" | "destructive" | "invalid-identifier" | "unknown-procedure" | "unsupported-procedure-shape";
|
|
42
|
-
/** Tagged result of generating a stub file. */
|
|
43
|
-
type ScaffoldFileResult = {
|
|
44
|
-
fileName: string;
|
|
45
|
-
ok: true;
|
|
46
|
-
source: string;
|
|
47
|
-
} | {
|
|
48
|
-
ok: false;
|
|
49
|
-
reason: PolicyScaffoldFailureReason;
|
|
50
|
-
};
|
|
51
|
-
/** Tagged result of wiring a procedure. */
|
|
52
|
-
type WireResult = {
|
|
53
|
-
ok: false;
|
|
54
|
-
reason: PolicyScaffoldFailureReason;
|
|
55
|
-
} | {
|
|
56
|
-
ok: true;
|
|
57
|
-
text: string;
|
|
58
|
-
};
|
|
59
|
-
/**
|
|
60
|
-
* Generate the source of a new policy/role/permission stub file. The `when`
|
|
61
|
-
* predicate is a `() => false` skeleton with a TODO — the scaffolder never
|
|
62
|
-
* authors real logic, the developer fills it in. Pure (no I/O); the handler
|
|
63
|
-
* writes the returned source and refuses to overwrite an existing file.
|
|
64
|
-
*/
|
|
65
|
-
declare const scaffoldPolicyFile: (edit: ScaffoldPolicyEdit) => ScaffoldFileResult;
|
|
66
|
-
/**
|
|
67
|
-
* Append `.use(rls(<policies>))` to a procedure's builder chain, preserving the
|
|
68
|
-
* terminal `.query(handler)` (and its handler body) byte-for-byte. Only the
|
|
69
|
-
* **builder** form can be wired; the bare-factory form (`query({ handler })`)
|
|
70
|
-
* has no chain and is reported `unsupported-procedure-shape` so the editor can
|
|
71
|
-
* tell the developer to convert it rather than silently rewriting their code.
|
|
72
|
-
*/
|
|
73
|
-
declare const wireRlsIntoProcedure: (source: string, edit: WireRlsEdit) => WireResult;
|
|
74
|
-
export { AdditivePolicyEdit as A, DestructivePolicyEdit as D, PolicyEdit as P, ScaffoldPolicyEdit as S, WireRlsEdit as W, PolicyScaffoldFailureReason as a, ScaffoldFileResult as b, WireResult as c, classifyPolicyEdit as d, scaffoldPolicyFile as s, wireRlsIntoProcedure as w };
|
|
@@ -1,334 +0,0 @@
|
|
|
1
|
-
import { writeFileSync } from 'node:fs';
|
|
2
|
-
import { containerBuildTag } from '@lunora/container';
|
|
3
|
-
import { modify, applyEdits } from 'jsonc-parser';
|
|
4
|
-
import { findWranglerFile, readWranglerJsonc } from './WRANGLER_FILES-DwSuC-Kn.mjs';
|
|
5
|
-
|
|
6
|
-
const FORMATTING = { formattingOptions: { insertSpaces: true, tabSize: 4 } };
|
|
7
|
-
const D1_PLACEHOLDER_ID = "<replace-with-d1-create-id>";
|
|
8
|
-
const collectExportGaps = (inferred) => {
|
|
9
|
-
const gaps = [];
|
|
10
|
-
for (const container of inferred.containers) {
|
|
11
|
-
if (!container.exported) {
|
|
12
|
-
gaps.push({ className: container.className, exportName: container.exportName, kind: "container", module: "containers" });
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
for (const workflow of inferred.workflows) {
|
|
16
|
-
if (!workflow.exported) {
|
|
17
|
-
gaps.push({ className: workflow.className, exportName: workflow.exportName, kind: "workflow", module: "workflows" });
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
return gaps;
|
|
21
|
-
};
|
|
22
|
-
const collectHintBindingWarnings = (inferred, parsed) => {
|
|
23
|
-
const flagshipBindingMissing = inferred.flagshipBinding !== void 0 && !(parsed?.flagship ?? []).some((entry) => entry.binding === inferred.flagshipBinding);
|
|
24
|
-
const rules = [
|
|
25
|
-
[
|
|
26
|
-
inferred.usesKv && (parsed?.kv_namespaces?.length ?? 0) === 0,
|
|
27
|
-
"@lunora/bindings/kv is used but no kv_namespaces binding exists; add a kv_namespaces entry ({ binding, id }) and pass env.<BINDING> to createKv() — the namespace id can't be auto-provisioned."
|
|
28
|
-
],
|
|
29
|
-
[
|
|
30
|
-
inferred.usesHyperdrive && (parsed?.hyperdrive?.length ?? 0) === 0,
|
|
31
|
-
"@lunora/hyperdrive is used but no hyperdrive binding exists; run 'wrangler hyperdrive create' and add a 'hyperdrive' binding ({ binding, id }) — the id can't be auto-provisioned."
|
|
32
|
-
],
|
|
33
|
-
[
|
|
34
|
-
inferred.usesPipelines && (parsed?.pipelines?.length ?? 0) === 0,
|
|
35
|
-
"ctx.pipelines is used but no pipelines binding exists; run 'wrangler pipelines create <name>' and add a 'pipelines' binding ({ binding, pipeline }) — the pipeline resource can't be auto-provisioned."
|
|
36
|
-
],
|
|
37
|
-
[
|
|
38
|
-
flagshipBindingMissing,
|
|
39
|
-
`lunora/flags.ts uses Flagship in binding mode but no flagship binding "${inferred.flagshipBinding ?? ""}" exists; add a flagship entry ({ binding: "${inferred.flagshipBinding ?? ""}", app_id }) — the app_id can't be auto-provisioned.`
|
|
40
|
-
]
|
|
41
|
-
];
|
|
42
|
-
return rules.filter(([active]) => active).map(([, warning]) => warning);
|
|
43
|
-
};
|
|
44
|
-
const collectWarnings = (inferred, parsed) => {
|
|
45
|
-
const exported = new Set(inferred.durableObjects.map((object) => object.className));
|
|
46
|
-
const warnings = [];
|
|
47
|
-
const hasR2Bucket = (parsed?.r2_buckets?.length ?? 0) > 0;
|
|
48
|
-
const hasSessionStore = (parsed?.d1_databases?.some((binding) => binding.binding === "DB") ?? false) || inferred.needsD1;
|
|
49
|
-
if (inferred.usesStorage && !hasR2Bucket) {
|
|
50
|
-
warnings.push(
|
|
51
|
-
"@lunora/storage is used but R2 bucket bindings have user-defined names; add an r2_buckets entry and pass env.<BINDING> to createStorage()."
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
if (inferred.usesAuth && !exported.has("SessionDO") && !hasSessionStore) {
|
|
55
|
-
warnings.push(
|
|
56
|
-
"@lunora/auth is used but the worker entry exports no SessionDO; sessions are D1-backed, or export SessionDO to enable DO-backed sessions."
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
if (inferred.usesScheduler && !exported.has("SchedulerDO")) {
|
|
60
|
-
warnings.push("@lunora/scheduler is used but the worker entry exports no SchedulerDO; export it so the SCHEDULER binding can be provisioned.");
|
|
61
|
-
}
|
|
62
|
-
for (const container of inferred.containers) {
|
|
63
|
-
if (!container.exported) {
|
|
64
|
-
warnings.push(
|
|
65
|
-
`container "${container.exportName}" is declared but ${container.className} is not exported by the worker entry; add \`export * from "./lunora/_generated/containers"\` so its binding can be provisioned.`
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
for (const workflow of inferred.workflows) {
|
|
70
|
-
if (!workflow.exported) {
|
|
71
|
-
warnings.push(
|
|
72
|
-
`workflow "${workflow.exportName}" is declared but ${workflow.className} is not exported by the worker entry; add \`export * from "./lunora/_generated/workflows"\` so its binding can be provisioned.`
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
if (inferred.containers.length > 0 && parsed?.observability?.enabled === false) {
|
|
77
|
-
warnings.push("containers are declared but observability is explicitly disabled in wrangler.jsonc — container logs will not be captured.");
|
|
78
|
-
}
|
|
79
|
-
if (inferred.usesPayment) {
|
|
80
|
-
warnings.push(
|
|
81
|
-
"@lunora/payment is used; set the provider secrets in .dev.vars — STRIPE_SECRET_KEY + STRIPE_WEBHOOK_SECRET (Stripe) or POLAR_ACCESS_TOKEN + POLAR_WEBHOOK_SECRET (Polar)."
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
warnings.push(...collectHintBindingWarnings(inferred, parsed));
|
|
85
|
-
return warnings;
|
|
86
|
-
};
|
|
87
|
-
const applyModify = (text, path, value) => {
|
|
88
|
-
const edits = modify(text, [...path], value, FORMATTING);
|
|
89
|
-
return edits.length > 0 ? applyEdits(text, edits) : text;
|
|
90
|
-
};
|
|
91
|
-
const nextMigrationTag = (migrations) => {
|
|
92
|
-
const used = new Set(migrations.map((migration) => migration.tag));
|
|
93
|
-
let index = 1;
|
|
94
|
-
while (used.has(`v${String(index)}`)) {
|
|
95
|
-
index += 1;
|
|
96
|
-
}
|
|
97
|
-
return `v${String(index)}`;
|
|
98
|
-
};
|
|
99
|
-
const reconcileDurableObjects = (text, parsed, required) => {
|
|
100
|
-
const existingBindings = parsed.durable_objects?.bindings ?? [];
|
|
101
|
-
const existingNames = new Set(existingBindings.map((binding) => binding.name));
|
|
102
|
-
const missing = required.filter((object) => !existingNames.has(object.binding));
|
|
103
|
-
let nextText = text;
|
|
104
|
-
const added = [];
|
|
105
|
-
if (missing.length > 0) {
|
|
106
|
-
const nextBindings = [
|
|
107
|
-
...existingBindings,
|
|
108
|
-
...missing.map((object) => {
|
|
109
|
-
return { class_name: object.className, name: object.binding };
|
|
110
|
-
})
|
|
111
|
-
];
|
|
112
|
-
nextText = applyModify(nextText, ["durable_objects", "bindings"], nextBindings);
|
|
113
|
-
added.push(...missing.map((object) => `${object.binding}/${object.className}`));
|
|
114
|
-
}
|
|
115
|
-
const migrations = parsed.migrations ?? [];
|
|
116
|
-
const registered = new Set(migrations.flatMap((migration) => [...migration.new_sqlite_classes ?? [], ...migration.new_classes ?? []]));
|
|
117
|
-
const missingClasses = required.map((object) => object.className).filter((className) => !registered.has(className));
|
|
118
|
-
if (missingClasses.length > 0) {
|
|
119
|
-
const nextMigrations = [...migrations, { new_sqlite_classes: missingClasses, tag: nextMigrationTag(migrations) }];
|
|
120
|
-
nextText = applyModify(nextText, ["migrations"], nextMigrations);
|
|
121
|
-
}
|
|
122
|
-
return { added, text: nextText };
|
|
123
|
-
};
|
|
124
|
-
const reconcileD1 = (text, parsed) => {
|
|
125
|
-
const d1Bindings = parsed.d1_databases ?? [];
|
|
126
|
-
if (d1Bindings.some((binding) => binding.binding === "DB")) {
|
|
127
|
-
return { added: [], text };
|
|
128
|
-
}
|
|
129
|
-
const databaseName = typeof parsed.name === "string" && parsed.name.length > 0 ? parsed.name : "lunora";
|
|
130
|
-
const nextD1 = [...d1Bindings, { binding: "DB", database_id: D1_PLACEHOLDER_ID, database_name: databaseName }];
|
|
131
|
-
return { added: ["DB (D1)"], text: applyModify(text, ["d1_databases"], nextD1) };
|
|
132
|
-
};
|
|
133
|
-
const reconcileSelfDescribing = (text, parsed, key, binding, label) => {
|
|
134
|
-
const current = parsed[key]?.binding;
|
|
135
|
-
if (typeof current === "string" && current.length > 0) {
|
|
136
|
-
return { added: [], text };
|
|
137
|
-
}
|
|
138
|
-
return { added: [label], text: applyModify(text, [key], { binding }) };
|
|
139
|
-
};
|
|
140
|
-
const reconcileAnalytics = (text, parsed) => {
|
|
141
|
-
if ((parsed.analytics_engine_datasets?.length ?? 0) > 0) {
|
|
142
|
-
return { added: [], text };
|
|
143
|
-
}
|
|
144
|
-
const nextDatasets = [{ binding: "ANALYTICS", dataset: "ANALYTICS" }];
|
|
145
|
-
return { added: ["ANALYTICS (Analytics Engine)"], text: applyModify(text, ["analytics_engine_datasets"], nextDatasets) };
|
|
146
|
-
};
|
|
147
|
-
const wranglerInstanceType = (instanceType) => {
|
|
148
|
-
if (typeof instanceType === "string") {
|
|
149
|
-
return instanceType;
|
|
150
|
-
}
|
|
151
|
-
const custom = {};
|
|
152
|
-
if (instanceType.diskMb !== void 0) {
|
|
153
|
-
custom.disk_mb = instanceType.diskMb;
|
|
154
|
-
}
|
|
155
|
-
if (instanceType.memoryMib !== void 0) {
|
|
156
|
-
custom.memory_mib = instanceType.memoryMib;
|
|
157
|
-
}
|
|
158
|
-
if (instanceType.vcpu !== void 0) {
|
|
159
|
-
custom.vcpu = instanceType.vcpu;
|
|
160
|
-
}
|
|
161
|
-
return custom;
|
|
162
|
-
};
|
|
163
|
-
const imageRefFor = (container) => {
|
|
164
|
-
if (container.image.kind === "dockerfile") {
|
|
165
|
-
return container.image.dockerfilePath;
|
|
166
|
-
}
|
|
167
|
-
if (container.image.kind === "registry") {
|
|
168
|
-
return container.image.reference;
|
|
169
|
-
}
|
|
170
|
-
return containerBuildTag(container.exportName);
|
|
171
|
-
};
|
|
172
|
-
const containerEntryFor = (container) => {
|
|
173
|
-
const entry = {
|
|
174
|
-
class_name: container.className,
|
|
175
|
-
image: imageRefFor(container)
|
|
176
|
-
};
|
|
177
|
-
if (container.image.kind === "dockerfile") {
|
|
178
|
-
entry.image_build_context = container.image.buildContext;
|
|
179
|
-
}
|
|
180
|
-
if (container.buildArgs !== void 0 && container.image.kind !== "registry") {
|
|
181
|
-
entry.image_vars = container.buildArgs;
|
|
182
|
-
}
|
|
183
|
-
if (container.instanceType !== void 0) {
|
|
184
|
-
entry.instance_type = wranglerInstanceType(container.instanceType);
|
|
185
|
-
}
|
|
186
|
-
if (container.maxInstances !== void 0) {
|
|
187
|
-
entry.max_instances = container.maxInstances;
|
|
188
|
-
}
|
|
189
|
-
if (container.name !== void 0) {
|
|
190
|
-
entry.name = container.name;
|
|
191
|
-
}
|
|
192
|
-
if (container.rollout?.stepPercentage !== void 0) {
|
|
193
|
-
entry.rollout_step_percentage = container.rollout.stepPercentage;
|
|
194
|
-
}
|
|
195
|
-
if (container.rollout?.gracePeriodSeconds !== void 0) {
|
|
196
|
-
entry.rollout_active_grace_period = container.rollout.gracePeriodSeconds;
|
|
197
|
-
}
|
|
198
|
-
return entry;
|
|
199
|
-
};
|
|
200
|
-
const reconcileContainers = (text, parsed, containers) => {
|
|
201
|
-
const existing = parsed.containers ?? [];
|
|
202
|
-
const existingClasses = new Set(existing.map((entry) => entry.class_name));
|
|
203
|
-
const missing = containers.filter((container) => !existingClasses.has(container.className));
|
|
204
|
-
if (missing.length === 0) {
|
|
205
|
-
return { added: [], text };
|
|
206
|
-
}
|
|
207
|
-
const nextText = applyModify(text, ["containers"], [...existing, ...missing.map((container) => containerEntryFor(container))]);
|
|
208
|
-
return { added: missing.map((container) => `containers/${container.className}`), text: nextText };
|
|
209
|
-
};
|
|
210
|
-
const reconcileObservability = (text, parsed) => {
|
|
211
|
-
if (parsed.observability !== void 0) {
|
|
212
|
-
return { added: [], text };
|
|
213
|
-
}
|
|
214
|
-
const nextText = applyModify(text, ["observability"], { enabled: true, head_sampling_rate: 1 });
|
|
215
|
-
return { added: ["observability"], text: nextText };
|
|
216
|
-
};
|
|
217
|
-
const workflowEntryFor = (workflow) => {
|
|
218
|
-
return { binding: workflow.bindingName, class_name: workflow.className, name: workflow.name };
|
|
219
|
-
};
|
|
220
|
-
const reconcileWorkflows = (text, parsed, workflows) => {
|
|
221
|
-
const existing = parsed.workflows ?? [];
|
|
222
|
-
const existingClasses = new Set(existing.map((entry) => entry.class_name));
|
|
223
|
-
const missing = workflows.filter((workflow) => !existingClasses.has(workflow.className));
|
|
224
|
-
if (missing.length === 0) {
|
|
225
|
-
return { added: [], text };
|
|
226
|
-
}
|
|
227
|
-
const nextText = applyModify(text, ["workflows"], [...existing, ...missing.map((workflow) => workflowEntryFor(workflow))]);
|
|
228
|
-
return { added: missing.map((workflow) => `workflows/${workflow.className}`), text: nextText };
|
|
229
|
-
};
|
|
230
|
-
const reconcileQueues = (text, parsed, queues) => {
|
|
231
|
-
const existing = parsed.queues ?? {};
|
|
232
|
-
const existingProducers = existing.producers ?? [];
|
|
233
|
-
const existingConsumers = existing.consumers ?? [];
|
|
234
|
-
const haveProducer = new Set(existingProducers.map((entry) => entry.binding));
|
|
235
|
-
const haveConsumer = new Set(existingConsumers.map((entry) => entry.queue));
|
|
236
|
-
const missingProducers = queues.filter((queue) => !haveProducer.has(queue.bindingName));
|
|
237
|
-
const missingConsumers = queues.filter((queue) => !haveConsumer.has(queue.name));
|
|
238
|
-
if (missingProducers.length === 0 && missingConsumers.length === 0) {
|
|
239
|
-
return { added: [], text };
|
|
240
|
-
}
|
|
241
|
-
const nextProducers = [
|
|
242
|
-
...existingProducers,
|
|
243
|
-
...missingProducers.map((queue) => {
|
|
244
|
-
return { binding: queue.bindingName, queue: queue.name };
|
|
245
|
-
})
|
|
246
|
-
];
|
|
247
|
-
const nextConsumers = [
|
|
248
|
-
...existingConsumers,
|
|
249
|
-
...missingConsumers.map((queue) => {
|
|
250
|
-
const consumer = { queue: queue.name };
|
|
251
|
-
if (queue.mode === "pull") {
|
|
252
|
-
consumer.type = "http_pull";
|
|
253
|
-
}
|
|
254
|
-
if (queue.tuning.maxBatchSize !== void 0) {
|
|
255
|
-
consumer.max_batch_size = queue.tuning.maxBatchSize;
|
|
256
|
-
}
|
|
257
|
-
if (queue.tuning.maxBatchTimeout !== void 0) {
|
|
258
|
-
consumer.max_batch_timeout = queue.tuning.maxBatchTimeout;
|
|
259
|
-
}
|
|
260
|
-
if (queue.tuning.maxRetries !== void 0) {
|
|
261
|
-
consumer.max_retries = queue.tuning.maxRetries;
|
|
262
|
-
}
|
|
263
|
-
if (queue.tuning.deadLetterQueue !== void 0) {
|
|
264
|
-
consumer.dead_letter_queue = queue.tuning.deadLetterQueue;
|
|
265
|
-
}
|
|
266
|
-
if (queue.tuning.retryDelay !== void 0) {
|
|
267
|
-
consumer.retry_delay = queue.tuning.retryDelay;
|
|
268
|
-
}
|
|
269
|
-
return consumer;
|
|
270
|
-
})
|
|
271
|
-
];
|
|
272
|
-
const nextText = applyModify(text, ["queues"], { consumers: nextConsumers, producers: nextProducers });
|
|
273
|
-
return {
|
|
274
|
-
added: [
|
|
275
|
-
...missingProducers.map((queue) => `queues.producers/${queue.bindingName}`),
|
|
276
|
-
...missingConsumers.map((queue) => `queues.consumers/${queue.name}`)
|
|
277
|
-
],
|
|
278
|
-
text: nextText
|
|
279
|
-
};
|
|
280
|
-
};
|
|
281
|
-
const reconcileWranglerBindings = (projectRoot, inferred) => {
|
|
282
|
-
const wranglerPath = findWranglerFile(projectRoot);
|
|
283
|
-
const exportGaps = collectExportGaps(inferred);
|
|
284
|
-
if (!wranglerPath) {
|
|
285
|
-
return { added: [], changed: false, exportGaps, reason: "wrangler.jsonc not found", warnings: collectWarnings(inferred) };
|
|
286
|
-
}
|
|
287
|
-
const { parsed, text: original } = readWranglerJsonc(wranglerPath);
|
|
288
|
-
if (parsed === void 0) {
|
|
289
|
-
return { added: [], changed: false, exportGaps, reason: `failed to parse ${wranglerPath} as JSONC`, warnings: collectWarnings(inferred), wranglerPath };
|
|
290
|
-
}
|
|
291
|
-
const warnings = collectWarnings(inferred, parsed);
|
|
292
|
-
const exportedContainers = inferred.containers.filter((container) => container.exported);
|
|
293
|
-
const requiredDurableObjects = [
|
|
294
|
-
...inferred.durableObjects,
|
|
295
|
-
...exportedContainers.map((container) => {
|
|
296
|
-
return { binding: container.bindingName, className: container.className };
|
|
297
|
-
})
|
|
298
|
-
];
|
|
299
|
-
const exportedWorkflows = inferred.workflows.filter((workflow) => workflow.exported);
|
|
300
|
-
const pipeline = [
|
|
301
|
-
{ enabled: true, run: (text2) => reconcileDurableObjects(text2, parsed, requiredDurableObjects) },
|
|
302
|
-
{ enabled: inferred.needsD1, run: (text2) => reconcileD1(text2, parsed) },
|
|
303
|
-
{ enabled: inferred.usesAi, run: (text2) => reconcileSelfDescribing(text2, parsed, "ai", "AI", "AI (Workers AI)") },
|
|
304
|
-
{ enabled: inferred.usesBrowser, run: (text2) => reconcileSelfDescribing(text2, parsed, "browser", "BROWSER", "BROWSER (Browser Rendering)") },
|
|
305
|
-
{ enabled: inferred.usesImages, run: (text2) => reconcileSelfDescribing(text2, parsed, "images", "IMAGES", "IMAGES (Cloudflare Images)") },
|
|
306
|
-
{ enabled: inferred.usesAnalytics, run: (text2) => reconcileAnalytics(text2, parsed) },
|
|
307
|
-
{ enabled: true, run: (text2) => reconcileObservability(text2, parsed) },
|
|
308
|
-
{ enabled: exportedContainers.length > 0, run: (text2) => reconcileContainers(text2, parsed, exportedContainers) },
|
|
309
|
-
{ enabled: exportedWorkflows.length > 0, run: (text2) => reconcileWorkflows(text2, parsed, exportedWorkflows) },
|
|
310
|
-
{ enabled: inferred.queues.length > 0, run: (text2) => reconcileQueues(text2, parsed, inferred.queues) }
|
|
311
|
-
];
|
|
312
|
-
let text = original;
|
|
313
|
-
const added = [];
|
|
314
|
-
for (const step of pipeline) {
|
|
315
|
-
if (!step.enabled) {
|
|
316
|
-
continue;
|
|
317
|
-
}
|
|
318
|
-
const result = step.run(text);
|
|
319
|
-
text = result.text;
|
|
320
|
-
added.push(...result.added);
|
|
321
|
-
}
|
|
322
|
-
if (added.includes("DB (D1)")) {
|
|
323
|
-
warnings.push(
|
|
324
|
-
`wrote a DB binding with a placeholder database_id ("${D1_PLACEHOLDER_ID}") — run \`wrangler d1 create <name>\` and replace it before deploying.`
|
|
325
|
-
);
|
|
326
|
-
}
|
|
327
|
-
if (text === original) {
|
|
328
|
-
return { added: [], changed: false, exportGaps, reason: "bindings already in sync", warnings, wranglerPath };
|
|
329
|
-
}
|
|
330
|
-
writeFileSync(wranglerPath, text, "utf8");
|
|
331
|
-
return { added, changed: true, exportGaps, warnings, wranglerPath };
|
|
332
|
-
};
|
|
333
|
-
|
|
334
|
-
export { reconcileWranglerBindings };
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
const forInlineScript = (value) => JSON.stringify(value).replaceAll("<", String.raw`\u003c`);
|
|
2
|
-
const forAttribute = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("<", "<");
|
|
3
|
-
const renderStudioHtml = (config) => {
|
|
4
|
-
const settings = [`window.__LUNORA_BASE_PATH__=${forInlineScript(config.basePath)};`];
|
|
5
|
-
if (config.adminToken !== void 0 && config.adminToken !== "") {
|
|
6
|
-
settings.push(`window.__LUNORA_ADMIN_TOKEN__=${forInlineScript(config.adminToken)};`);
|
|
7
|
-
}
|
|
8
|
-
if (config.dataEditable === true) {
|
|
9
|
-
settings.push("window.__LUNORA_DATA_EDITABLE__=true;");
|
|
10
|
-
}
|
|
11
|
-
if (config.runAsIdentity === true) {
|
|
12
|
-
settings.push("window.__LUNORA_RUN_AS_IDENTITY__=true;");
|
|
13
|
-
}
|
|
14
|
-
if (config.schemaEditable === true) {
|
|
15
|
-
settings.push("window.__LUNORA_SCHEMA_EDITABLE__=true;");
|
|
16
|
-
}
|
|
17
|
-
if (config.rulesInstalled === false) {
|
|
18
|
-
settings.push("window.__LUNORA_RULES_INSTALLED__=false;");
|
|
19
|
-
}
|
|
20
|
-
return `<!doctype html>
|
|
21
|
-
<html lang="en">
|
|
22
|
-
<head>
|
|
23
|
-
<meta charset="UTF-8" />
|
|
24
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
25
|
-
<title>Lunora Studio</title>
|
|
26
|
-
<script>${settings.join("")}<\/script>
|
|
27
|
-
<link rel="stylesheet" href="${forAttribute(config.styleHref)}" />
|
|
28
|
-
</head>
|
|
29
|
-
<body>
|
|
30
|
-
<div id="root"></div>
|
|
31
|
-
<script type="module" src="${forAttribute(config.scriptSrc)}"><\/script>
|
|
32
|
-
</body>
|
|
33
|
-
</html>
|
|
34
|
-
`;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export { renderStudioHtml as default };
|