@lunora/codegen 1.0.0-alpha.17 → 1.0.0-alpha.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +13 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.mjs +5 -5
- package/dist/packem_shared/{GENERATED_HEADER-BoVKLcnE.mjs → GENERATED_HEADER-D-AbhmRh.mjs} +27 -5
- package/dist/packem_shared/{OPENRPC_VERSION-BMCOe3B6.mjs → OPENRPC_VERSION-DDT4mIzD.mjs} +1 -1
- package/dist/packem_shared/{SCHEMA_SNAPSHOT_FILENAME-BA9tjjOl.mjs → SCHEMA_SNAPSHOT_FILENAME-ExbveiC6.mjs} +14 -4
- package/dist/packem_shared/{buildOpenApiDocument-CB2brlbc.mjs → buildOpenApiDocument-DoK7_x1g.mjs} +1 -1
- package/dist/packem_shared/{emitApp-Bh0HsQVK.mjs → emitApp-CV81L74c.mjs} +48 -6
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1099,6 +1099,13 @@ declare const emitApi: (functions: ReadonlyArray<FunctionIR>, workflows?: Readon
|
|
|
1099
1099
|
declare const emitCollections: (shapes: ReadonlyArray<ShapeIR>, hasDatabase: boolean, useUmbrella?: boolean) => string;
|
|
1100
1100
|
interface EmitServerOptions {
|
|
1101
1101
|
containers?: ReadonlyArray<ContainerIR>;
|
|
1102
|
+
/**
|
|
1103
|
+
* A `lunora/` source reads `ctx.access` — wires the verified Cloudflare Access
|
|
1104
|
+
* facade (`@lunora/cloudflare-access/context`) onto every ctx. Distinct from
|
|
1105
|
+
* `emitApp`'s `hasAccess` (which gates the worker's `.access()` resolveIdentity
|
|
1106
|
+
* method); this one gates the per-request `ctx.access` read surface.
|
|
1107
|
+
*/
|
|
1108
|
+
hasAccessFacade?: boolean;
|
|
1102
1109
|
hasAi?: boolean;
|
|
1103
1110
|
/** A `lunora/` source uses `@lunora/bindings/analytics` / `ctx.analytics` — wires the write helper onto every ctx. */
|
|
1104
1111
|
hasAnalytics?: boolean;
|
|
@@ -1127,6 +1134,7 @@ interface EmitServerOptions {
|
|
|
1127
1134
|
}
|
|
1128
1135
|
declare const emitServer: ({
|
|
1129
1136
|
containers,
|
|
1137
|
+
hasAccessFacade,
|
|
1130
1138
|
hasAi,
|
|
1131
1139
|
hasAnalytics,
|
|
1132
1140
|
hasBrowser,
|
|
@@ -1187,6 +1195,8 @@ interface EmitShardOptions {
|
|
|
1187
1195
|
key: string;
|
|
1188
1196
|
type: "boolean" | "number" | "object" | "string";
|
|
1189
1197
|
}>;
|
|
1198
|
+
/** A `lunora/` source reads `ctx.access` — wires the verified Cloudflare Access facade onto every ctx. */
|
|
1199
|
+
hasAccessFacade?: boolean;
|
|
1190
1200
|
hasAi?: boolean;
|
|
1191
1201
|
/** A `lunora/` source reads `ctx.analytics` — wires the Analytics Engine write helper onto every ctx. */
|
|
1192
1202
|
hasAnalytics?: boolean;
|
|
@@ -1224,6 +1234,7 @@ declare const emitShard: ({
|
|
|
1224
1234
|
advisories,
|
|
1225
1235
|
containers,
|
|
1226
1236
|
flagKeys,
|
|
1237
|
+
hasAccessFacade,
|
|
1227
1238
|
hasAi,
|
|
1228
1239
|
hasAnalytics,
|
|
1229
1240
|
hasBrowser,
|
|
@@ -1304,6 +1315,8 @@ declare const emitVectors: (vectorIndexes: ReadonlyArray<VectorIndexIR>) => stri
|
|
|
1304
1315
|
declare const emitWranglerCronTriggers: (crons: ReadonlyArray<CronJobIR>) => string[];
|
|
1305
1316
|
/** Which capability methods the generated `defineApp` builder exposes — one flag per package-backed feature the app actually uses. */
|
|
1306
1317
|
interface EmitAppOptions {
|
|
1318
|
+
/** App depends on `@lunora/cloudflare-access` → emit `.access()` (wire the Cloudflare Access `resolveIdentity`, composed ahead of `@lunora/auth` when both are present). */
|
|
1319
|
+
hasAccess: boolean;
|
|
1307
1320
|
/** App uses `@lunora/ai` / `ctx.ai` → emit `.ai()` (override the Workers AI binding backing `ctx.ai`). */
|
|
1308
1321
|
hasAi: boolean;
|
|
1309
1322
|
/** App uses `@lunora/bindings/analytics` / `ctx.analytics` → emit `.analytics()` (override the dataset backing `ctx.analytics`). */
|
package/dist/index.d.ts
CHANGED
|
@@ -1099,6 +1099,13 @@ declare const emitApi: (functions: ReadonlyArray<FunctionIR>, workflows?: Readon
|
|
|
1099
1099
|
declare const emitCollections: (shapes: ReadonlyArray<ShapeIR>, hasDatabase: boolean, useUmbrella?: boolean) => string;
|
|
1100
1100
|
interface EmitServerOptions {
|
|
1101
1101
|
containers?: ReadonlyArray<ContainerIR>;
|
|
1102
|
+
/**
|
|
1103
|
+
* A `lunora/` source reads `ctx.access` — wires the verified Cloudflare Access
|
|
1104
|
+
* facade (`@lunora/cloudflare-access/context`) onto every ctx. Distinct from
|
|
1105
|
+
* `emitApp`'s `hasAccess` (which gates the worker's `.access()` resolveIdentity
|
|
1106
|
+
* method); this one gates the per-request `ctx.access` read surface.
|
|
1107
|
+
*/
|
|
1108
|
+
hasAccessFacade?: boolean;
|
|
1102
1109
|
hasAi?: boolean;
|
|
1103
1110
|
/** A `lunora/` source uses `@lunora/bindings/analytics` / `ctx.analytics` — wires the write helper onto every ctx. */
|
|
1104
1111
|
hasAnalytics?: boolean;
|
|
@@ -1127,6 +1134,7 @@ interface EmitServerOptions {
|
|
|
1127
1134
|
}
|
|
1128
1135
|
declare const emitServer: ({
|
|
1129
1136
|
containers,
|
|
1137
|
+
hasAccessFacade,
|
|
1130
1138
|
hasAi,
|
|
1131
1139
|
hasAnalytics,
|
|
1132
1140
|
hasBrowser,
|
|
@@ -1187,6 +1195,8 @@ interface EmitShardOptions {
|
|
|
1187
1195
|
key: string;
|
|
1188
1196
|
type: "boolean" | "number" | "object" | "string";
|
|
1189
1197
|
}>;
|
|
1198
|
+
/** A `lunora/` source reads `ctx.access` — wires the verified Cloudflare Access facade onto every ctx. */
|
|
1199
|
+
hasAccessFacade?: boolean;
|
|
1190
1200
|
hasAi?: boolean;
|
|
1191
1201
|
/** A `lunora/` source reads `ctx.analytics` — wires the Analytics Engine write helper onto every ctx. */
|
|
1192
1202
|
hasAnalytics?: boolean;
|
|
@@ -1224,6 +1234,7 @@ declare const emitShard: ({
|
|
|
1224
1234
|
advisories,
|
|
1225
1235
|
containers,
|
|
1226
1236
|
flagKeys,
|
|
1237
|
+
hasAccessFacade,
|
|
1227
1238
|
hasAi,
|
|
1228
1239
|
hasAnalytics,
|
|
1229
1240
|
hasBrowser,
|
|
@@ -1304,6 +1315,8 @@ declare const emitVectors: (vectorIndexes: ReadonlyArray<VectorIndexIR>) => stri
|
|
|
1304
1315
|
declare const emitWranglerCronTriggers: (crons: ReadonlyArray<CronJobIR>) => string[];
|
|
1305
1316
|
/** Which capability methods the generated `defineApp` builder exposes — one flag per package-backed feature the app actually uses. */
|
|
1306
1317
|
interface EmitAppOptions {
|
|
1318
|
+
/** App depends on `@lunora/cloudflare-access` → emit `.access()` (wire the Cloudflare Access `resolveIdentity`, composed ahead of `@lunora/auth` when both are present). */
|
|
1319
|
+
hasAccess: boolean;
|
|
1307
1320
|
/** App uses `@lunora/ai` / `ctx.ai` → emit `.ai()` (override the Workers AI binding backing `ctx.ai`). */
|
|
1308
1321
|
hasAi: boolean;
|
|
1309
1322
|
/** App uses `@lunora/bindings/analytics` / `ctx.analytics` → emit `.analytics()` (override the dataset backing `ctx.analytics`). */
|
package/dist/index.mjs
CHANGED
|
@@ -19,11 +19,11 @@ export { default as discoverSchema } from './packem_shared/discoverSchema-BnWHHJ
|
|
|
19
19
|
export { SHAPES_FILENAME, discoverShapes } from './packem_shared/SHAPES_FILENAME-ChV7MqgE.mjs';
|
|
20
20
|
export { default as discoverStorageRulesMetadata } from './packem_shared/discoverStorageRulesMetadata-Da8BKXcI.mjs';
|
|
21
21
|
export { WORKFLOWS_FILENAME, discoverWorkflows } from './packem_shared/WORKFLOWS_FILENAME-D62dcBGg.mjs';
|
|
22
|
-
export { GENERATED_HEADER, emitApi, emitCollections, emitContainers, emitCrons, emitDataModel, emitDrizzleSchema, emitFunctions, emitServer, emitShard, emitVectors, emitWorkflows, emitWranglerCronTriggers } from './packem_shared/GENERATED_HEADER-
|
|
23
|
-
export { emitApp } from './packem_shared/emitApp-
|
|
24
|
-
export { buildOpenApiDocument, emitOpenApi, emitOpenApiModule } from './packem_shared/buildOpenApiDocument-
|
|
25
|
-
export { OPENRPC_VERSION, buildOpenRpcDocument, emitOpenRpc, emitOpenRpcModule } from './packem_shared/OPENRPC_VERSION-
|
|
26
|
-
export { SCHEMA_SNAPSHOT_FILENAME, createCodegenProject, refreshCodegenProject, runCodegen } from './packem_shared/SCHEMA_SNAPSHOT_FILENAME-
|
|
22
|
+
export { GENERATED_HEADER, emitApi, emitCollections, emitContainers, emitCrons, emitDataModel, emitDrizzleSchema, emitFunctions, emitServer, emitShard, emitVectors, emitWorkflows, emitWranglerCronTriggers } from './packem_shared/GENERATED_HEADER-D-AbhmRh.mjs';
|
|
23
|
+
export { emitApp } from './packem_shared/emitApp-CV81L74c.mjs';
|
|
24
|
+
export { buildOpenApiDocument, emitOpenApi, emitOpenApiModule } from './packem_shared/buildOpenApiDocument-DoK7_x1g.mjs';
|
|
25
|
+
export { OPENRPC_VERSION, buildOpenRpcDocument, emitOpenRpc, emitOpenRpcModule } from './packem_shared/OPENRPC_VERSION-DDT4mIzD.mjs';
|
|
26
|
+
export { SCHEMA_SNAPSHOT_FILENAME, createCodegenProject, refreshCodegenProject, runCodegen } from './packem_shared/SCHEMA_SNAPSHOT_FILENAME-ExbveiC6.mjs';
|
|
27
27
|
export { SCHEMA_SNAPSHOT_VERSION, SchemaSnapshotParseError, buildSchemaSnapshot, diffSchemaSnapshots, evaluateSchemaDrift, parseSchemaSnapshot, serializeSchemaSnapshot } from './packem_shared/SCHEMA_SNAPSHOT_VERSION-wWGP2_5E.mjs';
|
|
28
28
|
export { schemaFromIr } from './packem_shared/schemaFromIr-DTYsLBaA.mjs';
|
|
29
29
|
export { LUNORA_ERROR_CODES, validatorIrToJsonSchema } from './packem_shared/LUNORA_ERROR_CODES-CySpQPD3.mjs';
|
|
@@ -749,6 +749,7 @@ const buildStorageBucketNames = (schema, ruleBuckets = []) => {
|
|
|
749
749
|
};
|
|
750
750
|
const emitServer = ({
|
|
751
751
|
containers = [],
|
|
752
|
+
hasAccessFacade = false,
|
|
752
753
|
hasAi = false,
|
|
753
754
|
hasAnalytics = false,
|
|
754
755
|
hasBrowser = false,
|
|
@@ -821,6 +822,9 @@ ${envBindingFields}` : ""}
|
|
|
821
822
|
export type Env = CloudflareBindings;`;
|
|
822
823
|
const kvContextField = hasKv ? `
|
|
823
824
|
readonly kv: import("@lunora/bindings/kv").Kv;` : "";
|
|
825
|
+
const accessContextField = hasAccessFacade ? `
|
|
826
|
+
/** Verified Cloudflare Access identity — a synchronous facade over the resolved claims (email / groups / hasGroup / claims). Anonymous when no Access token is present. */
|
|
827
|
+
readonly access: import("@lunora/cloudflare-access/context").AccessFacade;` : "";
|
|
824
828
|
const flagsContextField = hasFlags ? `
|
|
825
829
|
/** Feature-flag evaluation (OpenFeature). Reads are memoized per request; evaluations never throw — a provider error resolves to the supplied default. */
|
|
826
830
|
readonly flags: import("@lunora/flags").LunoraFlags;` : "";
|
|
@@ -938,19 +942,19 @@ type TypedTableGet = <T extends TableName>(id: IdOfTable<T>) => Promise<Doc<T> |
|
|
|
938
942
|
export interface QueryCtx extends Omit<QueryCtxBase, "db" | "storage"> {
|
|
939
943
|
readonly db: Omit<DatabaseReader, "query" | "get"> & DatabaseReaderFacade & { query: TypedTableQuery; get: TypedTableGet };
|
|
940
944
|
readonly orm: OrmReader;
|
|
941
|
-
readonly storage: ReadOnlyStorage<StorageBucketName>;${kvContextField}${flagsContextField}${analyticsContextField}
|
|
945
|
+
readonly storage: ReadOnlyStorage<StorageBucketName>;${accessContextField}${kvContextField}${flagsContextField}${analyticsContextField}
|
|
942
946
|
}
|
|
943
947
|
|
|
944
948
|
export interface MutationCtx extends Omit<MutationCtxBase, "db" | "storage"${workflowsOmit}> {
|
|
945
949
|
readonly db: Omit<DatabaseWriter, "query" | "get"> & DatabaseWriterFacade & { query: TypedTableQuery; get: TypedTableGet };
|
|
946
950
|
readonly orm: OrmWriter;
|
|
947
|
-
readonly storage: ReadOnlyStorage<StorageBucketName>;${kvContextField}${flagsContextField}${analyticsContextField}${workflowsContextField}${queuesContextField}
|
|
951
|
+
readonly storage: ReadOnlyStorage<StorageBucketName>;${accessContextField}${kvContextField}${flagsContextField}${analyticsContextField}${workflowsContextField}${queuesContextField}
|
|
948
952
|
}
|
|
949
953
|
|
|
950
954
|
export interface ActionCtx extends Omit<ActionCtxBase, "db" | "storage"${workflowsOmit}> {
|
|
951
955
|
readonly db: Omit<DatabaseWriter, "query" | "get"> & DatabaseWriterFacade & { query: TypedTableQuery; get: TypedTableGet };
|
|
952
956
|
readonly orm: OrmWriter;
|
|
953
|
-
readonly storage: StorageBase<StorageBucketName>;${aiActionField}${paymentsActionField}${containersActionField}${kvContextField}${flagsContextField}${hyperdriveActionField}${browserActionField}${imagesActionField}${analyticsContextField}${pipelinesActionField}${r2sqlActionField}${workflowsContextField}${queuesContextField}
|
|
957
|
+
readonly storage: StorageBase<StorageBucketName>;${accessContextField}${aiActionField}${paymentsActionField}${containersActionField}${kvContextField}${flagsContextField}${hyperdriveActionField}${browserActionField}${imagesActionField}${analyticsContextField}${pipelinesActionField}${r2sqlActionField}${workflowsContextField}${queuesContextField}
|
|
954
958
|
}
|
|
955
959
|
|
|
956
960
|
/**
|
|
@@ -1361,6 +1365,21 @@ const emitFlagsFragments = (hasFlags) => {
|
|
|
1361
1365
|
stub: ""
|
|
1362
1366
|
};
|
|
1363
1367
|
};
|
|
1368
|
+
const emitAccessFragments = (hasAccessFacade) => {
|
|
1369
|
+
if (!hasAccessFacade) {
|
|
1370
|
+
return EMPTY_HELPER_FRAGMENTS;
|
|
1371
|
+
}
|
|
1372
|
+
return {
|
|
1373
|
+
build: `
|
|
1374
|
+
const access = accessFacade(identity, userId);
|
|
1375
|
+
`,
|
|
1376
|
+
configField: "",
|
|
1377
|
+
contextField: `
|
|
1378
|
+
access,`,
|
|
1379
|
+
importLines: [`import { accessFacade } from "@lunora/cloudflare-access/context";`],
|
|
1380
|
+
stub: ""
|
|
1381
|
+
};
|
|
1382
|
+
};
|
|
1364
1383
|
const emitFlagsOverrides = (flagKeys, hasFlags) => {
|
|
1365
1384
|
if (!hasFlags) {
|
|
1366
1385
|
return { constant: "", evaluateOverride: "", subscriptionOverride: "" };
|
|
@@ -1954,6 +1973,7 @@ const emitShard = ({
|
|
|
1954
1973
|
advisories = [],
|
|
1955
1974
|
containers = [],
|
|
1956
1975
|
flagKeys = [],
|
|
1976
|
+
hasAccessFacade = false,
|
|
1957
1977
|
hasAi = false,
|
|
1958
1978
|
hasAnalytics = false,
|
|
1959
1979
|
hasBrowser = false,
|
|
@@ -1979,6 +1999,7 @@ const emitShard = ({
|
|
|
1979
1999
|
const hasMutators = mutators.length > 0;
|
|
1980
2000
|
const hasShapes = shapes.length > 0;
|
|
1981
2001
|
const { build: aiBuild, configField: aiConfigField, contextField: aiContextField, stub: aiStub } = emitAiFragments(hasAi);
|
|
2002
|
+
const accessFragments = emitAccessFragments(hasAccessFacade);
|
|
1982
2003
|
const kvFragments = emitKvFragments(hasKv);
|
|
1983
2004
|
const flagsFragments = emitFlagsFragments(hasFlags);
|
|
1984
2005
|
const flagsOverrides = emitFlagsOverrides(flagKeys, hasFlags);
|
|
@@ -2126,6 +2147,7 @@ const LUNORA_RLS_READ_REGISTRY = buildRlsReadRegistry(Object.values(LUNORA_FUNCT
|
|
|
2126
2147
|
importLines.push(`import type { AiBindingLike, LunoraAi } from "@lunora/ai";`, `import { createAi } from "@lunora/ai";`);
|
|
2127
2148
|
}
|
|
2128
2149
|
importLines.push(
|
|
2150
|
+
...accessFragments.importLines,
|
|
2129
2151
|
...kvFragments.importLines,
|
|
2130
2152
|
...flagsFragments.importLines,
|
|
2131
2153
|
...analyticsFragments.importLines,
|
|
@@ -2314,8 +2336,8 @@ ${schema.tables.map(
|
|
|
2314
2336
|
const secretsBuild = `
|
|
2315
2337
|
const secrets = createSecrets(env);
|
|
2316
2338
|
`;
|
|
2317
|
-
const everyContextBuild = `${kvFragments.build}${flagsFragments.build}${analyticsFragments.build}${secretsBuild}`;
|
|
2318
|
-
const everyContextField = `${kvFragments.contextField}${flagsFragments.contextField}${analyticsFragments.contextField}
|
|
2339
|
+
const everyContextBuild = `${accessFragments.build}${kvFragments.build}${flagsFragments.build}${analyticsFragments.build}${secretsBuild}`;
|
|
2340
|
+
const everyContextField = `${accessFragments.contextField}${kvFragments.contextField}${flagsFragments.contextField}${analyticsFragments.contextField}
|
|
2319
2341
|
secrets,`;
|
|
2320
2342
|
const actionOnlyHasAny = hasImages || hasHyperdrive || hasBrowser || hasR2sql || hasPipelines;
|
|
2321
2343
|
const actionOnlyBlock = actionOnlyHasAny ? `
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GENERATED_HEADER } from './GENERATED_HEADER-
|
|
1
|
+
import { GENERATED_HEADER } from './GENERATED_HEADER-D-AbhmRh.mjs';
|
|
2
2
|
import { s as sanitizeNamespace } from './paths-BRd6JHuF.mjs';
|
|
3
3
|
import { argsObjectSchema, LUNORA_ERROR_CODES } from './LUNORA_ERROR_CODES-CySpQPD3.mjs';
|
|
4
4
|
|
|
@@ -23,10 +23,10 @@ import { discoverShapes } from './SHAPES_FILENAME-ChV7MqgE.mjs';
|
|
|
23
23
|
import discoverStorageRulesMetadata from './discoverStorageRulesMetadata-Da8BKXcI.mjs';
|
|
24
24
|
import { e as enclosingExportName$1 } from './discover-ast-CT6BgBr4.mjs';
|
|
25
25
|
import { discoverWorkflows } from './WORKFLOWS_FILENAME-D62dcBGg.mjs';
|
|
26
|
-
import { buildStorageColumns, emitDataModel, emitApi, emitServer, emitFunctions, emitShard, emitCollections, emitContainers, emitWorkflows, emitQueues, emitCrons, emitVectors, emitDrizzleSchema, emitSeed, emitWranglerCronTriggers } from './GENERATED_HEADER-
|
|
27
|
-
import { emitApp } from './emitApp-
|
|
28
|
-
import { buildOpenApiDocument, emitOpenApiModule } from './buildOpenApiDocument-
|
|
29
|
-
import { buildOpenRpcDocument, emitOpenRpcModule } from './OPENRPC_VERSION-
|
|
26
|
+
import { buildStorageColumns, emitDataModel, emitApi, emitServer, emitFunctions, emitShard, emitCollections, emitContainers, emitWorkflows, emitQueues, emitCrons, emitVectors, emitDrizzleSchema, emitSeed, emitWranglerCronTriggers } from './GENERATED_HEADER-D-AbhmRh.mjs';
|
|
27
|
+
import { emitApp } from './emitApp-CV81L74c.mjs';
|
|
28
|
+
import { buildOpenApiDocument, emitOpenApiModule } from './buildOpenApiDocument-DoK7_x1g.mjs';
|
|
29
|
+
import { buildOpenRpcDocument, emitOpenRpcModule } from './OPENRPC_VERSION-DDT4mIzD.mjs';
|
|
30
30
|
import { buildSchemaSnapshot, serializeSchemaSnapshot } from './SCHEMA_SNAPSHOT_VERSION-wWGP2_5E.mjs';
|
|
31
31
|
|
|
32
32
|
const HTTP_VERBS = /* @__PURE__ */ new Set(["delete", "get", "head", "options", "patch", "post", "put"]);
|
|
@@ -243,6 +243,11 @@ const discoverArgumentValidators = (project, lunoraDirectory) => {
|
|
|
243
243
|
};
|
|
244
244
|
|
|
245
245
|
const PROBES = {
|
|
246
|
+
// The middleware (`accessContext()` / `accessRoles()`) imports the `/context`
|
|
247
|
+
// and `/roles` subpaths, NOT the bare `@lunora/cloudflare-access` specifier —
|
|
248
|
+
// so the per-procedure middleware never trips the global `ctx.access` wiring.
|
|
249
|
+
// A handler reading `ctx.access` is the signal that wires it onto every ctx.
|
|
250
|
+
access: { contextProperty: "access", moduleSpecifier: "@lunora/cloudflare-access" },
|
|
246
251
|
ai: { contextProperty: "ai", moduleSpecifier: "@lunora/ai" },
|
|
247
252
|
analytics: { contextProperty: "analytics", moduleSpecifier: "@lunora/bindings/analytics" },
|
|
248
253
|
browser: { contextProperty: "browser", moduleSpecifier: "@lunora/browser" },
|
|
@@ -279,6 +284,7 @@ const readsContextProperty = (sourceFile, property) => {
|
|
|
279
284
|
};
|
|
280
285
|
const discoverFeatureUsage = (project, lunoraDirectory) => {
|
|
281
286
|
const usage = {
|
|
287
|
+
access: false,
|
|
282
288
|
ai: false,
|
|
283
289
|
analytics: false,
|
|
284
290
|
browser: false,
|
|
@@ -833,6 +839,7 @@ const runCodegen = (options) => {
|
|
|
833
839
|
const hasAi = featureUsage.ai;
|
|
834
840
|
const hasPayments = featureUsage.payments;
|
|
835
841
|
const hasKv = featureUsage.kv;
|
|
842
|
+
const hasAccessFacade = featureUsage.access;
|
|
836
843
|
const hasFlags = existsSync(join(lunoraDirectory, "flags.ts"));
|
|
837
844
|
const flagKeys = hasFlags ? discoverFlagKeys(project, lunoraDirectory) : [];
|
|
838
845
|
const hasHyperdrive = featureUsage.hyperdrive;
|
|
@@ -857,6 +864,7 @@ const runCodegen = (options) => {
|
|
|
857
864
|
const apiContent = emitApi(functions, workflows, useUmbrella);
|
|
858
865
|
const serverContent = emitServer({
|
|
859
866
|
containers,
|
|
867
|
+
hasAccessFacade,
|
|
860
868
|
hasAi,
|
|
861
869
|
hasAnalytics,
|
|
862
870
|
hasBrowser,
|
|
@@ -878,6 +886,7 @@ const runCodegen = (options) => {
|
|
|
878
886
|
advisories,
|
|
879
887
|
containers,
|
|
880
888
|
flagKeys,
|
|
889
|
+
hasAccessFacade,
|
|
881
890
|
hasAi,
|
|
882
891
|
hasAnalytics,
|
|
883
892
|
hasBrowser,
|
|
@@ -911,6 +920,7 @@ const runCodegen = (options) => {
|
|
|
911
920
|
const wantsOpenApi = apiSpec === "openapi" || apiSpec === "both";
|
|
912
921
|
const wantsOpenRpc = apiSpec === "openrpc" || apiSpec === "both";
|
|
913
922
|
const appContent = emitApp({
|
|
923
|
+
hasAccess: dependencies.has("@lunora/cloudflare-access"),
|
|
914
924
|
hasAi,
|
|
915
925
|
hasAnalytics,
|
|
916
926
|
hasAuth: dependencies.has("@lunora/auth"),
|
package/dist/packem_shared/{buildOpenApiDocument-CB2brlbc.mjs → buildOpenApiDocument-DoK7_x1g.mjs}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GENERATED_HEADER } from './GENERATED_HEADER-
|
|
1
|
+
import { GENERATED_HEADER } from './GENERATED_HEADER-D-AbhmRh.mjs';
|
|
2
2
|
import { s as sanitizeNamespace } from './paths-BRd6JHuF.mjs';
|
|
3
3
|
import { LUNORA_ERROR_CODES, objectSchema, argsObjectSchema, validatorIrToJsonSchema } from './LUNORA_ERROR_CODES-CySpQPD3.mjs';
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GENERATED_HEADER } from './GENERATED_HEADER-
|
|
1
|
+
import { GENERATED_HEADER } from './GENERATED_HEADER-D-AbhmRh.mjs';
|
|
2
2
|
|
|
3
3
|
const LONG_TAIL = [
|
|
4
4
|
["hasAi", "ai", "ai", "Override the Workers AI binding backing `ctx.ai` (defaults to `env.AI`)."],
|
|
@@ -22,8 +22,25 @@ const LONG_TAIL = [
|
|
|
22
22
|
["hasVectors", "vectors", "vectors", "Wire the Vectorize index map backing `ctx.vectors`."]
|
|
23
23
|
];
|
|
24
24
|
const hasAnyLongTail = (options) => LONG_TAIL.some(([flag]) => options[flag]);
|
|
25
|
+
const buildAccessImports = (hasAccess, hasAuth) => hasAccess ? [
|
|
26
|
+
`import type { CreateAccessResolverOptions } from "@lunora/cloudflare-access";`,
|
|
27
|
+
`import { createAccessResolver${hasAuth ? ", composeResolvers" : ""} } from "@lunora/cloudflare-access";`
|
|
28
|
+
] : [];
|
|
25
29
|
const buildImportLines = (options) => {
|
|
26
|
-
const {
|
|
30
|
+
const {
|
|
31
|
+
hasAccess,
|
|
32
|
+
hasAuth,
|
|
33
|
+
hasFramework,
|
|
34
|
+
hasGlobal,
|
|
35
|
+
hasHyperdriveGlobal,
|
|
36
|
+
hasQueue,
|
|
37
|
+
hasScheduler,
|
|
38
|
+
hasStorage,
|
|
39
|
+
hasWorkflow,
|
|
40
|
+
useUmbrella,
|
|
41
|
+
wantsOpenApi,
|
|
42
|
+
wantsOpenRpc
|
|
43
|
+
} = options;
|
|
27
44
|
const runtimeModule = useUmbrella ? "lunorash/runtime" : "@lunora/runtime";
|
|
28
45
|
const runtimeTypeImports = ["ExecutionContextLike", "LunoraWorker", "Route", "ScheduledControllerLike", "ShardNamespaceLike", "WorkerOptions"];
|
|
29
46
|
if (hasGlobal) {
|
|
@@ -42,6 +59,7 @@ const buildImportLines = (options) => {
|
|
|
42
59
|
`import type { LunoraAuth, LunoraAuthOptions } from "@lunora/auth";`,
|
|
43
60
|
`import { createAuth, createAuthAdmin, ensureMigrated, handleAuthRequest, lunoraD1Adapter } from "@lunora/auth";`
|
|
44
61
|
] : [],
|
|
62
|
+
...buildAccessImports(hasAccess, hasAuth),
|
|
45
63
|
...hasGlobal ? [
|
|
46
64
|
`import type { D1CtxDbOptions, D1DatabaseLike, D1Exec } from "@lunora/d1";`,
|
|
47
65
|
`import { createD1CtxDb, facetGlobalColumn, listGlobalTables, readGlobalTablePage } from "@lunora/d1";`
|
|
@@ -120,9 +138,10 @@ interface AuthDeclaration<Env> {
|
|
|
120
138
|
] : []
|
|
121
139
|
];
|
|
122
140
|
const buildFieldLines = (options) => [
|
|
141
|
+
...options.hasAccess ? [` private accessSelector?: Selector<Env, CreateAccessResolverOptions>;`] : [],
|
|
123
142
|
` private adminToken?: Selector<Env, string>;`,
|
|
124
143
|
...options.hasAuth ? [` private authDeclaration?: AuthDeclaration<Env>;`] : [],
|
|
125
|
-
` private readonly extendFns: ((env: Env) => Partial<WorkerOptions>)[] = [];`,
|
|
144
|
+
` private readonly extendFns: ((env: Env, derived: Readonly<WorkerOptions>) => Partial<WorkerOptions>)[] = [];`,
|
|
126
145
|
...options.hasGlobal ? [` private globalDeclaration?: GlobalDeclaration<Env>;`] : [],
|
|
127
146
|
...options.hasHyperdriveGlobal ? [` private hyperdriveGlobalDeclaration?: HyperdriveGlobalDeclaration<Env>;`] : [],
|
|
128
147
|
` private readonly routeMap: Record<string, Route> = {};`,
|
|
@@ -140,6 +159,14 @@ const buildLongTailMethods = (options) => LONG_TAIL.filter(([flag]) => options[f
|
|
|
140
159
|
}`
|
|
141
160
|
);
|
|
142
161
|
const buildMethodBlocks = (options) => [
|
|
162
|
+
...options.hasAccess ? [
|
|
163
|
+
` /** Wire Cloudflare Access (Zero Trust) — verifies the \`Cf-Access-Jwt-Assertion\` JWT and feeds the identity into \`ctx.auth\` / RLS via \`resolveIdentity\`. When \`.auth(...)\` is also configured, Access is composed ahead of it (Access wins when its JWT is present; everyone else falls through to the app session). */
|
|
164
|
+
public access(selector: Selector<Env, CreateAccessResolverOptions>): this {
|
|
165
|
+
this.accessSelector = selector;
|
|
166
|
+
|
|
167
|
+
return this;
|
|
168
|
+
}`
|
|
169
|
+
] : [],
|
|
143
170
|
` /** Bearer token gating the \`/_lunora/admin/*\` endpoints the studio calls. */
|
|
144
171
|
public admin(selector: Selector<Env, string>): this {
|
|
145
172
|
this.adminToken = selector;
|
|
@@ -154,8 +181,8 @@ const buildMethodBlocks = (options) => [
|
|
|
154
181
|
return this;
|
|
155
182
|
}`
|
|
156
183
|
] : [],
|
|
157
|
-
` /** Escape hatch — merge raw \`WorkerOptions\` (anything not yet sugared) over the derived options at build time. */
|
|
158
|
-
public extend(fn: (env: Env) => Partial<WorkerOptions>): this {
|
|
184
|
+
` /** Escape hatch — merge raw \`WorkerOptions\` (anything not yet sugared) over the derived options at build time. The second \`derived\` argument is a snapshot of the options assembled so far (after \`.auth(...)\` etc.), so you can compose rather than clobber — e.g. wrap \`derived.resolveIdentity\` instead of replacing it. */
|
|
185
|
+
public extend(fn: (env: Env, derived: Readonly<WorkerOptions>) => Partial<WorkerOptions>): this {
|
|
159
186
|
this.extendFns.push(fn);
|
|
160
187
|
|
|
161
188
|
return this;
|
|
@@ -344,6 +371,21 @@ const buildWorkerOptionLines = (options) => [
|
|
|
344
371
|
|
|
345
372
|
options.authAdmin = authInstance ? createAuthAdmin(authInstance) : undefined;
|
|
346
373
|
}`
|
|
374
|
+
] : [],
|
|
375
|
+
// Cloudflare Access — runs AFTER the auth block so it can compose ahead of
|
|
376
|
+
// the better-auth resolver rather than clobber it. With `.auth()` present,
|
|
377
|
+
// a request carrying a verified Access JWT is authenticated by Access and
|
|
378
|
+
// everyone else falls through to the app session; without it, Access is the
|
|
379
|
+
// sole resolver.
|
|
380
|
+
...options.hasAccess ? [
|
|
381
|
+
options.hasAuth ? ` if (this.accessSelector) {
|
|
382
|
+
const accessResolver = createAccessResolver(this.accessSelector(env));
|
|
383
|
+
const fallback = options.resolveIdentity;
|
|
384
|
+
|
|
385
|
+
options.resolveIdentity = fallback ? composeResolvers(accessResolver, fallback) : accessResolver;
|
|
386
|
+
}` : ` if (this.accessSelector) {
|
|
387
|
+
options.resolveIdentity = createAccessResolver(this.accessSelector(env));
|
|
388
|
+
}`
|
|
347
389
|
] : []
|
|
348
390
|
];
|
|
349
391
|
const buildBaseWorkerOptions = (options) => [
|
|
@@ -599,7 +641,7 @@ ${buildBaseWorkerOptions(options).join("\n")}
|
|
|
599
641
|
}
|
|
600
642
|
|
|
601
643
|
${workerOptionLines.join("\n\n")}${workerOptionLines.length > 0 ? "\n\n" : ""} for (const fn of this.extendFns) {
|
|
602
|
-
Object.assign(options, fn(env));
|
|
644
|
+
Object.assign(options, fn(env, { ...options }));
|
|
603
645
|
}
|
|
604
646
|
|
|
605
647
|
return options;
|