@lunora/codegen 1.0.0-alpha.50 → 1.0.0-alpha.52
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 +66 -4
- package/dist/index.d.ts +66 -4
- package/dist/index.mjs +22 -21
- package/dist/packem_shared/{FLAGS_FILENAME-Dg4mKUuz.mjs → FLAGS_FILENAME-D5igzqwR.mjs} +1 -1
- package/dist/packem_shared/{GENERATED_HEADER-C5paWNYO.mjs → GENERATED_HEADER-D5mkGdTx.mjs} +1 -1
- package/dist/packem_shared/NOTIFY_FILENAME-CK2IrsrP.mjs +152 -0
- package/dist/packem_shared/{OPENRPC_VERSION-7A2weq2u.mjs → OPENRPC_VERSION-Dnru3-Tg.mjs} +1 -1
- package/dist/packem_shared/{SCHEMA_SNAPSHOT_FILENAME-G5dkcxPR.mjs → SCHEMA_SNAPSHOT_FILENAME-7_LhHIAy.mjs} +118 -23
- package/dist/packem_shared/{buildOpenApiDocument-B7mEdzA2.mjs → buildOpenApiDocument-BH50tL6w.mjs} +80 -1
- package/dist/packem_shared/{discoverAuthApiCalls-Dx3K42rk.mjs → discoverAuthApiCalls-Dhwgf4J4.mjs} +1 -1
- package/dist/packem_shared/{discoverCrons-DvqkEWdx.mjs → discoverCrons-UbQLLmMS.mjs} +1 -1
- package/dist/packem_shared/{discoverFunctions-BJ-qR7Rg.mjs → discoverFunctions-COG_Xkyz.mjs} +27 -1
- package/dist/packem_shared/{discoverHttpRoutes-daCzuTe8.mjs → discoverHttpRoutes-CVXWZkzo.mjs} +2 -2
- package/dist/packem_shared/{discoverInserts-DI4q5NxE.mjs → discoverInserts-DdWnXmLS.mjs} +1 -1
- package/dist/packem_shared/{discoverMaskProcedures-BcTOEKNU.mjs → discoverMaskProcedures-BG58_fw3.mjs} +1 -1
- package/dist/packem_shared/{discoverMigrations-VNUFvCwr.mjs → discoverMigrations-Bw1U01zr.mjs} +1 -1
- package/dist/packem_shared/{discoverNondeterministicCalls-S0N2xLCq.mjs → discoverNondeterministicCalls-BbXEFZUT.mjs} +1 -1
- package/dist/packem_shared/{discoverQueries-CJnnnLpd.mjs → discoverQueries-CDmxu2ET.mjs} +1 -1
- package/dist/packem_shared/{discoverR2sqlCalls-pnpicWfz.mjs → discoverR2sqlCalls-Bn7QVv7J.mjs} +1 -1
- package/dist/packem_shared/{discoverRlsMetadata-DppniPUH.mjs → discoverRlsMetadata-D9uN35no.mjs} +1 -1
- package/dist/packem_shared/{discoverSandboxUsage-BUM2r90k.mjs → discoverSandboxUsage-B5jDU6Bt.mjs} +1 -1
- package/dist/packem_shared/{discoverSchema-BaSAvooG.mjs → discoverSchema-BJp5_T4o.mjs} +32 -1
- package/dist/packem_shared/{discoverStorageRulesMetadata-CnHl2rXD.mjs → discoverStorageRulesMetadata-BqMhuEjo.mjs} +1 -1
- package/dist/packem_shared/{emit-ClTbCLy4.mjs → emit-B4LUyyg7.mjs} +98 -18
- package/dist/packem_shared/{emitApp-CzzrjVqH.mjs → emitApp-BJ6weBMT.mjs} +11 -2
- package/dist/packem_shared/{formatAdvisories-BmF7Mplc.mjs → formatAdvisories-Cans5TWS.mjs} +17 -1
- package/dist/packem_shared/{parse-validator-BSJo1HGP.mjs → parse-validator-BDGV8iue.mjs} +1 -1
- package/package.json +7 -7
|
@@ -388,6 +388,8 @@ const SCALAR_TYPE_BY_KIND = {
|
|
|
388
388
|
// not statically recoverable at codegen time — emit `unknown` so the
|
|
389
389
|
// generated api types still compile without depending on the library.
|
|
390
390
|
from: "unknown",
|
|
391
|
+
// A geographic point stored as a `{ lat, lng }` JSON object.
|
|
392
|
+
geoPoint: "{ lat: number; lng: number }",
|
|
391
393
|
null: "null",
|
|
392
394
|
number: "number",
|
|
393
395
|
// The key of a stored R2 object — a string; the distinction is semantic only.
|
|
@@ -512,6 +514,10 @@ ${fields}
|
|
|
512
514
|
const names = table.rankIndexes.map((index) => JSON.stringify(index.name)).join(" | ");
|
|
513
515
|
return ` ${table.name}: ${names || "never"};`;
|
|
514
516
|
}).join("\n");
|
|
517
|
+
const geoIndexNamesByTable = schema.tables.map((table) => {
|
|
518
|
+
const names = table.shardMode === "global" ? "" : (table.geoIndexes ?? []).map((index) => JSON.stringify(index.name)).join(" | ");
|
|
519
|
+
return ` ${table.name}: ${names || "never"};`;
|
|
520
|
+
}).join("\n");
|
|
515
521
|
const vectorIndexNames = schema.vectorIndexes.map((index) => JSON.stringify(index.name)).join(" | ") || "never";
|
|
516
522
|
const insertInterfaces = schema.tables.map((table) => renderInsertInterface(table)).join("\n\n");
|
|
517
523
|
const insertMap = schema.tables.map((table) => ` ${table.name}: Insert_${table.name};`).join("\n");
|
|
@@ -592,6 +598,13 @@ ${rankIndexNamesByTable}
|
|
|
592
598
|
|
|
593
599
|
export type RankIndexName<T extends keyof DataModel> = RankIndexNamesByTable[T];
|
|
594
600
|
|
|
601
|
+
/** Per-table geo-index name union. \`never\` for tables without a geoIndex. */
|
|
602
|
+
export interface GeoIndexNamesByTable {
|
|
603
|
+
${geoIndexNamesByTable}
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
export type GeoIndexName<T extends keyof DataModel> = GeoIndexNamesByTable[T];
|
|
607
|
+
|
|
595
608
|
/** Union of declared vector index names. \`never\` when none are declared. */
|
|
596
609
|
export type VectorIndexName = ${vectorIndexNames};
|
|
597
610
|
|
|
@@ -631,16 +644,16 @@ export type WithArg<T extends keyof DataModel> = WithArgOf<DataModel, Relations,
|
|
|
631
644
|
export type LoadWith<T extends keyof DataModel, W> = LoadWithOf<DataModel, Relations, T, W>;
|
|
632
645
|
|
|
633
646
|
/** Read-only typed table accessor exposed on \`QueryCtx.db.<table>\`. */
|
|
634
|
-
export type TableReaderFacade<T extends keyof DataModel> = TableReaderFacadeOf<DataModel, Relations, RankIndexNamesByTable, SearchIndexNamesByTable, T>;
|
|
647
|
+
export type TableReaderFacade<T extends keyof DataModel> = TableReaderFacadeOf<DataModel, Relations, RankIndexNamesByTable, SearchIndexNamesByTable, T, GeoIndexNamesByTable>;
|
|
635
648
|
|
|
636
649
|
/** Read-write typed table accessor exposed on \`MutationCtx.db.<table>\` / \`ActionCtx.db.<table>\`. */
|
|
637
|
-
export type TableWriterFacade<T extends keyof DataModel> = TableWriterFacadeOf<DataModel, InsertModel, Relations, RankIndexNamesByTable, SearchIndexNamesByTable, T>;
|
|
650
|
+
export type TableWriterFacade<T extends keyof DataModel> = TableWriterFacadeOf<DataModel, InsertModel, Relations, RankIndexNamesByTable, SearchIndexNamesByTable, T, GeoIndexNamesByTable>;
|
|
638
651
|
|
|
639
652
|
/** Per-table read facade — \`ctx.db.<table>\` on a \`QueryCtx\`. */
|
|
640
|
-
export type DatabaseReaderFacade = DatabaseReaderFacadeOf<DataModel, Relations, RankIndexNamesByTable, SearchIndexNamesByTable>;
|
|
653
|
+
export type DatabaseReaderFacade = DatabaseReaderFacadeOf<DataModel, Relations, RankIndexNamesByTable, SearchIndexNamesByTable, GeoIndexNamesByTable>;
|
|
641
654
|
|
|
642
655
|
/** Per-table read-write facade — \`ctx.db.<table>\` on a \`MutationCtx\` / \`ActionCtx\`. */
|
|
643
|
-
export type DatabaseWriterFacade = DatabaseWriterFacadeOf<DataModel, InsertModel, Relations, RankIndexNamesByTable, SearchIndexNamesByTable>;
|
|
656
|
+
export type DatabaseWriterFacade = DatabaseWriterFacadeOf<DataModel, InsertModel, Relations, RankIndexNamesByTable, SearchIndexNamesByTable, GeoIndexNamesByTable>;
|
|
644
657
|
|
|
645
658
|
/** Insert builder returned by \`ctx.orm.insert(table)\`. */
|
|
646
659
|
export interface OrmInsertBuilder<T extends keyof DataModel> {
|
|
@@ -1131,6 +1144,7 @@ const emitServer = ({
|
|
|
1131
1144
|
hasHyperdrive = false,
|
|
1132
1145
|
hasImages = false,
|
|
1133
1146
|
hasKv = false,
|
|
1147
|
+
hasNotify = false,
|
|
1134
1148
|
hasPayments = false,
|
|
1135
1149
|
hasPipelines = false,
|
|
1136
1150
|
hasR2sql = false,
|
|
@@ -1219,6 +1233,11 @@ export type Env = CloudflareBindings;`;
|
|
|
1219
1233
|
const flagsContextField = hasFlags ? `
|
|
1220
1234
|
/** Feature-flag evaluation (OpenFeature). Reads are memoized per request; evaluations never throw — a provider error resolves to the supplied default. */
|
|
1221
1235
|
readonly flags: import("${base.flags}").LunoraFlags;` : "";
|
|
1236
|
+
const notifyContextField = hasNotify ? `
|
|
1237
|
+
/** Multi-channel notifications (@lunora/notify): send / chat / inApp / webhook plus the push device sub-facade. Sends are external I/O — confine them to action handlers. */
|
|
1238
|
+
readonly notify: import("@lunora/notify").LunoraNotify;
|
|
1239
|
+
/** Device push sub-facade — the same object as ctx.notify.push (register / send / broadcast). Sends belong in action handlers. */
|
|
1240
|
+
readonly push: import("@lunora/notify").LunoraPush;` : "";
|
|
1222
1241
|
const hasWorkflows = workflows.length > 0;
|
|
1223
1242
|
const workflowsTypeImport = hasWorkflows ? `import type { WorkflowHandle } from "@lunora/workflow";
|
|
1224
1243
|
import type * as lunoraWorkflowDefinitions from "../workflows.js";
|
|
@@ -1349,19 +1368,19 @@ type TypedTableGet = <T extends TableName>(id: IdOfTable<T>) => Promise<Doc<T> |
|
|
|
1349
1368
|
export interface QueryCtx extends Omit<QueryCtxBase, "db" | "storage"${authOmit}${envOmit}> {
|
|
1350
1369
|
readonly db: Omit<DatabaseReader, "query" | "get"> & DatabaseReaderFacade & { query: TypedTableQuery; get: TypedTableGet };
|
|
1351
1370
|
readonly orm: OrmReader;
|
|
1352
|
-
readonly storage: ReadOnlyStorage<StorageBucketName>;${accessContextField}${kvContextField}${flagsContextField}${analyticsContextField}${envContextField}${authContextField}
|
|
1371
|
+
readonly storage: ReadOnlyStorage<StorageBucketName>;${accessContextField}${kvContextField}${flagsContextField}${notifyContextField}${analyticsContextField}${envContextField}${authContextField}
|
|
1353
1372
|
}
|
|
1354
1373
|
|
|
1355
1374
|
export interface MutationCtx extends Omit<MutationCtxBase, "db" | "storage"${workflowsOmit}${authOmit}${envOmit}> {
|
|
1356
1375
|
readonly db: Omit<DatabaseWriter, "query" | "get"> & DatabaseWriterFacade & { query: TypedTableQuery; get: TypedTableGet };
|
|
1357
1376
|
readonly orm: OrmWriter;
|
|
1358
|
-
readonly storage: ReadOnlyStorage<StorageBucketName>;${accessContextField}${kvContextField}${flagsContextField}${analyticsContextField}${envContextField}${workflowsContextField}${queuesContextField}${agentsContextField}${authContextField}
|
|
1377
|
+
readonly storage: ReadOnlyStorage<StorageBucketName>;${accessContextField}${kvContextField}${flagsContextField}${notifyContextField}${analyticsContextField}${envContextField}${workflowsContextField}${queuesContextField}${agentsContextField}${authContextField}
|
|
1359
1378
|
}
|
|
1360
1379
|
|
|
1361
1380
|
export interface ActionCtx extends Omit<ActionCtxBase, "db" | "storage"${workflowsOmit}${authOmit}${envOmit}> {
|
|
1362
1381
|
readonly db: Omit<DatabaseWriter, "query" | "get"> & DatabaseWriterFacade & { query: TypedTableQuery; get: TypedTableGet };
|
|
1363
1382
|
readonly orm: OrmWriter;
|
|
1364
|
-
readonly storage: StorageBase<StorageBucketName>;${accessContextField}${aiActionField}${paymentsActionField}${x402ActionField}${containersActionField}${kvContextField}${flagsContextField}${hyperdriveActionField}${browserActionField}${imagesActionField}${analyticsContextField}${pipelinesActionField}${r2sqlActionField}${envContextField}${workflowsContextField}${queuesContextField}${agentsContextField}${authContextField}
|
|
1383
|
+
readonly storage: StorageBase<StorageBucketName>;${accessContextField}${aiActionField}${paymentsActionField}${x402ActionField}${containersActionField}${kvContextField}${flagsContextField}${notifyContextField}${hyperdriveActionField}${browserActionField}${imagesActionField}${analyticsContextField}${pipelinesActionField}${r2sqlActionField}${envContextField}${workflowsContextField}${queuesContextField}${agentsContextField}${authContextField}
|
|
1365
1384
|
}
|
|
1366
1385
|
|
|
1367
1386
|
/**
|
|
@@ -1625,6 +1644,9 @@ const buildTableIndexes = (schema) => {
|
|
|
1625
1644
|
...table.searchIndexes.map((index) => {
|
|
1626
1645
|
return { fields: [index.field, ...index.filterFields ?? []], name: index.name, type: "search" };
|
|
1627
1646
|
}),
|
|
1647
|
+
...(table.geoIndexes ?? []).map((index) => {
|
|
1648
|
+
return { fields: [index.field], name: index.name, type: "geo" };
|
|
1649
|
+
}),
|
|
1628
1650
|
...table.rankIndexes.map((index) => {
|
|
1629
1651
|
return { fields: index.sortBy.map((key) => key.field), name: index.name, type: "rank" };
|
|
1630
1652
|
}),
|
|
@@ -1638,6 +1660,21 @@ const buildTableIndexes = (schema) => {
|
|
|
1638
1660
|
}
|
|
1639
1661
|
return byTable;
|
|
1640
1662
|
};
|
|
1663
|
+
const buildTtlSweeps = (schema) => {
|
|
1664
|
+
const sweeps = [];
|
|
1665
|
+
for (const table of schema.tables) {
|
|
1666
|
+
if (!table.ttl || table.shardMode === "global") {
|
|
1667
|
+
continue;
|
|
1668
|
+
}
|
|
1669
|
+
sweeps.push({
|
|
1670
|
+
...table.ttl.after === void 0 ? {} : { after: table.ttl.after },
|
|
1671
|
+
field: table.ttl.field,
|
|
1672
|
+
...table.softDelete ? { softDeleteField: table.softDelete.field } : {},
|
|
1673
|
+
table: table.name
|
|
1674
|
+
});
|
|
1675
|
+
}
|
|
1676
|
+
return sweeps;
|
|
1677
|
+
};
|
|
1641
1678
|
const buildTableColumns = (schema) => {
|
|
1642
1679
|
const byTable = {};
|
|
1643
1680
|
for (const table of schema.tables) {
|
|
@@ -1690,7 +1727,16 @@ const emitAiFragments = (hasAi) => {
|
|
|
1690
1727
|
// a handler is never locked to Workers AI. Falls back to `aiStub`.
|
|
1691
1728
|
build: `
|
|
1692
1729
|
const aiBinding = config.ai?.(env) ?? (env as Record<string, unknown>).AI;
|
|
1693
|
-
|
|
1730
|
+
// Correlate AI-Gateway-routed calls with the Lunora trace: thread the
|
|
1731
|
+
// function path + trace id into createAi, which folds them into the
|
|
1732
|
+
// gateway's native \`metadata\` only when a gateway is configured (absent
|
|
1733
|
+
// otherwise). Mirror the tracer's anchor guard — a deferred subscription
|
|
1734
|
+
// re-run must not borrow a concurrent dispatch's trace, so read
|
|
1735
|
+
// \`getCurrentTrace()\` only on the synchronous (non-threaded-identity) path.
|
|
1736
|
+
const aiTrace = options.identity ? undefined : this.getCurrentTrace();
|
|
1737
|
+
const ai: LunoraAi = aiBinding
|
|
1738
|
+
? createAi({ binding: aiBinding as AiBindingLike, env: env as Record<string, unknown>, metadata: { functionPath: options.functionPath, traceId: aiTrace?.traceId } })
|
|
1739
|
+
: aiStub;
|
|
1694
1740
|
`,
|
|
1695
1741
|
// Optional override for the Workers AI binding. When omitted, ctx.ai is
|
|
1696
1742
|
// built from `env.AI` (the conventional binding the config layer
|
|
@@ -1781,6 +1827,22 @@ const emitFlagsFragments = (hasFlags, flagsSpecifier) => {
|
|
|
1781
1827
|
stub: ""
|
|
1782
1828
|
};
|
|
1783
1829
|
};
|
|
1830
|
+
const emitNotifyFragments = (hasNotify) => {
|
|
1831
|
+
if (!hasNotify) {
|
|
1832
|
+
return EMPTY_HELPER_FRAGMENTS;
|
|
1833
|
+
}
|
|
1834
|
+
return {
|
|
1835
|
+
build: `
|
|
1836
|
+
const { notify, push } = createNotify(notifyConfig, env);
|
|
1837
|
+
`,
|
|
1838
|
+
configField: "",
|
|
1839
|
+
contextField: `
|
|
1840
|
+
notify,
|
|
1841
|
+
push,`,
|
|
1842
|
+
importLines: [`import { createNotify } from "@lunora/notify";`, `import notifyConfig from "../notify.js";`],
|
|
1843
|
+
stub: ""
|
|
1844
|
+
};
|
|
1845
|
+
};
|
|
1784
1846
|
const emitEnvFragments = (env) => {
|
|
1785
1847
|
if (!env) {
|
|
1786
1848
|
return EMPTY_HELPER_FRAGMENTS;
|
|
@@ -2525,6 +2587,7 @@ const emitShard = ({
|
|
|
2525
2587
|
hasHyperdrive = false,
|
|
2526
2588
|
hasImages = false,
|
|
2527
2589
|
hasKv = false,
|
|
2590
|
+
hasNotify = false,
|
|
2528
2591
|
hasPayments = false,
|
|
2529
2592
|
hasPipelines = false,
|
|
2530
2593
|
hasR2sql = false,
|
|
@@ -2548,6 +2611,7 @@ const emitShard = ({
|
|
|
2548
2611
|
const kvFragments = emitKvFragments(hasKv);
|
|
2549
2612
|
const flagsFragments = emitFlagsFragments(hasFlags, base.flags);
|
|
2550
2613
|
const flagsOverrides = emitFlagsOverrides(flagKeys, hasFlags, base.flags);
|
|
2614
|
+
const notifyFragments = emitNotifyFragments(hasNotify);
|
|
2551
2615
|
const envFragments = emitEnvFragments(env);
|
|
2552
2616
|
const analyticsFragments = emitAnalyticsFragments(hasAnalytics);
|
|
2553
2617
|
const imagesFragments = emitImagesFragments(hasImages);
|
|
@@ -2613,6 +2677,7 @@ const emitShard = ({
|
|
|
2613
2677
|
const tableIndexes = buildTableIndexes(schema);
|
|
2614
2678
|
const tableColumns = buildTableColumns(schema);
|
|
2615
2679
|
const storageColumns = buildStorageColumns(schema);
|
|
2680
|
+
const ttlSweeps = buildTtlSweeps(schema);
|
|
2616
2681
|
const doTypeImports = buildDoTypeImports(hasVectors, workflows.length > 0, queues.length > 0, hasFlags);
|
|
2617
2682
|
if (hasShapes) {
|
|
2618
2683
|
doTypeImports.push("WhereInput");
|
|
@@ -2705,6 +2770,7 @@ const LUNORA_RLS_READ_REGISTRY = buildRlsReadRegistry(Object.values(LUNORA_FUNCT
|
|
|
2705
2770
|
...accessFragments.importLines,
|
|
2706
2771
|
...kvFragments.importLines,
|
|
2707
2772
|
...flagsFragments.importLines,
|
|
2773
|
+
...notifyFragments.importLines,
|
|
2708
2774
|
...envFragments.importLines,
|
|
2709
2775
|
...analyticsFragments.importLines,
|
|
2710
2776
|
...imagesFragments.importLines,
|
|
@@ -2987,10 +3053,8 @@ const sourcePollAtCache = new WeakMap<object, Map<string, number>>();
|
|
|
2987
3053
|
return nextDueAt;
|
|
2988
3054
|
}
|
|
2989
3055
|
` : "";
|
|
2990
|
-
const
|
|
2991
|
-
|
|
2992
|
-
super(state, env);
|
|
2993
|
-
|
|
3056
|
+
const hasTtlTables = ttlSweeps.length > 0;
|
|
3057
|
+
const sourceBootstrap = hasSourcedTables ? `
|
|
2994
3058
|
const autoSourced = Object.values((schema as unknown as SchemaLike).tables).some((definition) => {
|
|
2995
3059
|
const source = (definition as { externalSource?: ExternalSourceLike }).externalSource;
|
|
2996
3060
|
|
|
@@ -3000,7 +3064,16 @@ const sourcePollAtCache = new WeakMap<object, Map<string, number>>();
|
|
|
3000
3064
|
if (autoSourced) {
|
|
3001
3065
|
void this.scheduleSourcePoll();
|
|
3002
3066
|
}
|
|
3003
|
-
|
|
3067
|
+
` : "";
|
|
3068
|
+
const ttlBootstrap = hasTtlTables ? `
|
|
3069
|
+
if (LUNORA_TTL_SWEEPS.length > 0) {
|
|
3070
|
+
void this.scheduleTtlSweep();
|
|
3071
|
+
}
|
|
3072
|
+
` : "";
|
|
3073
|
+
const sourceConstructorOverride = hasSourcedTables || hasTtlTables ? `
|
|
3074
|
+
public constructor(state: ShardDOState, env: unknown) {
|
|
3075
|
+
super(state, env);
|
|
3076
|
+
${sourceBootstrap}${ttlBootstrap} }
|
|
3004
3077
|
` : "";
|
|
3005
3078
|
const facadeBlock = hasTables ? `
|
|
3006
3079
|
const facade = db as unknown as Record<string, ReturnType<typeof bindTableFacade>>;
|
|
@@ -3017,8 +3090,8 @@ ${schema.tables.map(
|
|
|
3017
3090
|
const secretsBuild = `
|
|
3018
3091
|
const secrets = createSecrets(env);
|
|
3019
3092
|
`;
|
|
3020
|
-
const everyContextBuild = `${accessFragments.build}${kvFragments.build}${flagsFragments.build}${analyticsFragments.build}${envFragments.build}${secretsBuild}`;
|
|
3021
|
-
const everyContextField = `${accessFragments.contextField}${kvFragments.contextField}${flagsFragments.contextField}${analyticsFragments.contextField}${envFragments.contextField}
|
|
3093
|
+
const everyContextBuild = `${accessFragments.build}${kvFragments.build}${flagsFragments.build}${notifyFragments.build}${analyticsFragments.build}${envFragments.build}${secretsBuild}`;
|
|
3094
|
+
const everyContextField = `${accessFragments.contextField}${kvFragments.contextField}${flagsFragments.contextField}${notifyFragments.contextField}${analyticsFragments.contextField}${envFragments.contextField}
|
|
3022
3095
|
secrets,`;
|
|
3023
3096
|
const actionOnlyHasAny = hasImages || hasHyperdrive || hasBrowser || hasR2sql || hasPipelines || hasX402;
|
|
3024
3097
|
const actionOnlyBlock = actionOnlyHasAny ? `
|
|
@@ -3048,8 +3121,8 @@ interface FunctionReference {
|
|
|
3048
3121
|
/** Foreign-key columns per table (\`v.id("target")\` fields) for the data browser. */
|
|
3049
3122
|
const LUNORA_TABLE_REFS: Record<string, Record<string, string>> = ${JSON.stringify(tableReferences, void 0, 4)};
|
|
3050
3123
|
|
|
3051
|
-
/** Declared indexes per table (secondary, search, rank, vector) for the schema viewer. */
|
|
3052
|
-
const LUNORA_TABLE_INDEXES: Record<string, Array<{ fields: string[]; name: string; type: "index" | "rank" | "search" | "vector"; unique?: boolean }>> = ${JSON.stringify(tableIndexes, void 0, 4)};
|
|
3124
|
+
/** Declared indexes per table (secondary, search, geo, rank, vector) for the schema viewer. */
|
|
3125
|
+
const LUNORA_TABLE_INDEXES: Record<string, Array<{ fields: string[]; name: string; type: "geo" | "index" | "rank" | "search" | "vector"; unique?: boolean }>> = ${JSON.stringify(tableIndexes, void 0, 4)};
|
|
3053
3126
|
|
|
3054
3127
|
/** Columns per table (typed, with PK/FK markers) for the studio's schema diagram, served via \`__lunora_admin__:describeTable\`. */
|
|
3055
3128
|
const LUNORA_TABLE_COLUMNS: Record<string, Array<{ isStorage?: boolean; name: string; optional: boolean; pk?: boolean; ref?: string; type: string }>> = ${JSON.stringify(tableColumns, void 0, 4)};
|
|
@@ -3057,6 +3130,9 @@ const LUNORA_TABLE_COLUMNS: Record<string, Array<{ isStorage?: boolean; name: st
|
|
|
3057
3130
|
/** Storage-key columns per table (\`v.storage(...)\` fields) for the file browser's records↔files join. */
|
|
3058
3131
|
const LUNORA_STORAGE_COLUMNS: Record<string, string[]> = ${JSON.stringify(storageColumns, void 0, 4)};
|
|
3059
3132
|
|
|
3133
|
+
/** Declarative TTL policies (\`.ttl(field, { after? })\`) the DO alarm sweep auto-expires rows for. */
|
|
3134
|
+
const LUNORA_TTL_SWEEPS: Array<{ after?: number; field: string; softDeleteField?: string; table: string }> = ${JSON.stringify(ttlSweeps, void 0, 4)};
|
|
3135
|
+
|
|
3060
3136
|
/** Static schema advisories (computed by @lunora/advisor at codegen time) served via \`__lunora_admin__:getAdvisories\`. */
|
|
3061
3137
|
const LUNORA_ADVISORIES: AdvisoryFinding[] = ${JSON.stringify(advisoryData, void 0, 4)};
|
|
3062
3138
|
|
|
@@ -3238,10 +3314,14 @@ ${customMutatorOverride}${shapeResolveOverride}${globalShapeReaderOverride}${ext
|
|
|
3238
3314
|
return LUNORA_TABLE_REFS[table];
|
|
3239
3315
|
}
|
|
3240
3316
|
|
|
3241
|
-
protected override tableIndexes(table: string): Array<{ fields: string[]; name: string; type: "index" | "rank" | "search" | "vector"; unique?: boolean }> {
|
|
3317
|
+
protected override tableIndexes(table: string): Array<{ fields: string[]; name: string; type: "geo" | "index" | "rank" | "search" | "vector"; unique?: boolean }> {
|
|
3242
3318
|
return LUNORA_TABLE_INDEXES[table] ?? [];
|
|
3243
3319
|
}
|
|
3244
3320
|
|
|
3321
|
+
protected override ttlSweeps(): ReadonlyArray<{ after?: number; field: string; softDeleteField?: string; table: string }> {
|
|
3322
|
+
return LUNORA_TTL_SWEEPS;
|
|
3323
|
+
}
|
|
3324
|
+
|
|
3245
3325
|
protected override tableColumns(table: string): Array<{ isStorage?: boolean; name: string; optional: boolean; pk?: boolean; ref?: string; type: string }> {
|
|
3246
3326
|
return LUNORA_TABLE_COLUMNS[table] ?? [];
|
|
3247
3327
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as APP_METHOD_CAPABILITIES, G as GENERATED_HEADER } from './emit-
|
|
1
|
+
import { A as APP_METHOD_CAPABILITIES, G as GENERATED_HEADER } from './emit-B4LUyyg7.mjs';
|
|
2
2
|
|
|
3
3
|
const hasFlagKey = (key) => `has${key.charAt(0).toUpperCase()}${key.slice(1)}`;
|
|
4
4
|
const LONG_TAIL = APP_METHOD_CAPABILITIES.map(
|
|
@@ -11,6 +11,7 @@ const buildAccessImports = (hasAccess, hasAuth) => hasAccess ? [
|
|
|
11
11
|
`import { createAccessResolver${hasAuth ? ", composeResolvers" : ""} } from "@lunora/cloudflare-access";`
|
|
12
12
|
] : [];
|
|
13
13
|
const buildKvImports = (hasKv) => hasKv ? [`import { createKvIntrospectorFromEnv } from "@lunora/bindings/kv";`] : [];
|
|
14
|
+
const buildNotifyImports = (hasNotify) => hasNotify ? [`import notifyConfig from "../notify.js";`] : [];
|
|
14
15
|
const hasEmailAgents = (options) => (options.emailAgents?.length ?? 0) > 0;
|
|
15
16
|
const buildInboundImports = (options) => hasEmailAgents(options) ? [`import { dispatchAgentEmail } from "@lunora/agent/inbound";`] : [];
|
|
16
17
|
const buildAgentDefinitionsImport = (options) => hasEmailAgents(options) ? [`import * as lunoraAgentDefinitions from "../agents.js";`] : [];
|
|
@@ -47,7 +48,7 @@ const buildImportLines = (options) => {
|
|
|
47
48
|
return [
|
|
48
49
|
...hasAuth ? [
|
|
49
50
|
`import type { LunoraAuth, LunoraAuthOptions } from "@lunora/auth";`,
|
|
50
|
-
`import { createAuth, createAuthAdmin, ensureMigrated, handleAuthRequest, lunoraD1Adapter } from "@lunora/auth";`
|
|
51
|
+
`import { createAuth, createAuthAdmin, createAuthAuditReader, d1Executor, ensureMigrated, handleAuthRequest, lunoraD1Adapter } from "@lunora/auth";`
|
|
51
52
|
] : [],
|
|
52
53
|
...buildAccessImports(hasAccess, hasAuth),
|
|
53
54
|
...hasGlobal ? [
|
|
@@ -70,6 +71,7 @@ const buildImportLines = (options) => {
|
|
|
70
71
|
...buildIdentityImports(options.identity),
|
|
71
72
|
...buildAgentDefinitionsImport(options),
|
|
72
73
|
...hasGlobal || hasHyperdriveGlobal ? [`import schema from "../schema.js";`] : [],
|
|
74
|
+
...buildNotifyImports(options.hasNotify),
|
|
73
75
|
`import { LUNORA_CRONS } from "./crons.js";`,
|
|
74
76
|
`import { LUNORA_FUNCTIONS } from "./functions.js";`,
|
|
75
77
|
...hasQueue ? [
|
|
@@ -352,6 +354,12 @@ const buildWorkerOptionLines = (options) => [
|
|
|
352
354
|
// with no manual `createKvIntrospector` call. A deployment with no KV binding
|
|
353
355
|
// yields an empty namespace list rather than crashing.
|
|
354
356
|
...options.hasKv ? [` options.kvIntrospector = createKvIntrospectorFromEnv(env);`] : [],
|
|
357
|
+
// The studio's Notifications page reads the app's registered `@lunora/notify`
|
|
358
|
+
// device subscriptions through the SAME store the handlers register into. The
|
|
359
|
+
// store is built from `env` via `lunora/notify.ts`'s `defineNotify({ store })`;
|
|
360
|
+
// when no `store` is configured (the in-memory default), the gated
|
|
361
|
+
// `__lunora_admin__:listPushSubscriptions` RPC returns an empty device list.
|
|
362
|
+
...options.hasNotify ? [` options.notifySubscriptionStore = notifyConfig.store ? notifyConfig.store(env) : undefined;`] : [],
|
|
355
363
|
// The studio's Logs → Archive feed is wired zero-config: when the operator sets
|
|
356
364
|
// `LUNORA_LOG_ARCHIVE_TABLE` (the R2 Data Catalog table `pipelineLogSink` writes
|
|
357
365
|
// to), the durable archive becomes readable; unset ⇒ `undefined` ⇒ the feed
|
|
@@ -378,6 +386,7 @@ const buildWorkerOptionLines = (options) => [
|
|
|
378
386
|
const authInstance = getAuth();
|
|
379
387
|
|
|
380
388
|
options.authAdmin = authInstance ? createAuthAdmin(authInstance) : undefined;
|
|
389
|
+
options.authAuditReader = createAuthAuditReader(d1Executor(this.authDeclaration.d1(env) as never));
|
|
381
390
|
}`
|
|
382
391
|
] : [],
|
|
383
392
|
// Cloudflare Access — runs AFTER the auth block so it can compose ahead of
|
|
@@ -12,8 +12,18 @@ const flattenIndexes = (table) => [
|
|
|
12
12
|
}),
|
|
13
13
|
...table.vectorIndexes.filter((index) => index.field !== void 0).map((index) => {
|
|
14
14
|
return { fields: [index.field], kind: "vector", name: index.name };
|
|
15
|
+
}),
|
|
16
|
+
...(table.geoIndexes ?? []).map((index) => {
|
|
17
|
+
return { fields: [index.field], kind: "geo", name: index.name };
|
|
15
18
|
})
|
|
16
19
|
];
|
|
20
|
+
const columnKindsOf = (table) => {
|
|
21
|
+
const kinds = {};
|
|
22
|
+
for (const [fieldName, validator] of Object.entries(table.shape)) {
|
|
23
|
+
kinds[fieldName] = validator.kind === "optional" ? validator.inner?.kind ?? "optional" : validator.kind;
|
|
24
|
+
}
|
|
25
|
+
return kinds;
|
|
26
|
+
};
|
|
17
27
|
const toAdvisorSchema = (schema) => {
|
|
18
28
|
return {
|
|
19
29
|
rlsMode: schema.rlsMode,
|
|
@@ -27,6 +37,7 @@ const toAdvisorSchema = (schema) => {
|
|
|
27
37
|
mode: table.externalSource.mode,
|
|
28
38
|
unanalyzable: table.externalSource.unanalyzable
|
|
29
39
|
} : void 0,
|
|
40
|
+
columnKinds: columnKindsOf(table),
|
|
30
41
|
fields: Object.keys(table.shape),
|
|
31
42
|
indexes: flattenIndexes(table),
|
|
32
43
|
isPublic: table.isPublic ?? false,
|
|
@@ -42,7 +53,8 @@ const toAdvisorSchema = (schema) => {
|
|
|
42
53
|
};
|
|
43
54
|
}),
|
|
44
55
|
shardKind: typeof table.shardMode === "string" ? table.shardMode : "shardBy",
|
|
45
|
-
softDelete: table.softDelete
|
|
56
|
+
softDelete: table.softDelete,
|
|
57
|
+
ttl: table.ttl
|
|
46
58
|
};
|
|
47
59
|
})
|
|
48
60
|
};
|
|
@@ -64,8 +76,10 @@ const lintSchema = (options) => runAdvisor(
|
|
|
64
76
|
containerKeyAccesses: options.containerKeyAccesses,
|
|
65
77
|
containerOverrides: options.containerOverrides,
|
|
66
78
|
containers: options.containers,
|
|
79
|
+
exportSinks: options.exportSinks,
|
|
67
80
|
failOpenGuards: options.failOpenGuards,
|
|
68
81
|
flagSecurityDefaults: options.flagSecurityDefaults,
|
|
82
|
+
geoIndexUsages: options.geoIndexUsages,
|
|
69
83
|
httpActionGuards: options.httpActionGuards,
|
|
70
84
|
httpHeaderWrites: options.httpHeaderWrites,
|
|
71
85
|
identityClaimReads: options.identityClaimReads,
|
|
@@ -78,6 +92,8 @@ const lintSchema = (options) => runAdvisor(
|
|
|
78
92
|
mutatorWrites: options.mutatorWrites,
|
|
79
93
|
nondeterministicCalls: options.nondeterministicCalls,
|
|
80
94
|
normalizeIdAuthorizations: options.normalizeIdAuthorizations,
|
|
95
|
+
notifyCalls: options.notifyCalls,
|
|
96
|
+
notifyConfig: options.notifyConfig,
|
|
81
97
|
ownerFieldWrites: options.ownerFieldWrites,
|
|
82
98
|
paymentWebhooks: options.paymentWebhooks,
|
|
83
99
|
privilegedDispatches: options.privilegedDispatches,
|
|
@@ -30,7 +30,7 @@ const applyColumnModifier = (base, modifier) => {
|
|
|
30
30
|
}
|
|
31
31
|
return { ...base, column };
|
|
32
32
|
};
|
|
33
|
-
const SCALAR_KINDS = /* @__PURE__ */ new Set(["any", "bigint", "boolean", "bytes", "date", "null", "number", "string", "timestamp"]);
|
|
33
|
+
const SCALAR_KINDS = /* @__PURE__ */ new Set(["any", "bigint", "boolean", "bytes", "date", "geoPoint", "null", "number", "string", "timestamp"]);
|
|
34
34
|
const TRANSPARENT_MODIFIERS = /* @__PURE__ */ new Set(["check", "meta"]);
|
|
35
35
|
const parseValidator = (expression) => {
|
|
36
36
|
if (Node.isCallExpression(expression)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/codegen",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.52",
|
|
4
4
|
"description": "Code generator for Lunora: emits _generated/{api,server,dataModel}.ts from your schema",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -46,14 +46,14 @@
|
|
|
46
46
|
"access": "public"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@lunora/advisor": "1.0.0-alpha.
|
|
50
|
-
"@lunora/agent": "1.0.0-alpha.
|
|
51
|
-
"@lunora/container": "1.0.0-alpha.
|
|
52
|
-
"@lunora/errors": "1.0.0-alpha.
|
|
49
|
+
"@lunora/advisor": "1.0.0-alpha.33",
|
|
50
|
+
"@lunora/agent": "1.0.0-alpha.9",
|
|
51
|
+
"@lunora/container": "1.0.0-alpha.14",
|
|
52
|
+
"@lunora/errors": "1.0.0-alpha.7",
|
|
53
53
|
"@lunora/queue": "1.0.0-alpha.9",
|
|
54
54
|
"@lunora/scheduler": "1.0.0-alpha.11",
|
|
55
|
-
"@lunora/values": "1.0.0-alpha.
|
|
56
|
-
"@lunora/workflow": "1.0.0-alpha.
|
|
55
|
+
"@lunora/values": "1.0.0-alpha.10",
|
|
56
|
+
"@lunora/workflow": "1.0.0-alpha.12",
|
|
57
57
|
"ts-morph": "^28.0.0"
|
|
58
58
|
},
|
|
59
59
|
"engines": {
|