@lunora/codegen 1.0.0-alpha.336 → 1.0.0-alpha.337
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 +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/{SCHEMA_SNAPSHOT_FILENAME-DcWyFDv9.mjs → SCHEMA_SNAPSHOT_FILENAME-6cfIWExE.mjs} +1 -1
- package/dist/packem_shared/SCHEMA_SNAPSHOT_VERSION-C7Um0EnM.mjs +2 -0
- package/dist/packem_shared/SchemaSnapshotParseError-H9eQX4ui.mjs +18 -0
- package/dist/packem_shared/{emitAgents-C9JRmvrC.mjs → emitAgents--VDKoet4.mjs} +1 -1
- package/dist/packem_shared/{emitShard-FJhdFx9H.mjs → emitShard-fpKA7Svs.mjs} +1 -1
- package/dist/packem_shared/{shard-B6afe1Uh.mjs → shard-BCqz_05A.mjs} +128 -51
- package/dist/packem_shared/{shard-runtime-BW1kffN4.mjs → shard-runtime-ByYXjCKY.mjs} +1 -1
- package/package.json +7 -7
- package/dist/packem_shared/SCHEMA_SNAPSHOT_VERSION-C0oHwiJZ.mjs +0 -2
- package/dist/packem_shared/SchemaSnapshotParseError-BRJT7c2k.mjs +0 -18
package/dist/index.d.mts
CHANGED
|
@@ -93,6 +93,12 @@ interface FieldSnapshot {
|
|
|
93
93
|
nullable?: boolean;
|
|
94
94
|
/** `v.array(inner)` element / `v.record(…, value)` value shape. */
|
|
95
95
|
of?: FieldSnapshot;
|
|
96
|
+
/**
|
|
97
|
+
* `v.from(schema)` — the wrapped schema's inferred OUTPUT type as TS source, the
|
|
98
|
+
* type the column is stored and read as. Absent when it could not be resolved,
|
|
99
|
+
* and on baselines written before it was recorded; see {@link comparableFromOutput}.
|
|
100
|
+
*/
|
|
101
|
+
output?: string;
|
|
96
102
|
/** True when declared `v.optional(...)` — accepts `undefined` / absent on insert. */
|
|
97
103
|
optional: boolean;
|
|
98
104
|
/** `v.id("table")` — the referenced table. */
|
package/dist/index.d.ts
CHANGED
|
@@ -93,6 +93,12 @@ interface FieldSnapshot {
|
|
|
93
93
|
nullable?: boolean;
|
|
94
94
|
/** `v.array(inner)` element / `v.record(…, value)` value shape. */
|
|
95
95
|
of?: FieldSnapshot;
|
|
96
|
+
/**
|
|
97
|
+
* `v.from(schema)` — the wrapped schema's inferred OUTPUT type as TS source, the
|
|
98
|
+
* type the column is stored and read as. Absent when it could not be resolved,
|
|
99
|
+
* and on baselines written before it was recorded; see {@link comparableFromOutput}.
|
|
100
|
+
*/
|
|
101
|
+
output?: string;
|
|
96
102
|
/** True when declared `v.optional(...)` — accepts `undefined` / absent on insert. */
|
|
97
103
|
optional: boolean;
|
|
98
104
|
/** `v.id("table")` — the referenced table. */
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{SCHEMA_SNAPSHOT_VERSION as t,diffSchemaSnapshots as a,serializeSchemaSnapshot as s}from"./packem_shared/SCHEMA_SNAPSHOT_VERSION-
|
|
1
|
+
import{SCHEMA_SNAPSHOT_VERSION as t,diffSchemaSnapshots as a,serializeSchemaSnapshot as s}from"./packem_shared/SCHEMA_SNAPSHOT_VERSION-C7Um0EnM.mjs";import{formatAdvisories as f,lintSchema as m,toAdvisorContext as d}from"./packem_shared/formatAdvisories-BCVASH7N.mjs";import{describeErrorLevelFindings as n,errorAdvisoryNames as l,errorPlatformDiagnosticNames as c,sortedUniqueNames as x}from"./packem_shared/describeErrorLevelFindings-vzaGS9KL.mjs";import{CAPABILITY_PROBES as E}from"./packem_shared/CAPABILITY_PROBES-brcmKenl.mjs";import{CodegenDiagnosticError as A,diagnosticAt as v}from"./packem_shared/CodegenDiagnosticError-BUXlG3P-.mjs";import{AGENTS_FILENAME as g,discoverAgents as N}from"./packem_shared/AGENTS_FILENAME-isdHqPIt.mjs";import{isTestPath as R,listLunoraSourceFiles as h}from"./packem_shared/isTestPath-C3QumE88.mjs";import{default as I}from"./packem_shared/discoverAuthApiCalls-CScPrUD-.mjs";import{CONTAINERS_FILENAME as L,discoverContainers as M}from"./packem_shared/CONTAINERS_FILENAME-mK4cZpcz.mjs";import{default as P}from"./packem_shared/discoverCrons-B1_NUt19.mjs";import{capabilitiesUsedBy as b,foldCapabilitySignals as y,mayReadCapabilityContext as U,sourceCapabilitySignals as G}from"./packem_shared/capabilitiesUsedBy-C-7D7vlH.mjs";import{FLAGS_FILENAME as j,discoverFlags as B}from"./packem_shared/FLAGS_FILENAME-BQk3SX8D.mjs";import{default as W}from"./packem_shared/discoverFunctions-DkPOc8b9.mjs";import{default as V}from"./packem_shared/discoverHttpRoutes-DCDgDIYv.mjs";import{default as Q}from"./packem_shared/discoverHyperdriveCalls-CL-d0IVo.mjs";import{default as w}from"./packem_shared/discoverInserts-BcoTjXqI.mjs";import{d as Y}from"./packem_shared/index-CN8FVvr-.mjs";import{default as Z}from"./packem_shared/discoverMigrations-BWxx8Wv9.mjs";import{MUTATORS_FILENAME as ee,discoverMutators as re}from"./packem_shared/MUTATORS_FILENAME-Cy9h3EVW.mjs";import{default as te}from"./packem_shared/discoverNondeterministicCalls-3INW8oqs.mjs";import{NOTIFY_FILENAME as se,discoverNotifyCalls as ie,discoverNotifyChannels as fe,discoverNotifyConfig as me}from"./packem_shared/NOTIFY_FILENAME-9to_l_Kh.mjs";import{default as pe}from"./packem_shared/readPackageDependencies-RHhGiz0k.mjs";import{default as le}from"./packem_shared/discoverQueries-CxQRVuIV.mjs";import{QUEUES_FILENAME as xe,discoverQueues as Se}from"./packem_shared/QUEUES_FILENAME-Civ-7SiI.mjs";import{default as ue}from"./packem_shared/discoverR2sqlCalls-B4oeTYEM.mjs";import{default as ve}from"./packem_shared/discoverRlsProcedures-Cl6UKT7L.mjs";import{default as ge}from"./packem_shared/discoverRlsMetadata-D0B4nCmG.mjs";import{discoverSandboxUsage as Oe}from"./packem_shared/discoverSandboxUsage--Z1vx7GM.mjs";import{default as he}from"./packem_shared/discoverSchema-Cwt-DQgh.mjs";import{readServiceBindings as Ie,resolveServiceBindings as _e}from"./packem_shared/readServiceBindings-BA49C6aN.mjs";import{SHAPES_FILENAME as Me,discoverShapes as Fe}from"./packem_shared/SHAPES_FILENAME-DVJbfDZ8.mjs";import{default as De}from"./packem_shared/discoverStorageRulesMetadata-CitX6ziW.mjs";import{WORKFLOWS_FILENAME as ye,discoverWorkflows as Ue}from"./packem_shared/WORKFLOWS_FILENAME-kXq07aGl.mjs";import{emitApp as He}from"./packem_shared/emitApp-BL16wvE9.mjs";import{isD1GlobalTable as Be,isHyperdriveGlobalTable as ke}from"./packem_shared/isD1GlobalTable-udvHAAzD.mjs";import{buildOpenApiDocument as Ke,emitOpenApi as Ve,emitOpenApiModule as ze}from"./packem_shared/buildOpenApiDocument-DWdj2jvW.mjs";import{OPENRPC_VERSION as qe,buildOpenRpcDocument as we,emitOpenRpc as Je,emitOpenRpcModule as Ye}from"./packem_shared/OPENRPC_VERSION-l4HD4osw.mjs";import{DEFAULT_TARGET as Ze,platformMatrixIds as $e,readProjectTarget as er,resolveCodegenTarget as rr}from"./packem_shared/DEFAULT_TARGET-3OLdJhTj.mjs";import{loadProjectConfig as tr,readProjectConfigLiterals as ar}from"./packem_shared/loadProjectConfig-B7RmxIeD.mjs";import{PROJECT_CONFIG_FILENAMES as ir,findCodegenConfigFile as fr,findProjectConfigFile as mr,projectConfigCandidatePaths as dr}from"./packem_shared/PROJECT_CONFIG_FILENAMES-CLfsyvjA.mjs";import{SCHEMA_SNAPSHOT_FILENAME as nr,runCodegen as lr}from"./packem_shared/SCHEMA_SNAPSHOT_FILENAME-6cfIWExE.mjs";import{SchemaSnapshotParseError as xr,buildSchemaSnapshot as Sr,evaluateSchemaDrift as Er,parseSchemaSnapshot as ur}from"./packem_shared/SchemaSnapshotParseError-H9eQX4ui.mjs";import{default as vr}from"./packem_shared/fingerprintSchemaSources-BKXkgkj4.mjs";import{schemaFromIr as gr}from"./packem_shared/schemaFromIr-BWFnvCVg.mjs";import{LUNORA_ERROR_CODES as Or,validatorIrToJsonSchema as Rr}from"./packem_shared/LUNORA_ERROR_CODES-CIAJQeKB.mjs";import{SDK_LANGUAGES as Tr,SDK_TARGETS as Ir,generateSdk as _r}from"./sdk/index.mjs";import{redact as Mr,secretKindOf as Fr}from"./packem_shared/redact-Cy14LEnc.mjs";import{default as Dr}from"./packem_shared/emitDrizzleSchema-bct1OuH5.mjs";import{e as yr}from"./packem_shared/server-B6VhYK7m.mjs";import{e as Gr}from"./packem_shared/shard-BCqz_05A.mjs";import{G as jr}from"./packem_shared/shared-8vTRkL2-.mjs";import{MESSAGE_SOLUTIONS as kr,findSolutionByMessage as Wr}from"@lunora/errors";import{createCodegenProject as Vr,findTsconfig as zr,refreshCodegenProject as Qr}from"./packem_shared/createCodegenProject-R4so-yTU.mjs";import{s as wr,t as Jr,u as Yr}from"./packem_shared/shard-runtime-ByYXjCKY.mjs";import{emitApi as Zr,emitCollections as $r,emitInternalApi as eo}from"./packem_shared/emitApi-c14__tie.mjs";import{emitCrons as oo,emitScheduler as to,emitVectors as ao,emitWranglerCronTriggers as so}from"./packem_shared/emitCrons-lc-hnJYn.mjs";import{emitDataModel as fo}from"./packem_shared/emitDataModel-CuFqq97x.mjs";import{emitFunctions as po}from"./packem_shared/emitFunctions-CkBPtGDF.mjs";import{isTypedSchema as lo}from"./packem_shared/isTypedSchema-CKzc3ioR.mjs";const e="0.0.0";export{g as AGENTS_FILENAME,E as CAPABILITY_PROBES,L as CONTAINERS_FILENAME,A as CodegenDiagnosticError,Ze as DEFAULT_TARGET,j as FLAGS_FILENAME,jr as GENERATED_HEADER,Or as LUNORA_ERROR_CODES,kr as LUNORA_SOLUTION_RULES,ee as MUTATORS_FILENAME,se as NOTIFY_FILENAME,qe as OPENRPC_VERSION,ir as PROJECT_CONFIG_FILENAMES,xe as QUEUES_FILENAME,nr as SCHEMA_SNAPSHOT_FILENAME,t as SCHEMA_SNAPSHOT_VERSION,Tr as SDK_LANGUAGES,Ir as SDK_TARGETS,Me as SHAPES_FILENAME,xr as SchemaSnapshotParseError,e as VERSION,ye as WORKFLOWS_FILENAME,Ke as buildOpenApiDocument,we as buildOpenRpcDocument,Sr as buildSchemaSnapshot,b as capabilitiesUsedBy,Vr as createCodegenProject,n as describeErrorLevelFindings,v as diagnosticAt,a as diffSchemaSnapshots,N as discoverAgents,I as discoverAuthApiCalls,M as discoverContainers,P as discoverCrons,B as discoverFlags,W as discoverFunctions,V as discoverHttpRoutes,Q as discoverHyperdriveCalls,w as discoverInserts,Y as discoverMaskProcedures,Z as discoverMigrations,re as discoverMutators,te as discoverNondeterministicCalls,ie as discoverNotifyCalls,fe as discoverNotifyChannels,me as discoverNotifyConfig,le as discoverQueries,Se as discoverQueues,ue as discoverR2sqlCalls,ge as discoverRlsMetadata,ve as discoverRlsProcedures,Oe as discoverSandboxUsage,he as discoverSchema,Fe as discoverShapes,De as discoverStorageRulesMetadata,Ue as discoverWorkflows,wr as emitAgents,Zr as emitApi,He as emitApp,$r as emitCollections,Jr as emitContainers,oo as emitCrons,fo as emitDataModel,Dr as emitDrizzleSchema,po as emitFunctions,eo as emitInternalApi,Ve as emitOpenApi,ze as emitOpenApiModule,Je as emitOpenRpc,Ye as emitOpenRpcModule,to as emitScheduler,yr as emitServer,Gr as emitShard,ao as emitVectors,Yr as emitWorkflows,so as emitWranglerCronTriggers,l as errorAdvisoryNames,c as errorPlatformDiagnosticNames,Er as evaluateSchemaDrift,fr as findCodegenConfigFile,Wr as findLunoraSolution,mr as findProjectConfigFile,zr as findTsconfig,vr as fingerprintSchemaSources,y as foldCapabilitySignals,f as formatAdvisories,_r as generateSdk,Be as isD1GlobalTable,ke as isHyperdriveGlobalTable,R as isTestPath,lo as isTypedSchema,m as lintSchema,h as listLunoraSourceFiles,tr as loadProjectConfig,U as mayReadCapabilityContext,ur as parseSchemaSnapshot,$e as platformMatrixIds,dr as projectConfigCandidatePaths,pe as readPackageDependencies,ar as readProjectConfigLiterals,er as readProjectTarget,Ie as readServiceBindings,Mr as redact,Qr as refreshCodegenProject,rr as resolveCodegenTarget,_e as resolveServiceBindings,lr as runCodegen,gr as schemaFromIr,Fr as secretKindOf,s as serializeSchemaSnapshot,x as sortedUniqueNames,G as sourceCapabilitySignals,d as toAdvisorContext,Rr as validatorIrToJsonSchema};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{existsSync as M,readFileSync as Ge,mkdirSync as $t,writeFileSync as gr,rmSync as ye,readdirSync as Cn}from"node:fs";import{dirname as Bt,join as E,relative as Tn}from"node:path";import{performance as mt}from"node:perf_hooks";import{runAdvisor as pr}from"@lunora/advisor";import{LunoraError as _}from"@lunora/errors";import{serializeSchemaSnapshot as mr}from"./SCHEMA_SNAPSHOT_VERSION-
|
|
1
|
+
import{existsSync as M,readFileSync as Ge,mkdirSync as $t,writeFileSync as gr,rmSync as ye,readdirSync as Cn}from"node:fs";import{dirname as Bt,join as E,relative as Tn}from"node:path";import{performance as mt}from"node:perf_hooks";import{runAdvisor as pr}from"@lunora/advisor";import{LunoraError as _}from"@lunora/errors";import{serializeSchemaSnapshot as mr}from"./SCHEMA_SNAPSHOT_VERSION-C7Um0EnM.mjs";import{toAdvisorContext as hr}from"./formatAdvisories-BCVASH7N.mjs";import{Node as r,SyntaxKind as d,Project as Vt,ts as vr,VariableDeclarationKind as Er}from"ts-morph";import{listLunoraSourceFiles as A,lunoraRelativePath as w,bindingKeyName as ce,collectCallRows as C,findObjectProperty as V,collectSecurityCallRows as xr,propertyInitializer as R,listSecurityScanFiles as Ye,objectLiteralFromCallbackBody as On,limitNameOf as kn,optionsObjectLiteral as Rn,handlerOf as Sr,collectNodeRows as ne,chainRootOf as Qe,outermostValueWrapper as I,isWriteTarget as Xe,isSameNode as y,unwrapExpression as h,isConstDeclaration as ie,memberAccessOf as Ut,returningFunctionOf as Pt,walkChain as Ar,RUN_METHODS as Fn,functionReferenceSegments as yr,isTestPath as br,isFunctionLike as re,functionKeyOf as Ln}from"./isTestPath-C3QumE88.mjs";import{b as Q,d as j,f as L,g as Wt,c as x,a as qt,w as jt,k as Nr,l as Pr,h as wr,m as Ir,j as wt,i as Cr}from"./attribution-CG8-kUcl.mjs";import{a as Fs,r as ht,i as G,b as Tr,m as Dn,c as Je,e as Ht,E as Mn,C as _n,d as Or,f as kr,g as Rr}from"./context-root-CNR6TAsP.mjs";import{a as P,i as Fr,c as ee,d as Kn,e as Lr,f as Dr,g as zn}from"./classify-procedure-call-BkaeM9Ej.mjs";import{a as S,s as Mr}from"./property-name-7cBlgK_O.mjs";import{b as _r,a as Ze}from"./module-specifiers-BctA0m_p.mjs";import{r as et,s as Kr}from"./parse-validator-iVTounLK.mjs";import zr from"./discoverAuthApiCalls-CScPrUD-.mjs";import{i as z,r as $n}from"./database-calls-UPlhi3Ks.mjs";import $r from"./discoverHyperdriveCalls-CL-d0IVo.mjs";import{diagnosticAt as de}from"./CodegenDiagnosticError-BUXlG3P-.mjs";import{m as Gt,a as Be,s as Bn,d as Br}from"./index-CN8FVvr-.mjs";import{MUTATORS_FILENAME as Vr,isDefineMutatorCallee as Ur,mutatorServerImplOf as Wr,discoverMutators as qr}from"./MUTATORS_FILENAME-Cy9h3EVW.mjs";import jr from"./discoverNondeterministicCalls-3INW8oqs.mjs";import{discoverNotifyConfig as Hr,discoverNotifyCalls as Gr}from"./NOTIFY_FILENAME-9to_l_Kh.mjs";import Yr from"./discoverR2sqlCalls-B4oeTYEM.mjs";import Qr from"./discoverRlsProcedures-Cl6UKT7L.mjs";import{s as Yt,n as Xr}from"./dispatch-namespace-DwTjD7BU.mjs";import{secretKindOf as Jr,redact as Zr,isHeuristicSecretKind as eo,isSecretishName as to}from"./redact-Cy14LEnc.mjs";import{readProjectConfigLiterals as Vn,readMergeDurableObjects as so}from"./loadProjectConfig-B7RmxIeD.mjs";import{a as Le,d as no,r as io}from"./modules-l-Db0C4S.mjs";import{WORKFLOWS_FILENAME as ro,discoverWorkflows as oo}from"./WORKFLOWS_FILENAME-kXq07aGl.mjs";import{r as ao}from"./json-data-Chfs2Cz5.mjs";import{a as co,I as lo,g as uo,G as Un,d as fo,i as go}from"./shared-8vTRkL2-.mjs";import{createCodegenProject as po}from"./createCodegenProject-R4so-yTU.mjs";import{findTsconfig as PE,refreshCodegenProject as wE}from"./createCodegenProject-R4so-yTU.mjs";import{CAPABILITIES as mo,usedCapabilities as ho}from"./CAPABILITY_PROBES-brcmKenl.mjs";import{isD1GlobalTable as Wn,isHyperdriveGlobalTable as qn}from"./isD1GlobalTable-udvHAAzD.mjs";import{discoverAgents as vo}from"./AGENTS_FILENAME-isdHqPIt.mjs";import{discoverContainers as Eo}from"./CONTAINERS_FILENAME-mK4cZpcz.mjs";import xo from"./discoverCrons-B1_NUt19.mjs";import{contextPropertiesRead as So,fileWiresRequestSecretTool as Ao,discoverFeatureUsage as yo}from"./capabilitiesUsedBy-C-7D7vlH.mjs";import jn from"./readPackageDependencies-RHhGiz0k.mjs";import{PROJECT_CONFIG_FILENAMES as bo,findProjectConfigFile as No}from"./PROJECT_CONFIG_FILENAMES-CLfsyvjA.mjs";import{discoverQueueDeclarations as Po}from"./QUEUES_FILENAME-Civ-7SiI.mjs";import{discoverSandboxUsage as wo}from"./discoverSandboxUsage--Z1vx7GM.mjs";import{resolveServiceBindings as Io}from"./readServiceBindings-BA49C6aN.mjs";import Co from"./discoverStorageRulesMetadata-CitX6ziW.mjs";import{resolveCodegenTarget as It,gatePlatformFeatures as To,readTargetDiagnostics as Oo,vectorizeDimensionDiagnostics as ko,liveStreamsDeliveryAuthorizationDiagnostic as Ro,socketRoutesDeliveryAuthorizationDiagnostic as Fo,studioPlatformFor as Lo,platformFeatureAvailable as Do}from"./DEFAULT_TARGET-3OLdJhTj.mjs";import{i as Mo}from"./schema-BgM8A3XV.mjs";import{b as Hn,e as _o}from"./shard-BCqz_05A.mjs";import{e as Ko,a as zo}from"./server-B6VhYK7m.mjs";import{emitDataModel as $o}from"./emitDataModel-CuFqq97x.mjs";import{i as Bo,a as Vo,e as Uo,b as Wo,d as qo,c as jo}from"./unwrap-handler-return-CGdJGvGh.mjs";import Ho from"./discoverFunctions-DkPOc8b9.mjs";import Go from"./discoverHttpRoutes-DCDgDIYv.mjs";import Yo from"./discoverInserts-BcoTjXqI.mjs";import{e as Gn}from"./exported-procedure-chains-D1WlRfqJ.mjs";import Qo from"./discoverMigrations-BWxx8Wv9.mjs";import Xo from"./discoverQueries-CxQRVuIV.mjs";import Jo from"./discoverRlsMetadata-D0B4nCmG.mjs";import Zo from"./discoverSchema-Cwt-DQgh.mjs";import{discoverShapes as ea}from"./SHAPES_FILENAME-DVJbfDZ8.mjs";import{i as ta}from"./reserved-words-CW1QFbTd.mjs";import{emitApp as sa}from"./emitApp-BL16wvE9.mjs";import{readJsonSync as na}from"@visulima/fs";import{buildSchemaSnapshot as ia}from"./SchemaSnapshotParseError-H9eQX4ui.mjs";import{buildOpenApiDocument as ra,emitOpenApiModule as oa}from"./buildOpenApiDocument-DWdj2jvW.mjs";import{buildOpenRpcDocument as aa,emitOpenRpcModule as ca}from"./OPENRPC_VERSION-l4HD4osw.mjs";import{v as la,t as da,u as ua,s as fa,w as ga}from"./shard-runtime-ByYXjCKY.mjs";import{emitCollections as pa,emitSeed as ma,emitApi as ha,emitInternalApi as va}from"./emitApi-c14__tie.mjs";import{emitCrons as Ea,emitScheduler as xa,emitShardRegistry as Sa,emitDurableObjects as Aa,emitVectors as ya,emitWranglerCronTriggers as ba}from"./emitCrons-lc-hnJYn.mjs";import Na from"./emitDrizzleSchema-bct1OuH5.mjs";import{LAZY_FUNCTION_DIRECTORY as Yn,emitFunctions as Pa,emitLazyFunctionModules as wa}from"./emitFunctions-CkBPtGDF.mjs";const Ia=(e,t=!1)=>{if(e.length===0)return"";const s=fo(t),n=e.map(c=>{if(co(c.exportName,"live stream export name"),!lo.test(c.filePath))throw new Error(`@lunora/codegen: live stream file path is not safe to import: ${JSON.stringify(c.filePath)}`);return`import type { ${c.exportName} as ${c.exportName}Stream } from "../${c.filePath}.js";`}),i=e.map(c=>{const l=c.topics.map(u=>{uo(u.name,"live topic name");const f=`(typeof ${c.exportName}Stream)["topics"]["${u.name}"]`,g=`LiveTopicRef<LiveTopicPayload<${f}>>`,m=JSON.stringify(c.id);if(u.fields.length===0)return` ${u.name}: (): ${g} => ({ __lunoraLive: ${m}, topic: ${JSON.stringify(u.name)} }),`;const v=u.fields.map($=>`\${encodeURIComponent(key.${$})}`).join(":");return` ${u.name}: (key: LiveTopicKey<${f}>): ${g} => ({
|
|
2
2
|
__lunoraLive: ${m},
|
|
3
3
|
topic: \`${u.name}:${v}\`,
|
|
4
4
|
}),`});return` ${c.exportName}: {
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const k=(e,t=2166136261)=>{let i=t;for(let r=0;r<e.length;r+=1)i^=e.charCodeAt(r),i=Math.imul(i,16777619);return(i>>>0).toString(16).padStart(8,"0")},q=e=>`${k(e,2166136261)}${k(e,16777619)}`,X=1;function A(e){const t={},i=Object.keys(e);i.sort();for(const r of i)t[r]=e[r];return t}const C=e=>`${JSON.stringify(e,void 0,2)}
|
|
2
|
+
`,Z=e=>q(C(e)),l=e=>typeof e=="object"&&e!==null,I=e=>l(e)&&l(e.fields)&&l(e.indexes)&&l(e.relations)&&typeof e.shardMode=="string",N=e=>{if(e===void 0||e.trim()==="")return{status:"absent"};let t;try{t=JSON.parse(e)}catch(r){return{error:`baseline is not valid JSON: ${r instanceof Error?r.message:String(r)}`,status:"invalid"}}if(!l(t)||t.version!==1||!l(t.tables))return{error:`baseline is malformed or written by an incompatible version (expected version ${String(1)})`,status:"invalid"};for(const[r,o]of Object.entries(t.tables))if(!I(o))return{error:`baseline table "${r}" has an invalid structure`,status:"invalid"};return{snapshot:{jurisdiction:typeof t.jurisdiction=="string"?t.jurisdiction:void 0,migrationIds:Array.isArray(t.migrationIds)?t.migrationIds:[],tables:t.tables,version:1},status:"ok"}},R=(e,t)=>e.unique===t.unique&&e.fields.length===t.fields.length&&e.fields.every((i,r)=>i===t.fields[r]),S=e=>e.unique!==void 0,h=({nullable:e,optional:t,refined:i,unique:r,...o})=>JSON.stringify(A(o)),O=e=>({form:JSON.stringify([h(e),e.optional===!0,e.nullable===!0]),refined:e.refined===!0}),w=e=>e.kind==="union"&&e.members?e.members.map(t=>O(t)):[O({...e,nullable:!1,optional:!1})],V=(e,t)=>{if(t.kind!=="union")return!1;const i=w(t);return w(e).every(r=>i.some(o=>o.form===r.form&&(r.refined||!o.refined)))},c=e=>{switch(e.kind){case"array":return`array(${e.of?c(e.of):"?"})`;case"from":return e.output===void 0?"from":`from(${e.output})`;case"id":return`id(${e.ref??"?"})`;case"literal":return`literal(${e.literal??"?"})`;case"object":return`object({ ${Object.keys(e.fields??{}).join(", ")} })`;case"record":return`record(${e.key?c(e.key):"?"}, ${e.of?c(e.of):"?"})`;case"union":return(e.members??[]).map(t=>c(t)).join(" | ");default:return e.kind}},p=(e,t,i)=>({remediation:"backfill",scope:"table",severity:"breaking",summary:i,table:e,type:t}),g=(e,t,i)=>({remediation:"none",scope:"table",severity:"safe",summary:i,table:e,type:t}),M=(e,t)=>{const i=JSON.stringify(e),r=JSON.stringify(t);return i===r?0:i<r?-1:1},f=e=>({...e,...e.kind==="from"?{output:void 0}:{},...e.fields?{fields:Object.fromEntries(Object.entries(e.fields).map(([t,i])=>[t,f(i)]))}:{},...e.key?{key:f(e.key)}:{},...e.of?{of:f(e.of)}:{},...e.members?{members:e.members.map(t=>f(t)).toSorted(M)}:{}}),x=e=>e.kind==="union"?e.members??[]:[e],L=(e,t)=>{const i=[...e],r=[...t],o=new Set,n=new Set,s=(a,d)=>{for(const[b,$]of i.entries()){if(n.has(b))continue;const m=r.findIndex((_,E)=>!o.has(E)&&a($,_));m!==-1&&(o.add(m),n.add(b),d&&([i[b],r[m]]=v($,r[m])))}};return s((a,d)=>JSON.stringify(a)===JSON.stringify(d),!1),s((a,d)=>h(f(a))===h(f(d)),!0),[i,r]},v=(e,t)=>{if(e.kind==="union"||t.kind==="union"){const[o,n]=L(x(e),x(t)),s=(a,d)=>a.kind==="union"?{...a,members:d.toSorted(M)}:d[0];return[s(e,o),s(t,n)]}if(e.kind!==t.kind)return[e,t];if(e.kind==="from")return e.output===void 0||t.output===void 0?[{...e,output:void 0},{...t,output:void 0}]:[e,t];const i={...e.fields?{fields:{...e.fields}}:{}},r={...t.fields?{fields:{...t.fields}}:{}};for(const o of["key","of"])e[o]&&t[o]&&([i[o],r[o]]=v(e[o],t[o]));for(const o of Object.keys(e.fields??{})){const n=e.fields?.[o],s=t.fields?.[o];n&&s&&i.fields&&r.fields&&([i.fields[o],r.fields[o]]=v(n,s))}return[{...e,...i},{...t,...r}]},D=(e,t,i,r,o)=>{const[n,s]=v(i,r);if(!(n.kind===s.kind&&(!o||h(n)===h(s))))return o&&V(n,s)?g(e,"widenedFieldShape",`field ${e}.${t} widened: ${c(n)} → ${c(s)} — every stored value stays valid`):n.kind!==s.kind?p(e,"changedFieldKind",`field ${e}.${t} changed type: ${n.kind} → ${s.kind} — add a data migration to convert existing values`):p(e,"changedFieldShape",`field ${e}.${t} changed shape: ${c(n)} → ${c(s)} — stored values were written against the old shape; add a data migration to convert them`)},H=(e,t,i,r)=>{const o=[];return i.unique!==r.unique&&o.push(r.unique===!0?p(e,"addedFieldConstraint",`field ${e}.${t} became unique — existing duplicates would violate it; add a data migration to de-duplicate first`):g(e,"relaxedFieldConstraint",`field ${e}.${t} is no longer unique`)),i.nullable!==r.nullable&&o.push(r.nullable===!0?g(e,"relaxedFieldConstraint",`field ${e}.${t} became nullable`):p(e,"addedFieldConstraint",`field ${e}.${t} is no longer nullable — rows holding NULL would be invalid; add a data migration to backfill them`)),i.refined!==r.refined&&o.push(r.refined===!0?p(e,"addedFieldConstraint",`field ${e}.${t} gained a validation refinement — stored values were never checked against it; add a data migration if any could fail`):g(e,"relaxedFieldConstraint",`field ${e}.${t} dropped its validation refinement`)),o},J=(e,t,i,r)=>{const o=[],n=S(i)&&S(r),s=D(e,t,i,r,n);return s&&o.push(s),n&&o.push(...H(e,t,i,r)),i.optional&&!r.optional?o.push({remediation:"backfill",severity:"breaking",summary:`field ${e}.${t} became required — rows missing it would be invalid; add a data migration to backfill it`,table:e,scope:"table",type:"fieldOptionalToRequired"}):!i.optional&&r.optional&&o.push({remediation:"none",scope:"table",severity:"safe",summary:`field ${e}.${t} became optional`,table:e,type:"fieldRequiredToOptional"}),o},P=(e,t,i)=>i.optional?{remediation:"none",scope:"table",severity:"safe",summary:`added optional field ${e}.${t}`,table:e,type:"addedOptionalField"}:{remediation:"backfill",severity:"breaking",summary:`added required field ${e}.${t} — existing rows have no value; add a data migration to backfill it`,table:e,scope:"table",type:"addedRequiredField"},B=(e,t,i,r)=>{for(const[o,n]of Object.entries(i.fields)){const s=t.fields[o];s===void 0?r.push(P(e,o,n)):r.push(...J(e,o,s,n))}for(const o of Object.keys(t.fields))i.fields[o]===void 0&&r.push({remediation:"backfill",severity:"breaking",summary:`removed field ${e}.${o} — add a data migration if stored data must be cleaned up`,table:e,scope:"table",type:"removedField"})},G=(e,t,i,r)=>{for(const[o,n]of Object.entries(i.indexes)){const s=t.indexes[o];if(s===void 0){r.push(n.unique?{remediation:"backfill",scope:"table",severity:"breaking",summary:`added unique index ${o} on ${e} — existing duplicates would violate it; add a data migration to de-duplicate first`,table:e,type:"addedIndex"}:{remediation:"none",scope:"table",severity:"safe",summary:`added index ${o} on ${e}`,table:e,type:"addedIndex"});continue}R(s,n)||r.push({remediation:"code",severity:"breaking",summary:`index ${o} on ${e} changed shape — a query may have relied on the old index`,table:e,scope:"table",type:"changedIndex"})}for(const o of Object.keys(t.indexes))i.indexes[o]===void 0&&r.push({remediation:"code",severity:"breaking",summary:`removed index ${o} on ${e} — a query that used \`.withIndex("${o}")\` would break`,table:e,scope:"table",type:"removedIndex"})},U=(e,t,i,r)=>{for(const o of Object.keys(i.relations))t.relations[o]===void 0&&r.push({remediation:"none",scope:"schema",severity:"safe",summary:`added relation ${e}.${o}`,table:e,type:"addedRelation"});for(const o of Object.keys(t.relations))i.relations[o]===void 0&&r.push({remediation:"code",scope:"schema",severity:"breaking",summary:`removed relation ${e}.${o}`,table:e,type:"removedRelation"})},F="shardBy:_unknown_",y="global",W=(e,t)=>e===y&&t.startsWith(`${y}:`)||t===y&&e.startsWith(`${y}:`),K=(e,t,i)=>{if(t===i)return i!==F?void 0:{remediation:"rehome",scope:"table",severity:"breaking",summary:`table ${e} declares a non-literal .shardBy(...) key, so codegen cannot read which column partitions it — every such key records as "${F}" and two DIFFERENT keys would compare equal. Pass the shard key as a string literal; until then this is reported on every run, because the alternative is a silent pass on a re-home that strands every row (export/import is the only way back).`,table:e,type:"changedShardMode"};if(!W(t,i))return{remediation:"rehome",severity:"breaking",summary:`table ${e} changed shard mode: ${t} → ${i} — its physical storage moves, and existing rows do NOT follow the schema; re-home them with an export/import round trip (https://lunora.sh/docs/concepts/sharding#migrating-a-populated-table)`,table:e,scope:"table",type:"changedShardMode"}},T=e=>e.memory!==void 0,j=e=>e.after??0,u=e=>e.after===void 0?`.ttl("${e.field}")`:`.ttl("${e.field}", { after: ${String(e.after)} })`,z=(e,t,i)=>{if(t===void 0&&i===void 0)return;const r=a=>({remediation:"backfill",scope:"table",severity:"breaking",summary:a,table:e,type:"changedTtlPolicy"}),o=a=>({remediation:"none",scope:"table",severity:"safe",summary:a,table:e,type:"changedTtlPolicy"});if(i===void 0)return o(`table ${e} dropped its TTL policy — its rows are no longer swept`);if(t===void 0)return r(`table ${e} gained a TTL policy ${u(i)} — every row already past the cutoff is deleted on the next alarm sweep; add a data migration to refresh or clear "${i.field}" on the rows written before it`);if(t.field!==i.field)return r(`table ${e} moved its TTL to a different column: ${u(t)} → ${u(i)} — rows are now expired by a column they were never written against; add a data migration to populate "${i.field}"`);const n=j(t),s=j(i);return s<n?r(`table ${e} shortened its TTL: ${u(t)} → ${u(i)} — rows that were not expired under the old offset are deleted on the next alarm sweep; add a data migration to refresh "${i.field}" on the rows that must survive`):s>n?o(`table ${e} lengthened its TTL: ${u(t)} → ${u(i)}`):void 0},Q=(e,t,i)=>{const r=[];return t.memory!==i.memory&&r.push(i.memory===!0?{remediation:"rehome",scope:"table",severity:"breaking",summary:`table ${e} became a .memory() table — every row is deleted in every shard on the next Durable Object cold start, and no data migration survives that; export the rows first if they must be kept, or revert`,table:e,type:"changedMemoryMode"}:{remediation:"none",scope:"table",severity:"safe",summary:`table ${e} is no longer a .memory() table — its rows now survive a cold start`,table:e,type:"changedMemoryMode"}),t.commitOrdered!==i.commitOrdered&&r.push(i.commitOrdered===!0?{remediation:"backfill",scope:"table",severity:"breaking",summary:`table ${e} became .commitOrdered() — rows written before it carry no _commitSeq, so a \`_commitSeq > cursor\` changefeed never offers them; add a data migration over the table to stamp them (the rewrite allocates a sequence)`,table:e,type:"changedCommitOrdering"}:{remediation:"code",scope:"table",severity:"breaking",summary:`table ${e} is no longer .commitOrdered() — new rows carry no _commitSeq, so a \`_commitSeq > cursor\` changefeed stops advancing without erroring; update the consumers before deploying`,table:e,type:"changedCommitOrdering"}),r},Y=(e,t,i,r)=>{const o=K(e,t.shardMode,i.shardMode);if(o&&r.push(o),T(t)&&T(i)){r.push(...Q(e,t,i));const n=z(e,t.ttl,i.ttl);n&&r.push(n)}B(e,t,i,r),G(e,t,i,r),U(e,t,i,r)},ee=(e,t)=>{const i=[],r=e?.tables??{};for(const[o,n]of Object.entries(t.tables)){const s=r[o];if(s===void 0){i.push({remediation:"none",scope:"table",severity:"safe",summary:`added table ${o}`,table:o,type:"addedTable"});continue}Y(o,s,n,i)}for(const o of Object.keys(r))t.tables[o]===void 0&&i.push({remediation:"rehome",scope:"table",severity:"breaking",summary:`removed table ${o} — its rows stay in each shard's SQLite, unreachable through the schema; export the shard first if the data must be kept`,table:o,type:"removedTable"});if(e!==void 0&&e.jurisdiction!==t.jurisdiction){const o=e.jurisdiction??"(none)",n=t.jurisdiction??"(none)";i.push({remediation:"rehome",scope:"schema",severity:"breaking",summary:`Durable Object jurisdiction changed from ${o} to ${n} — this re-homes every DO and strands all existing shard, scheduler, and session-DO data in the old region (no in-place migration; export then import to move it). Revert the change, or override the gate to proceed intentionally.`,type:"changedJurisdiction"})}return{changes:i}};export{X as SCHEMA_SNAPSHOT_VERSION,c as describeShape,J as diffExistingField,ee as diffSchemaSnapshots,Z as hashSchemaSnapshot,I as isValidTableSnapshot,N as parseSnapshotJson,C as serializeSchemaSnapshot,A as sortKeys};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import{LunoraError as A}from"@lunora/errors";import{SCHEMA_SNAPSHOT_VERSION as E,sortKeys as f,diffSchemaSnapshots as I,parseSnapshotJson as L}from"./SCHEMA_SNAPSHOT_VERSION-C7Um0EnM.mjs";import{isHyperdriveGlobalTable as O}from"./isD1GlobalTable-udvHAAzD.mjs";const _=e=>{const t=e.shardMode;return t==="global"?`global:${O(e)?"hyperdrive":"d1"}`:t==="root"?t:`shardBy:${t.field}`},v=(e,t)=>{const s=JSON.stringify(e),i=JSON.stringify(t);return s===i?0:s<i?-1:1},l=e=>{const t=e.kind==="optional",s=t?e.inner:void 0,i=s??e,r={kind:t?s?.kind??"unknown":e.kind,nullable:i.column?.notNull===!1||e.column?.notNull===!1,optional:t,unique:i.column?.unique===!0||e.column?.unique===!0,...D[i.kind]?.(i)};return(i.hasRefinement===!0||e.hasRefinement===!0)&&(r.refined=!0),r},N=e=>{const t={};for(const[s,i]of Object.entries(e))t[s]=l(i);return f(t)},j=/import\(\s*["'`](?:[A-Za-z]:)?[\\/]/u,D={array:e=>e.inner?{of:l(e.inner)}:{},from:e=>e.tsType===void 0||j.test(e.tsType)?{}:{output:e.tsType},id:e=>e.tableName===void 0?{}:{ref:e.tableName},literal:e=>e.literalValue===void 0?{}:{literal:e.literalValue},object:e=>e.shape?{fields:N(e.shape)}:{},record:e=>({...e.keyType?{key:l(e.keyType)}:{},...e.valueType?{of:l(e.valueType)}:{}}),union:e=>e.members?{members:e.members.map(t=>l(t)).toSorted(v)}:{}},M=e=>{const t={};for(const[n,a]of Object.entries(e.shape))t[n]=l(a);const s={};for(const n of e.indexes)s[n.name]={fields:[...n.fields],unique:n.unique??!1};const i={};for(const n of e.relations)i[n.name]=n.through===void 0?{field:n.field,kind:n.kind,table:n.table}:{kind:n.kind,table:n.table,through:{...n.through}};const r={commitOrdered:e.commitOrdered===!0,fields:f(t),indexes:f(s),memory:e.memory===!0,relations:f(i),shardMode:_(e)};return e.ttl&&(r.ttl=e.ttl.after===void 0?{field:e.ttl.field}:{after:e.ttl.after,field:e.ttl.field}),r},z=(e,t)=>{const s={};for(const r of e.tables)s[r.name]=M(r);const i=[...t].sort();return{jurisdiction:e.jurisdiction,migrationIds:i,tables:f(s),version:E}};class R extends A{constructor(t){super("SCHEMA_SNAPSHOT_PARSE",t,{name:"SchemaSnapshotParseError"})}}const J=e=>{const t=L(e);if(t.status==="invalid")throw new R(t.error);return t.status==="ok"?t.snapshot:void 0},B={build:{allowDrift:!0,updateBaseline:!1},deploy:{allowDrift:!0,updateBaseline:!0},prepare:{allowDrift:!0,updateBaseline:!0},verify:{allowDrift:!0,updateBaseline:!1}},S=" • For backward-compatible changes (e.g. adding an optional field): pass `--allow-schema-drift` to skip the block.",k=" • To accept the new shape without a migration (you know data is compatible): pass `--update-schema-baseline`.",P=e=>{const t=e===void 0?void 0:B[e];if(e===void 0||t===void 0)return`${S}
|
|
2
|
+
${k}
|
|
3
|
+
`;const s=t.updateBaseline?k:` • To accept the new shape without a migration, run \`lunora prepare --update-schema-baseline\` — \`lunora ${e}\` does not take that flag.`;return`${S}
|
|
4
|
+
${s}
|
|
5
|
+
`},p=e=>e.map(t=>` - ${t.summary}`).join(`
|
|
6
|
+
`),T=e=>e.remediation==="backfill"&&e.table!==void 0,x=/^[A-Za-z_]\w*$/u,F=e=>` lunora migrate create backfill_${e} --table ${e}`,C=(e,t,s)=>{const i=[...new Set(e.filter(n=>T(n)).map(n=>n.table))],r=[];if(i.length>0){r.push(" • Add a `defineMigration({ id, table, up })` in lunora/ for each affected table, then re-run this command — the baseline is re-blessed on a successful deploy, not by `lunora migrate` itself.\n");const n=i.filter(a=>x.test(a));n.length>0&&r.push(`
|
|
7
|
+
Scaffold the missing migration(s) — the generated \`up\` is an identity placeholder you must fill in:
|
|
8
|
+
${n.map(a=>F(a)).join(`
|
|
9
|
+
`)}
|
|
10
|
+
|
|
11
|
+
`)}return t.length>0&&r.push(` • Migration(s) ${t.join(", ")} declare a non-literal \`table\`, so codegen cannot tell which table they visit and they cover nothing. Use a string literal.
|
|
12
|
+
`),r.push(P(s)),[`${s??"deploy"} blocked: ${String(e.length)} unresolved breaking schema change(s) since the last blessed schema baseline:`,p(e),"",`To fix:
|
|
13
|
+
${r.join("")}Docs: https://lunora.dev/docs/migrations`].join(`
|
|
14
|
+
`)},V=e=>{const{allowDrift:t=!1,baseline:s,command:i,current:r,migrations:n}=e,a=I(s,r),u=a.changes.filter(o=>o.severity==="breaking"),b=r.migrationIds.filter(o=>!(s?.migrationIds??[]).includes(o)),m=n.filter(o=>b.includes(o.id)),c=(o,h)=>({blocked:o,changes:a.changes,newMigrationIds:b,reason:h}),w=new Set(m.filter(o=>o.table!=="").map(o=>o.table)),$=m.filter(o=>o.table==="").map(o=>o.id);if(a.changes.length===0||s===void 0)return c(!1,"");if(u.length===0)return c(!1,`schema drift detected (all additive/safe):
|
|
15
|
+
${p(a.changes)}`);const g=u.filter(o=>!T(o)||!w.has(o.table));if(g.length===0){const o=new Set(u.map(d=>d.table)),h=m.filter(d=>o.has(d.table)).map(d=>d.id);return c(!1,`breaking schema drift detected, covered by ${String(h.length)} new migration(s) (${h.join(", ")}):
|
|
16
|
+
${p(u)}`)}const y=C(g,$,i);return t?c(!1,`${y}
|
|
17
|
+
|
|
18
|
+
(overridden by --allow-schema-drift)`):c(!0,y)};export{R as SchemaSnapshotParseError,z as buildSchemaSnapshot,V as evaluateSchemaDrift,J as parseSchemaSnapshot};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./json-data-Chfs2Cz5.mjs";import{o as i,j as r,s as n,h as o,t as g,k as u,d as F,w as p,m as l,g as d,f,i as k,u as w,l as A,v as Q}from"./shard-runtime-
|
|
1
|
+
import"./json-data-Chfs2Cz5.mjs";import{o as i,j as r,s as n,h as o,t as g,k as u,d as F,w as p,m as l,g as d,f,i as k,u as w,l as A,v as Q}from"./shard-runtime-ByYXjCKY.mjs";import"./shared-8vTRkL2-.mjs";import"./platform-8oj7iXQy.mjs";export{i as buildDoTypeImports,r as emitAgentFragments,n as emitAgents,o as emitContainerFragments,g as emitContainers,u as emitPaymentFragments,F as emitQueueFragments,p as emitQueues,l as emitQueuesMetadataFragments,d as emitServiceFragments,f as emitTopicFragments,k as emitWorkflowFragments,w as emitWorkflows,A as emitWorkflowsMetadataFragments,Q as queueAliasFindings};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./SCHEMA_SNAPSHOT_VERSION-
|
|
1
|
+
import"./SCHEMA_SNAPSHOT_VERSION-C7Um0EnM.mjs";import"./isD1GlobalTable-udvHAAzD.mjs";import"./json-data-Chfs2Cz5.mjs";import{e as d}from"./shard-BCqz_05A.mjs";import"./shard-runtime-ByYXjCKY.mjs";import"./shared-8vTRkL2-.mjs";import"./platform-8oj7iXQy.mjs";import"./schema-BgM8A3XV.mjs";export{d as default};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{LunoraError as he}from"@lunora/errors";import{serializeSchemaSnapshot as Jt,hashSchemaSnapshot as
|
|
1
|
+
import{LunoraError as he}from"@lunora/errors";import{serializeSchemaSnapshot as Jt,hashSchemaSnapshot as Yt}from"./SCHEMA_SNAPSHOT_VERSION-C7Um0EnM.mjs";import{isHyperdriveGlobalTable as zt,isD1GlobalTable as Xt}from"./isD1GlobalTable-udvHAAzD.mjs";import{r as Zt}from"./json-data-Chfs2Cz5.mjs";import{r as $,e as er,a as tr,b as rr,c as nr,d as ar,f as sr,g as or,h as ir,i as dr,j as cr,k as lr,l as ur,m as hr,n as pr,o as mr,p as gr,q as fr}from"./shard-runtime-ByYXjCKY.mjs";import{u as re,h as br,s as wr,a as yr,I as vr,c as kr,G as Sr,d as Rr}from"./shared-8vTRkL2-.mjs";import{p as xr}from"./platform-8oj7iXQy.mjs";import{i as Ar}from"./schema-BgM8A3XV.mjs";const u=(n,t)=>`((): (() => ${t}) => { let cached: ${t} | undefined; return () => (cached ??= JSON.parse(${JSON.stringify(JSON.stringify(n))}) as ${t}); })()`,pe=["categories","description","facing","level","remediation","title"],Or=n=>{const t={};return{advisoryRows:n.map(a=>{let r=t[a.name];return r||(r=Object.fromEntries(pe.filter(o=>o in a).map(o=>[o,a[o]])),t[a.name]=r),Object.fromEntries(Object.entries(a).filter(([o,d])=>!pe.includes(o)||JSON.stringify(d)!==JSON.stringify(r[o])))}),advisoryRules:t}},Dr=` /**
|
|
2
2
|
* The bare writer every admin/maintenance entry point writes through.
|
|
3
3
|
*
|
|
4
4
|
* Admin and maintenance writes go through the SAME reactive-cache hooks as a
|
|
@@ -49,19 +49,25 @@ import{LunoraError as he}from"@lunora/errors";import{serializeSchemaSnapshot as
|
|
|
49
49
|
|
|
50
50
|
${w()}
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
52
|
+
try {
|
|
53
|
+
return await runDataMigration({
|
|
54
|
+
...(args.batchSize === undefined ? {} : { batchSize: args.batchSize }),
|
|
55
|
+
...(args.direction === undefined ? {} : { direction: args.direction }),
|
|
56
|
+
...(args.dryRun === undefined ? {} : { dryRun: args.dryRun }),
|
|
57
|
+
...(args.maxBatches === undefined ? {} : { maxBatches: args.maxBatches }),
|
|
58
|
+
migration: migration as unknown as DataMigrationLike,
|
|
59
|
+
// Flush after each batch so live migrationStatus subscribers see
|
|
60
|
+
// progress mid-run (the base method records the reserved state
|
|
61
|
+
// table the raw-SQL progress write is invisible to the tracker).
|
|
62
|
+
onBatch: () => this.flushMigrationProgress(),
|
|
63
|
+
sql: this.sql as SqlExec,
|
|
64
|
+
writer,
|
|
65
|
+
});
|
|
66
|
+
} finally {
|
|
67
|
+
// The de-dup that unblocks a deferred UNIQUE index runs through here;
|
|
68
|
+
// let the next call rebuild it now instead of after the retry interval.
|
|
69
|
+
this.migrationRetryAt = 0;
|
|
70
|
+
}
|
|
65
71
|
}
|
|
66
72
|
|
|
67
73
|
protected override async runShardWrite(args: RunShardWriteArgs, headroom?: TransactionHeadroomTracker): Promise<RunShardWriteResult> {
|
|
@@ -225,9 +231,9 @@ ${w()}
|
|
|
225
231
|
await applyCdcChanges(writer, args.changes);
|
|
226
232
|
|
|
227
233
|
return { applied: args.changes.length };
|
|
228
|
-
}`,_r=({actionOnlyBuild:n,actionOnlyFields:t,agentsBuild:e,agentsContextField:a,containersBuild:r,containersContextField:o,databaseOptions:d,everyContextBuild:m,everyContextField:g,facadeBlock:h,globalDatabaseLine:x,hasSensitiveArgs:S=!1,lazyFunctions:f=!1,notifyBuild:c,ormContextField:y,paymentsBuild:M,paymentsContextField:A,queuesBuild:q,queuesContextField:F,topicsBuild:R,topicsContextField:U,vectorsBuild:i,vectorsContextField:v,workflowsBuild:
|
|
234
|
+
}`,_r=({actionOnlyBuild:n,actionOnlyFields:t,agentsBuild:e,agentsContextField:a,containersBuild:r,containersContextField:o,databaseOptions:d,everyContextBuild:m,everyContextField:g,facadeBlock:h,globalDatabaseLine:x,hasSensitiveArgs:S=!1,lazyFunctions:f=!1,notifyBuild:c,ormContextField:y,paymentsBuild:M,paymentsContextField:A,queuesBuild:q,queuesContextField:F,topicsBuild:R,topicsContextField:U,vectorsBuild:i,vectorsContextField:v,workflowsBuild:E,workflowsContextField:B})=>{const I=t.length>0,C=y===""?"{ db }":"{ db, orm: bindOrm(facade) }",j=y===""?"":`
|
|
229
235
|
orm: databaseContext.orm,`,W=y===""?"":`
|
|
230
|
-
orm: { configurable: true, enumerable: true, value: mutationDatabase.orm, writable: true },`,O=
|
|
236
|
+
orm: { configurable: true, enumerable: true, value: mutationDatabase.orm, writable: true },`,O=I?`
|
|
231
237
|
// ActionCtx-only helpers (external, non-deterministic I/O): constructed
|
|
232
238
|
// and attached only for an \`action\` so query/mutation ctx never carry them.
|
|
233
239
|
if (isAction) {
|
|
@@ -261,7 +267,7 @@ ${n.replaceAll(/^(?=.)/gmu," ")}${t.map(p=>` ctx.${p} = ${p};`
|
|
|
261
267
|
};
|
|
262
268
|
})();
|
|
263
269
|
const { identity, ip, userId } = caller;
|
|
264
|
-
${i}${m}${r}${
|
|
270
|
+
${i}${m}${r}${E}${q}${R}${e}
|
|
265
271
|
// Which dispatch this ctx belongs to. Drives the two deferral facades
|
|
266
272
|
// below and the \`ctx.run*\` caller guard; a ctx built for an
|
|
267
273
|
// admin/lifecycle path has no registered function, and so no kind. An
|
|
@@ -376,7 +382,7 @@ ${x} // \`ctx.db\`, wrapped in automatic instrumentation: by default
|
|
|
376
382
|
// mutation must rebuild its DB and table/ORM views with its own queue.
|
|
377
383
|
const makeDatabaseContext = (scheduler: SchedulerLike) => {
|
|
378
384
|
const db: DatabaseWriterLike = this.instrumentDb(createShardCtxDb(${d}), logFunctionPath, traceAnchor, observability, options.sensitive);
|
|
379
|
-
${h} return ${
|
|
385
|
+
${h} return ${C};
|
|
380
386
|
};
|
|
381
387
|
const databaseContext = makeDatabaseContext(scheduler);
|
|
382
388
|
const db = databaseContext.db;
|
|
@@ -446,7 +452,7 @@ ${c}
|
|
|
446
452
|
trace,${v}${g}${A}${o}${B}${F}${U}${a}${S?`
|
|
447
453
|
[Symbol.for("lunora.admitSensitiveArgs")]: (args: Record<string, unknown>, names: ReadonlySet<string>): void => this.admitSensitiveValues(options.sensitive, args, names),`:""}
|
|
448
454
|
};
|
|
449
|
-
${
|
|
455
|
+
${I?` const isAction = contextKind === "action";
|
|
450
456
|
`:""}${O}
|
|
451
457
|
${f?` const captureScope = (): (() => void) => {
|
|
452
458
|
const requestScope = this.captureRequestScope();
|
|
@@ -621,7 +627,7 @@ const dispatchRun = async (
|
|
|
621
627
|
} finally {
|
|
622
628
|
runDepth -= 1;
|
|
623
629
|
}
|
|
624
|
-
};`,
|
|
630
|
+
};`,Er=n=>n?me.replace(" runTransactional?: (work: () => Promise<unknown>) => Promise<unknown>,",` runTransactional?: (work: () => Promise<unknown>) => Promise<unknown>,
|
|
625
631
|
captureScope?: () => () => void,`).replace(` try {
|
|
626
632
|
// A mutation composed from an action`,` try {
|
|
627
633
|
let loaded = getLoadedFunction(functionPath);
|
|
@@ -642,7 +648,7 @@ const dispatchRun = async (
|
|
|
642
648
|
|
|
643
649
|
const loadedFunction = loaded;
|
|
644
650
|
|
|
645
|
-
// A mutation composed from an action`).replaceAll("registered.handler","loadedFunction.handler"):me,
|
|
651
|
+
// A mutation composed from an action`).replaceAll("registered.handler","loadedFunction.handler"):me,Ir=` public override async handleRpc(functionPath: string, args: Record<string, unknown>, headroom?: TransactionHeadroomTracker, scope?: QueryReadScope, bookmarks?: DispatchBookmark, sensitive?: SensitiveScope): Promise<unknown> {
|
|
646
652
|
// A dispatch that did not come through the shard's \`/rpc\` (a scheduled call,
|
|
647
653
|
// a lifecycle hook, an admin run) has no scope of its own, so it opens one here
|
|
648
654
|
// and releases it when the handler settles.
|
|
@@ -666,7 +672,7 @@ __PREPARE_FUNCTION__ const registered = LUNORA_FUNCTIONS[functionPath
|
|
|
666
672
|
throw new LunoraError("FUNCTION_NOT_FOUND", \`function not registered: \${functionPath}\`);
|
|
667
673
|
}
|
|
668
674
|
|
|
669
|
-
this.
|
|
675
|
+
this.ensureServable();
|
|
670
676
|
|
|
671
677
|
// \`headroom\`, when the caller supplied one, is threaded straight
|
|
672
678
|
// through to \`buildCtx\` — bypassing its \`this.transactionHeadroom()\`
|
|
@@ -839,14 +845,14 @@ __COMMITTED_CATCH__ } finally {
|
|
|
839
845
|
// \`ctx.scheduler\` call that reached the buffer in the first place.
|
|
840
846
|
protected override scheduleOutboxScheduler(): SchedulerLike | undefined {
|
|
841
847
|
return config.scheduler?.((this.env ?? {}) as Record<string, unknown>) as SchedulerLike | undefined;
|
|
842
|
-
}`,
|
|
848
|
+
}`,Cr=` protected override async executeSubscription(functionPath: string, args: Record<string, unknown>, identity?: SubscriptionIdentity): Promise<{ ranges?: Map<string, KeyRange[]>; result: unknown; tables: Set<string> } | null> {
|
|
843
849
|
const registered = LUNORA_FUNCTIONS[functionPath];
|
|
844
850
|
|
|
845
851
|
if (!registered || registered.kind !== "query" || registered.visibility === "internal") {
|
|
846
852
|
return null;
|
|
847
853
|
}
|
|
848
854
|
|
|
849
|
-
__PREPARE_FUNCTION__ this.
|
|
855
|
+
__PREPARE_FUNCTION__ this.ensureServable();
|
|
850
856
|
|
|
851
857
|
const footprint = createReadFootprint();
|
|
852
858
|
// Identity is threaded EXPLICITLY from the (deferred/interleaved)
|
|
@@ -869,7 +875,7 @@ __PREPARE_FUNCTION__ this.ensureMigrated();
|
|
|
869
875
|
return null;
|
|
870
876
|
}
|
|
871
877
|
|
|
872
|
-
this.
|
|
878
|
+
this.ensureServable();
|
|
873
879
|
|
|
874
880
|
return {
|
|
875
881
|
...(registered.durable ? { durable: registered.durable as { ttlMs?: number } } : {}),
|
|
@@ -880,7 +886,7 @@ __PREPARE_FUNCTION__ this.ensureMigrated();
|
|
|
880
886
|
// \`ctx.auth\` stream as nobody — or as a concurrent RPC's caller.
|
|
881
887
|
iterator: (signal) => (registered.handler as (context: unknown, args: Record<string, unknown>, signal: AbortSignal) => AsyncIterable<unknown>)(this.buildCtx({ functionPath, identity }), args, signal),
|
|
882
888
|
};
|
|
883
|
-
}`,
|
|
889
|
+
}`,Lr=` } catch (error) {
|
|
884
890
|
// The write committed before this failed. Mark the error so the caller can tell
|
|
885
891
|
// a durable write from a rollback: the rethrow still reaches the caller unchanged.
|
|
886
892
|
if (typeof error === "object" && error !== null) {
|
|
@@ -905,7 +911,7 @@ __PREPARE_FUNCTION__ this.ensureMigrated();
|
|
|
905
911
|
}
|
|
906
912
|
}
|
|
907
913
|
|
|
908
|
-
`:"";return
|
|
914
|
+
`:"";return Ir.replace("__COMMITTED_CATCH__",n?Lr:"").replace("__PREPARE_FUNCTION__",`${e}${a}`)},Nr=n=>{const t={};for(const e of n.tables){const a={};for(const[r,o]of Object.entries(e.shape)){const d=re(o);d.kind==="id"&&d.tableName!==void 0&&(a[r]=d.tableName)}Object.keys(a).length>0&&(t[e.name]=a)}return t},$r=n=>{const t={};for(const e of n.tables){const a=[];for(const[r,o]of Object.entries(e.shape))re(o).kind==="storage"&&a.push(r);a.length>0&&(t[e.name]=a)}return t},Mr=n=>{const t={};for(const e of n.tables){const a=[...e.indexes.map(r=>({fields:[...r.fields],name:r.name,type:"index",...r.unique===!0?{unique:!0}:{}})),...e.searchIndexes.map(r=>({fields:[r.field,...r.filterFields??[]],name:r.name,type:"search"})),...(e.geoIndexes??[]).map(r=>({fields:[r.field],name:r.name,type:"geo"})),...e.rankIndexes.map(r=>({fields:r.sortBy.map(o=>o.field),name:r.name,type:"rank"})),...e.vectorIndexes.map(r=>({fields:r.field===void 0?[]:[r.field],name:r.name,type:"vector"}))];a.length>0&&(t[e.name]=a)}return t},qr=n=>{const t=[];for(const e of n.tables)!e.ttl||e.shardMode==="global"||t.push({...e.ttl.after===void 0?{}:{after:e.ttl.after},field:e.ttl.field,...e.softDelete?{softDeleteField:e.softDelete.field}:{},table:e.name});return t},Fr=n=>{if(n.kind!=="union"||n.members===void 0||n.members.length===0)return;const t=[];for(const e of n.members){if(e.kind!=="literal"||e.literalValue===void 0)return;try{const a=JSON.parse(e.literalValue);if(typeof a!="string")return;t.push(a)}catch{return}}return t},Ur=(n,t,e)=>{const a=re(t),r={name:n,optional:br(t),type:a.kind};if(a.kind==="id"&&a.tableName!==void 0){r.ref=a.tableName;const d=e.get(n);d!==void 0&&(r.onDelete=d)}a.kind==="storage"&&(r.isStorage=!0,a.bucket!==void 0&&(r.bucket=a.bucket));const o=Fr(a);return o!==void 0&&(r.enumValues=o),a.column?.notNull===!1&&(r.nullable=!0),r},Br=n=>{const t={};for(const e of n.tables){const a=[{name:"_id",optional:!1,pk:!0,type:"id"},{name:"_creationTime",optional:!1,type:"number"},...e.commitOrdered===!0?[{name:"_commitSeq",optional:!1,type:"number"}]:[]],r=new Map(e.relations.flatMap(o=>o.kind==="one"?[[o.field,o.onDelete]]:[]));for(const[o,d]of Object.entries(e.shape))a.push(Ur(o,d,r));t[e.name]=a}return t},jr=({hasMutators:n,hasSensitiveShapes:t,hasShapes:e,rlsData:a})=>{const r="{ columns?: readonly string[]; effectiveWhere?: WhereInput; global?: boolean; table: string } | undefined",o=t?` protected override resolveShape(name: string, args: Record<string, unknown>, identity?: SubscriptionIdentity): ${r} {
|
|
909
915
|
const sensitive = this.openSensitiveScope(\`__shape__:\${name}\`, args);
|
|
910
916
|
|
|
911
917
|
try {
|
|
@@ -925,7 +931,7 @@ ${o}
|
|
|
925
931
|
return undefined;
|
|
926
932
|
}
|
|
927
933
|
|
|
928
|
-
this.
|
|
934
|
+
this.ensureServable();
|
|
929
935
|
|
|
930
936
|
// Trusted ctx from the socket's OWN verified identity — the client
|
|
931
937
|
// supplies only the shape name + args; \`compileWhere\` validates the
|
|
@@ -1250,10 +1256,10 @@ ${o} const vectors = createContextVectors(lunora${g});
|
|
|
1250
1256
|
ordered: async (read, work) => this.runOrderedAfterWrites(read, work),
|
|
1251
1257
|
});
|
|
1252
1258
|
}
|
|
1253
|
-
`:"",vectorsBuild:h,vectorsStub:r}},on=({advisories:n=[],advisorProcedures:t=[],agents:e=[],capabilities:a=new Set,containers:r=[],env:o,flagKeys:d=[],hasFlags:m=!1,hasNotify:g=!1,hasRooms:h=!1,hasSecretValues:x=!1,hasSensitiveArgs:S=!1,hasSockets:f=!1,lazyFunctions:c=!1,hasVectors:y=!0,liveStreamDeclarations:M=[],liveStreams:A=!1,maskMetadata:q,mutators:F=[],queues:R=[],rlsMetadata:U,schema:i,schemaSnapshot:v,shapes:
|
|
1259
|
+
`:"",vectorsBuild:h,vectorsStub:r}},on=({advisories:n=[],advisorProcedures:t=[],agents:e=[],capabilities:a=new Set,containers:r=[],env:o,flagKeys:d=[],hasFlags:m=!1,hasNotify:g=!1,hasRooms:h=!1,hasSecretValues:x=!1,hasSensitiveArgs:S=!1,hasSockets:f=!1,lazyFunctions:c=!1,hasVectors:y=!0,liveStreamDeclarations:M=[],liveStreams:A=!1,maskMetadata:q,mutators:F=[],queues:R=[],rlsMetadata:U,schema:i,schemaSnapshot:v,shapes:E=[],storageRules:B,studioFeatures:I,services:C=[],topics:j=[],useUmbrella:W=!1,workflows:O=[]})=>{const l=Rr(W),H=F.length>0,p=E.length>0,D=E.some(s=>wr(s.args).length>0),V=S||D,ge=v===void 0?"":Jt(v),fe=v===void 0?"":`
|
|
1254
1260
|
/** Structural schema snapshot + its content hash, recorded in the shard's \`__lunora_schema_history\` ledger on cold start so the studio can show a schema-version timeline and diff any two versions. */
|
|
1255
|
-
const LUNORA_SCHEMA_SNAPSHOT: { hash: string; json: string } = { hash: ${JSON.stringify(
|
|
1256
|
-
`,be=v===void 0?"":", schemaSnapshot: LUNORA_SCHEMA_SNAPSHOT",k=er(a),
|
|
1261
|
+
const LUNORA_SCHEMA_SNAPSHOT: { hash: string; json: string } = { hash: ${JSON.stringify(Yt(v))}, json: ${JSON.stringify(ge)} };
|
|
1262
|
+
`,be=v===void 0?"":", schemaSnapshot: LUNORA_SCHEMA_SNAPSHOT",k=er(a),L=tr(m,l.flags),K=rr(d,m,l.flags),G=fr(g),Q=nr(o),{build:we,contextField:ye,importLines:ve,specs:ke}=ar(xr(R)),{build:Se,contextField:Re,importLines:xe,specs:Ae}=sr(j,R),J=or(C,l.server),{build:Oe,contextField:De,importLines:Te,specs:_e}=ir(r,i.jurisdiction),{build:Ee,contextField:Ie,importLines:Ce,specs:Le}=dr(O),{build:Pe,contextField:Ne,importLines:$e,specs:Me}=cr(e,x&&e.length>0),{build:qe,configField:Fe,contextField:Ue,imports:Be,stub:je}=lr(a.has("payments")),We=n,{advisoryRules:He,advisoryRows:Ve}=Or(We),Ke=t,ne=U??{policies:[],roles:[]},Ge=q??{columns:[]},Qe=B??{rules:[]},Je=I??{analytics:!1,auth:!1,containers:!1,flags:!1,kv:!1,mail:!1,notifications:!1,payments:!1,privacy:!1,queues:!1,scheduler:!1,storage:!1,vectors:!1,workflows:!1},{constant:Ye,override:ze}=ur(O),{constant:Xe,override:Ze}=hr(R),b=y&&i.vectorIndexes.length>0,Y=new Set(i.tables.filter(s=>Ar(s)).map(s=>s.name)),ae=b&&i.vectorIndexes.some(s=>Y.has(s.table)),T=i.tables.some(s=>s.shardMode==="global"),z=pr(Y),X=i.tables.some(s=>zt(s)),se=i.tables.some(s=>Xt(s)),P=i.tables.some(s=>s.externalSource!==void 0),oe=i.tables.some(s=>s.memory===!0),Z=i.tables.some(s=>s.shardMode!=="global"&&s.searchIndexes.length>0);if(se&&X)throw new he("INTERNAL",'lunora codegen: mixing `.global()` (D1) and `.global({ backend: "hyperdrive" })` tables in one app is not supported yet — use a single global backend.');const ee=i.tables.length>0,et=Nr(i),tt=Mr(i),rt=Br(i),nt=$r(i),ie=qr(i),te=mr(b,O.length>0,R.length>0,m,Z);p&&te.push("WhereInput"),D&&te.push("SensitiveScope");const de=gr(T),{customMutatorOverride:at,shapeGuardImport:st,shapeReadPolicyAssertion:ot,shapeReadPolicyImport:it,shapeResolveOverride:dt}=jr({hasMutators:H,hasSensitiveShapes:D,hasShapes:p,rlsData:ne}),_=A?M:[];for(const s of _)if(yr(s.exportName,"live stream export name"),!vr.test(s.filePath))throw new he("INTERNAL",`@lunora/codegen: refusing to emit import for unsafe live stream file path: ${JSON.stringify(s.filePath)}`);const ct=c?[]:_.map(s=>`import { ${s.exportName} as liveStream_${s.exportName} } from "../${s.filePath}.js";`),lt=` protected override liveStreams() {
|
|
1257
1263
|
return { ${_.map(s=>`${kr(s.id)}: liveStream_${s.exportName}`).join(", ")} };
|
|
1258
1264
|
}
|
|
1259
1265
|
`,ut=` private readonly liveStreamLoaders = new Map<string, () => Promise<{ validatePublish: (topic: string, payload: unknown) => unknown }>>([
|
|
@@ -1278,11 +1284,11 @@ ${_.map(s=>` [${JSON.stringify(s.id)}, () => import("../${s.filePath}
|
|
|
1278
1284
|
protected override liveStreams() {
|
|
1279
1285
|
return Object.fromEntries(this.loadedLiveStreams);
|
|
1280
1286
|
}
|
|
1281
|
-
`;let ce="";_.length>0&&(ce=c?ut:lt);const N=[`import type { ${te.join(", ")} } from "${l.do}";`,`import { applyCdcChanges, createStableIdFactory, ${Z?"backfillSearchIndexes, ":""}${b?"backfillVectorIndexes, ":""}buildReprojectionMigration, ${oe?"clearMemoryTables, ":""}${st}createReadFootprint, createShardCtxDb, exportShardRows, importShardRows, ${P?"isSourceDue, pullExternalSourceIncrementalTick, pullExternalSourceTick, ":""}markUnvouchableReads, ${ae?"ROOT_SHARD_NAME, ":""}runDataMigration, runShardMigrations, ${de.importFragment}ShardDO as ShardDOBase } from "${l.do}";`,...P?[`import type { ExternalSourceLike, SourceClientLike, TraceRefLike } from "${l.do}";`]:[],p?`import { asBucketStorage, ${it}beginDeferredDeletes, beginDeferredSchedules, composeShapeReadWhere, createSecrets, flushDeferredDeletes, LunoraError, withDeferredDeletes, withDeferredSchedules } from "${l.server}";`:`import { asBucketStorage, beginDeferredDeletes, beginDeferredSchedules, createSecrets, flushDeferredDeletes, LunoraError, withDeferredDeletes, withDeferredSchedules } from "${l.server}";`];ee&&N.push(`import { bindOrm, bindTableFacade } from "${l.server}";`),b&&N.push('import type { SchemaLike as VectorSchemaLike, VectorBackfillSync, VectorizeIndexLike, VectorSearchLike } from "@lunora/bindings/vectors";','import { createContextVectors, createVectorBackfillSync, createVectors, createVectorSyncHook, vectorBackfillTargets } from "@lunora/bindings/vectors";'),N.push(...k.importLines,...
|
|
1287
|
+
`;let ce="";_.length>0&&(ce=c?ut:lt);const N=[`import type { ${te.join(", ")} } from "${l.do}";`,`import { applyCdcChanges, createStableIdFactory, ${Z?"backfillSearchIndexes, ":""}${b?"backfillVectorIndexes, ":""}buildReprojectionMigration, ${oe?"clearMemoryTables, ":""}${st}createReadFootprint, createShardCtxDb, exportShardRows, importShardRows, ${P?"isSourceDue, pullExternalSourceIncrementalTick, pullExternalSourceTick, ":""}markUnvouchableReads, ${ae?"ROOT_SHARD_NAME, ":""}runDataMigration, runShardMigrations, ${de.importFragment}ShardDO as ShardDOBase } from "${l.do}";`,...P?[`import type { ExternalSourceLike, SourceClientLike, TraceRefLike } from "${l.do}";`]:[],p?`import { asBucketStorage, ${it}beginDeferredDeletes, beginDeferredSchedules, composeShapeReadWhere, createSecrets, flushDeferredDeletes, LunoraError, withDeferredDeletes, withDeferredSchedules } from "${l.server}";`:`import { asBucketStorage, beginDeferredDeletes, beginDeferredSchedules, createSecrets, flushDeferredDeletes, LunoraError, withDeferredDeletes, withDeferredSchedules } from "${l.server}";`];ee&&N.push(`import { bindOrm, bindTableFacade } from "${l.server}";`),b&&N.push('import type { SchemaLike as VectorSchemaLike, VectorBackfillSync, VectorizeIndexLike, VectorSearchLike } from "@lunora/bindings/vectors";','import { createContextVectors, createVectorBackfillSync, createVectors, createVectorSyncHook, vectorBackfillTargets } from "@lunora/bindings/vectors";'),N.push(...k.importLines,...L.importLines,...G.importLines,...Q.importLines,...Te,...Ce,...ve,...xe,...J.importLines,...$e,...Be,...V?[`import { sensitiveArgumentNames } from "${l.values}";`]:[],"",'import schema from "../schema.js";',...ct,`import { ${["LUNORA_FUNCTIONS","LUNORA_LIFECYCLE_HOOKS","LUNORA_MIGRATIONS",...c?["getLoadedFunction","loadFunction"]:[],...H?["LUNORA_MUTATOR_PATHS"]:[],...h?["LUNORA_ROOMS"]:[],...f?["LUNORA_SOCKETS"]:[],...p?["LUNORA_SHAPES"]:[]].join(", ")} } from "./functions.js";`);const ht=b?`
|
|
1282
1288
|
vectors?: (env: Record<string, unknown>) => Record<string, VectorizeIndexLike>;`:"",pt=se?`
|
|
1283
1289
|
d1?: (env: Record<string, unknown>, request?: { bookmark?: string; cdc?: boolean; cdcRetentionMs?: number; identity?: Record<string, unknown>; onBookmark?: (bookmark: string | undefined) => void; userId?: string }) => DatabaseWriterLike | undefined;`:"",mt=X?`
|
|
1284
1290
|
hyperdriveGlobal?: (env: Record<string, unknown>, request?: { cdc?: boolean; cdcRetentionMs?: number; identity?: Record<string, unknown>; userId?: string }) => DatabaseWriterLike | undefined;`:"",gt=P?`
|
|
1285
|
-
sourceClient?: (env: Record<string, unknown>, binding: string) => { query: <Row = Record<string, unknown>>(text: string, params?: readonly unknown[]) => Promise<Row[]> } | undefined;`:"",ft="ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().",bt="ctx.scheduler: no scheduler configured. Pass `scheduler` to createShardDO().",wt="ctx.storage: no storage configured. Pass `storage` to createShardDO().",yt=T?$("globalDbStub: DatabaseWriterLike",ft,["aggregate","count","delete","explain","findFirst","findFirstOrThrow","findMany","get","groupBy","insert","normalizeId","patch","query","rank","rankPage","replace"],{sync:["normalizeId","query"]}):"",{vectorSyncMethod:vt,vectorsBuild:kt,vectorsStub:St}=Vr(b,ae?i.vectorIndexes.filter(s=>
|
|
1291
|
+
sourceClient?: (env: Record<string, unknown>, binding: string) => { query: <Row = Record<string, unknown>>(text: string, params?: readonly unknown[]) => Promise<Row[]> } | undefined;`:"",ft="ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().",bt="ctx.scheduler: no scheduler configured. Pass `scheduler` to createShardDO().",wt="ctx.storage: no storage configured. Pass `storage` to createShardDO().",yt=T?$("globalDbStub: DatabaseWriterLike",ft,["aggregate","count","delete","explain","findFirst","findFirstOrThrow","findMany","get","groupBy","insert","normalizeId","patch","query","rank","rankPage","replace"],{sync:["normalizeId","query"]}):"",{vectorSyncMethod:vt,vectorsBuild:kt,vectorsStub:St}=Vr(b,ae?i.vectorIndexes.filter(s=>Y.has(s.table)).map(s=>s.name):[]),Rt=`{
|
|
1286
1292
|
...this.ctxDbTuning(),
|
|
1287
1293
|
auth: { identity: identity ?? null, userId: userId ?? null },
|
|
1288
1294
|
broadcast: (delta) => {
|
|
@@ -1354,13 +1360,52 @@ ${_.map(s=>` [${JSON.stringify(s.id)}, () => import("../${s.filePath}
|
|
|
1354
1360
|
`:"",_t=f?` protected override socketRoute(path: string): { auth: boolean; functionPath: string } | undefined {
|
|
1355
1361
|
return LUNORA_SOCKETS[path];
|
|
1356
1362
|
}
|
|
1357
|
-
`:"",{externalSourceOverride:
|
|
1363
|
+
`:"",{externalSourceOverride:Et,sourceBootstrap:It,sourceClientCacheConst:Ct}=Hr(P),Lt=`
|
|
1364
|
+
private shardInitDeferred = false;
|
|
1365
|
+
private deferredShardInit?: Promise<void>;
|
|
1366
|
+
|
|
1358
1367
|
protected override async runShardInit(): Promise<void> {
|
|
1359
1368
|
this.ensureMigrated();
|
|
1360
1369
|
${oe?` clearMemoryTables(this.sql as SqlExec, schema as unknown as SchemaLike);
|
|
1361
1370
|
`:""}
|
|
1371
|
+
if (this.blockedUniqueIndexes.length > 0) {
|
|
1372
|
+
this.shardInitDeferred = true;
|
|
1373
|
+
|
|
1374
|
+
return;
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1362
1377
|
await this.dispatchShardInit();
|
|
1363
1378
|
}
|
|
1379
|
+
|
|
1380
|
+
protected override async ensureShardInit(): Promise<void> {
|
|
1381
|
+
await super.ensureShardInit();
|
|
1382
|
+
|
|
1383
|
+
if (!this.shardInitDeferred) {
|
|
1384
|
+
return;
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
try {
|
|
1388
|
+
this.ensureMigrated();
|
|
1389
|
+
} catch (error: unknown) {
|
|
1390
|
+
this.recordShardInitError("__shard_init__", error);
|
|
1391
|
+
|
|
1392
|
+
return;
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
if (this.blockedUniqueIndexes.length > 0) {
|
|
1396
|
+
return;
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
this.deferredShardInit ??= (async (): Promise<void> => {
|
|
1400
|
+
try {
|
|
1401
|
+
await this.dispatchShardInit();
|
|
1402
|
+
} finally {
|
|
1403
|
+
this.shardInitDeferred = false;
|
|
1404
|
+
}
|
|
1405
|
+
})();
|
|
1406
|
+
|
|
1407
|
+
await this.deferredShardInit;
|
|
1408
|
+
}
|
|
1364
1409
|
`,Pt=ie.length>0?`
|
|
1365
1410
|
if (LUNORA_TTL_SWEEPS.length > 0) {
|
|
1366
1411
|
void this.scheduleTtlSweep();
|
|
@@ -1382,7 +1427,7 @@ ${oe?` clearMemoryTables(this.sql as SqlExec, schema as unknown as Sc
|
|
|
1382
1427
|
// exists — a trigger that fails first still flushes and fuses.
|
|
1383
1428
|
...(config.observability === undefined ? {} : { telemetrySink: () => config.observability?.((env ?? {}) as Record<string, unknown>) }),
|
|
1384
1429
|
});
|
|
1385
|
-
${
|
|
1430
|
+
${It}${Pt} }
|
|
1386
1431
|
|
|
1387
1432
|
protected override isCacheableQuery(functionPath: string): boolean {
|
|
1388
1433
|
// NOT \`kind === "query"\` alone. A cache hit answers without running
|
|
@@ -1437,22 +1482,22 @@ ${Et}${Pt} }
|
|
|
1437
1482
|
return new Set([...registered.sensitiveArgs, ...fromValidators]);
|
|
1438
1483
|
}
|
|
1439
1484
|
|
|
1440
|
-
`:"",qt=
|
|
1485
|
+
`:"",qt=Er(c),Ft=c?` const preparation = this.prepareFunction(functionPath, "subscription");
|
|
1441
1486
|
if (preparation !== undefined) await preparation;
|
|
1442
|
-
`:"",Ut=
|
|
1487
|
+
`:"",Ut=Cr.replace("__PREPARE_FUNCTION__",Ft),Bt=Pr(h,c),jt=ee?`
|
|
1443
1488
|
const facade = db as unknown as Record<string, ReturnType<typeof bindTableFacade>>;
|
|
1444
1489
|
${i.tables.map(s=>` facade[${JSON.stringify(s.name)}] = bindTableFacade(db, ${JSON.stringify(s.name)});`).join(`
|
|
1445
1490
|
`)}
|
|
1446
|
-
`:"",Wt=`${k.everyBuild}${
|
|
1491
|
+
`:"",Wt=`${k.everyBuild}${L.build}${Q.build}
|
|
1447
1492
|
const secrets = createSecrets(env);
|
|
1448
|
-
`,Ht=`${k.everyFields}${
|
|
1493
|
+
`,Ht=`${k.everyFields}${L.contextField}${G.contextField}${Q.contextField}
|
|
1449
1494
|
secrets,`,Vt=G.build,Kt=A?`
|
|
1450
1495
|
const live = {
|
|
1451
1496
|
publish: async (ref: { __lunoraLive: string; topic: string }, payload: unknown, publishOptions?: { shardKey?: string }): Promise<void> => {
|
|
1452
1497
|
await this.publishLiveFromAction(ref.topic, payload, { ...publishOptions, stream: ref.__lunoraLive });
|
|
1453
1498
|
},
|
|
1454
1499
|
};
|
|
1455
|
-
`:"",Gt=[...k.actionFields,...
|
|
1500
|
+
`:"",Gt=[...k.actionFields,...C.length>0?["services"]:[],...A?["live"]:[]],Qt=`${k.actionBuild}${J.build}${Kt}`;return`${Sr}${N.join(`
|
|
1456
1501
|
`)}
|
|
1457
1502
|
|
|
1458
1503
|
type FunctionKind = "action" | "mutation" | "query";
|
|
@@ -1515,7 +1560,10 @@ const LUNORA_STORAGE_RULES = ${u(Qe,"StorageRulesResult")};
|
|
|
1515
1560
|
|
|
1516
1561
|
/** Which optional package-backed features this app wires up (discovered from imports / \`ctx.*\` reads / schema signals) served via \`__lunora_admin__:studioFeatures\` so the studio hides nav pages whose package isn't enabled. */
|
|
1517
1562
|
const LUNORA_STUDIO_FEATURES = ${u(Je,"StudioFeaturesResult")};
|
|
1518
|
-
|
|
1563
|
+
|
|
1564
|
+
/** How long a shard with a UNIQUE index blocked by duplicate rows serves the cached diagnostic before re-attempting the build. */
|
|
1565
|
+
const BLOCKED_MIGRATION_RETRY_MS = 5000;
|
|
1566
|
+
${fe}${z.constant}${K.constant}${Ye}${Xe}${_e}${Le}${ke}${Ae}${J.specs}${Me}
|
|
1519
1567
|
export interface ShardDOConfig {
|
|
1520
1568
|
/** Opt into change-data-capture: records a post-image to \`__cdc_log\` on every write (backs streaming export + replay-PITR). */
|
|
1521
1569
|
cdc?: boolean;
|
|
@@ -1532,9 +1580,9 @@ export interface ShardDOConfig {
|
|
|
1532
1580
|
/** \`unknown\` because \`@lunora/scheduler\`'s \`Scheduler\` is not assignable to \`SchedulerLike\`; the shard casts it. */
|
|
1533
1581
|
scheduler?: (env: Record<string, unknown>) => unknown;
|
|
1534
1582
|
/** \`origin\` is the origin the current \`/rpc\` request reached the worker on — the fallback base for signed object URLs when no \`publicBaseUrl\` is configured. \`undefined\` off the synchronous dispatch path. */
|
|
1535
|
-
storage?: (env: Record<string, unknown>, origin?: string) => unknown;${ht}${k.configFields}${
|
|
1583
|
+
storage?: (env: Record<string, unknown>, origin?: string) => unknown;${ht}${k.configFields}${L.configField}${Fe}${pt}${mt}${gt}${z.configField}
|
|
1536
1584
|
}
|
|
1537
|
-
${$("schedulerStub",bt,["cancel","runAfter","runAt"])}${$("storageStub",wt,["createMultipartUpload","delete","download","generateUploadUrl","getMetadata","getPresignedUrl","getSignedUrl","getUrl","head","list","resumeMultipartUpload","store","upload"],{sync:["getUrl","resumeMultipartUpload"]})}${yt}${
|
|
1585
|
+
${$("schedulerStub",bt,["cancel","runAfter","runAt"])}${$("storageStub",wt,["createMultipartUpload","delete","download","generateUploadUrl","getMetadata","getPresignedUrl","getSignedUrl","getUrl","head","list","resumeMultipartUpload","store","upload"],{sync:["getUrl","resumeMultipartUpload"]})}${yt}${Ct}${St}${k.stubs}${je}
|
|
1538
1586
|
${qt}
|
|
1539
1587
|
|
|
1540
1588
|
/**
|
|
@@ -1543,14 +1591,16 @@ ${qt}
|
|
|
1543
1591
|
*/
|
|
1544
1592
|
export const createShardDO = (config: ShardDOConfig = {}): new (state: ShardDOState, env: unknown) => ShardDOBase =>
|
|
1545
1593
|
class extends ShardDOBase {${Nt}
|
|
1546
|
-
private
|
|
1594
|
+
private blockedUniqueIndexes: readonly string[] = [];
|
|
1595
|
+
private migrated = false;
|
|
1596
|
+
private migrationRetryAt = 0;${$t}${Mt}${Bt}
|
|
1547
1597
|
${de.override}
|
|
1548
1598
|
${Ut}
|
|
1549
|
-
${at}${dt}${Dt}${
|
|
1599
|
+
${at}${dt}${Dt}${Et}
|
|
1550
1600
|
protected override lifecycleHookPaths(event: "connect" | "disconnect" | "init" | "reactor" | "whisper"): readonly string[] {
|
|
1551
1601
|
return LUNORA_LIFECYCLE_HOOKS[event];
|
|
1552
1602
|
}
|
|
1553
|
-
${Tt}${_t}${ce}${
|
|
1603
|
+
${Tt}${_t}${ce}${z.override}${Lt}
|
|
1554
1604
|
// One \`onQueryChange\` dispatch. Mirrors \`executeSubscription\` — the
|
|
1555
1605
|
// socket-terminated half of the same reactivity — and differs only in who
|
|
1556
1606
|
// consumes the result: the base's \`dispatchReactors\` stores the digest as
|
|
@@ -1588,7 +1638,7 @@ ${c?` const requestScope = this.captureRequestScope();
|
|
|
1588
1638
|
return undefined;
|
|
1589
1639
|
}
|
|
1590
1640
|
|
|
1591
|
-
this.
|
|
1641
|
+
this.ensureServable();
|
|
1592
1642
|
|
|
1593
1643
|
const footprint = createReadFootprint();
|
|
1594
1644
|
const ctx = this.buildCtx({ functionPath, headroom: this.subscriptionHeadroom(), onRead: footprint.onRead, onReadRange: footprint.onReadRange, trusted: true });
|
|
@@ -1649,7 +1699,7 @@ ${c?` const requestScope = this.captureRequestScope();
|
|
|
1649
1699
|
protected override studioFeatures(): StudioFeaturesResult {
|
|
1650
1700
|
return LUNORA_STUDIO_FEATURES();
|
|
1651
1701
|
}
|
|
1652
|
-
${K.evaluateOverride}${K.subscriptionOverride}${
|
|
1702
|
+
${K.evaluateOverride}${K.subscriptionOverride}${ze}${Ze}
|
|
1653
1703
|
protected override advisories(): AdvisoryFinding[] {
|
|
1654
1704
|
return LUNORA_ADVISORIES();
|
|
1655
1705
|
}
|
|
@@ -1660,13 +1710,40 @@ ${K.evaluateOverride}${K.subscriptionOverride}${Ye}${Ze}
|
|
|
1660
1710
|
|
|
1661
1711
|
${Tr}
|
|
1662
1712
|
|
|
1713
|
+
/**
|
|
1714
|
+
* Migrate the base schema. A UNIQUE index that existing duplicate rows block
|
|
1715
|
+
* is deferred, not thrown: the rest of the pass completes so the admin path
|
|
1716
|
+
* (including the data migration that de-duplicates the table) keeps working.
|
|
1717
|
+
* User dispatch goes through \`ensureServable\`, which refuses until the
|
|
1718
|
+
* index exists. \`migrated\` stays false while one is outstanding, but the
|
|
1719
|
+
* retry (a schema-ledger write plus a full-table duplicate scan per blocked
|
|
1720
|
+
* index) runs at most once per \`BLOCKED_MIGRATION_RETRY_MS\`; in between,
|
|
1721
|
+
* callers see the cached diagnostics. The first call after a cold start
|
|
1722
|
+
* always migrates, and an admin data migration resets the clock so the
|
|
1723
|
+
* de-dup that unblocks the index takes effect on the next call.
|
|
1724
|
+
*/
|
|
1663
1725
|
protected override ensureMigrated(): void {
|
|
1664
1726
|
if (this.migrated) {
|
|
1665
1727
|
return;
|
|
1666
1728
|
}
|
|
1667
1729
|
|
|
1668
|
-
|
|
1669
|
-
|
|
1730
|
+
const now = Date.now();
|
|
1731
|
+
|
|
1732
|
+
if (this.blockedUniqueIndexes.length > 0 && now < this.migrationRetryAt) {
|
|
1733
|
+
return;
|
|
1734
|
+
}
|
|
1735
|
+
|
|
1736
|
+
this.blockedUniqueIndexes = runShardMigrations(this.sql as SqlExec, schema as unknown as SchemaLike, { cdc: config.cdc ?? false, deferBlockedUniqueIndexes: true${be} });
|
|
1737
|
+
this.migrated = this.blockedUniqueIndexes.length === 0;
|
|
1738
|
+
this.migrationRetryAt = now + BLOCKED_MIGRATION_RETRY_MS;
|
|
1739
|
+
}
|
|
1740
|
+
|
|
1741
|
+
private ensureServable(): void {
|
|
1742
|
+
this.ensureMigrated();
|
|
1743
|
+
|
|
1744
|
+
if (this.blockedUniqueIndexes.length > 0) {
|
|
1745
|
+
throw new LunoraError("INTERNAL", this.blockedUniqueIndexes.join("; "));
|
|
1746
|
+
}
|
|
1670
1747
|
}
|
|
1671
1748
|
${Z?`
|
|
1672
1749
|
protected override runShardSearchBackfill(options: { maxPages?: number }): SearchBackfillProgress {
|
|
@@ -1678,6 +1755,6 @@ ${Z?`
|
|
|
1678
1755
|
return backfillSearchIndexes(this.sql as SqlExec, schema as unknown as SchemaLike, options);
|
|
1679
1756
|
}
|
|
1680
1757
|
`:""}${vt}
|
|
1681
|
-
${_r({hasSensitiveArgs:V,lazyFunctions:c,actionOnlyFields:Gt,agentsBuild:Pe,agentsContextField:Ne,containersBuild:Oe,containersContextField:De,databaseOptions:Rt,everyContextBuild:Wt,everyContextField:Ht,facadeBlock:jt,globalDatabaseLine:Ot,notifyBuild:Vt,ormContextField:At,paymentsBuild:qe,paymentsContextField:Ue,queuesBuild:we,queuesContextField:ye,topicsBuild:Se,topicsContextField:Re,vectorsBuild:kt,vectorsContextField:xt,workflowsBuild:
|
|
1758
|
+
${_r({hasSensitiveArgs:V,lazyFunctions:c,actionOnlyFields:Gt,agentsBuild:Pe,agentsContextField:Ne,containersBuild:Oe,containersContextField:De,databaseOptions:Rt,everyContextBuild:Wt,everyContextField:Ht,facadeBlock:jt,globalDatabaseLine:Ot,notifyBuild:Vt,ormContextField:At,paymentsBuild:qe,paymentsContextField:Ue,queuesBuild:we,queuesContextField:ye,topicsBuild:Se,topicsContextField:Re,vectorsBuild:kt,vectorsContextField:xt,workflowsBuild:Ee,workflowsContextField:Ie,actionOnlyBuild:Qt})}
|
|
1682
1759
|
};
|
|
1683
1760
|
`};export{$r as b,on as e};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import{r as b}from"./json-data-Chfs2Cz5.mjs";import{CAPABILITIES as N}from"./CAPABILITY_PROBES-brcmKenl.mjs";import{a as l,G as g}from"./shared-8vTRkL2-.mjs";import{s as k}from"./platform-8oj7iXQy.mjs";const I=e=>e?{importFragment:"serveRelationFanout, ",override:`
|
|
2
2
|
protected override async runRelationFanoutRead(functionPath: string, args: Record<string, unknown>): Promise<unknown> {
|
|
3
|
-
this.
|
|
3
|
+
this.ensureServable();
|
|
4
4
|
|
|
5
5
|
const { db } = this.buildCtx({ functionPath }) as { db: DatabaseWriterLike };
|
|
6
6
|
|
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.337",
|
|
4
4
|
"description": "Code generator for Lunora: emits _generated/{api,server,dataModel}.ts from your schema",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -50,15 +50,15 @@
|
|
|
50
50
|
"access": "public"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@lunora/advisor": "1.0.0-alpha.
|
|
54
|
-
"@lunora/agent": "1.0.0-alpha.
|
|
55
|
-
"@lunora/container": "1.0.0-alpha.
|
|
53
|
+
"@lunora/advisor": "1.0.0-alpha.244",
|
|
54
|
+
"@lunora/agent": "1.0.0-alpha.234",
|
|
55
|
+
"@lunora/container": "1.0.0-alpha.88",
|
|
56
56
|
"@lunora/errors": ">=1.0.0-alpha.51 <2.0.0-0",
|
|
57
57
|
"@lunora/platform": "1.0.0-alpha.72",
|
|
58
|
-
"@lunora/queue": "1.0.0-alpha.
|
|
59
|
-
"@lunora/scheduler": "1.0.0-alpha.
|
|
58
|
+
"@lunora/queue": "1.0.0-alpha.121",
|
|
59
|
+
"@lunora/scheduler": "1.0.0-alpha.143",
|
|
60
60
|
"@lunora/values": "1.0.0-alpha.77",
|
|
61
|
-
"@lunora/workflow": "1.0.0-alpha.
|
|
61
|
+
"@lunora/workflow": "1.0.0-alpha.91",
|
|
62
62
|
"@visulima/fs": "6.0.29",
|
|
63
63
|
"jiti": "^2.7.0",
|
|
64
64
|
"quicktype-core": "^26.0.0",
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const m=(e,t=2166136261)=>{let i=t;for(let o=0;o<e.length;o+=1)i^=e.charCodeAt(o),i=Math.imul(i,16777619);return(i>>>0).toString(16).padStart(8,"0")},S=e=>`${m(e,2166136261)}${m(e,16777619)}`,H=1;function w(e){const t={},i=Object.keys(e);i.sort();for(const o of i)t[o]=e[o];return t}const O=e=>`${JSON.stringify(e,void 0,2)}
|
|
2
|
-
`,P=e=>S(O(e)),c=e=>typeof e=="object"&&e!==null,x=e=>c(e)&&c(e.fields)&&c(e.indexes)&&c(e.relations)&&typeof e.shardMode=="string",J=e=>{if(e===void 0||e.trim()==="")return{status:"absent"};let t;try{t=JSON.parse(e)}catch(o){return{error:`baseline is not valid JSON: ${o instanceof Error?o.message:String(o)}`,status:"invalid"}}if(!c(t)||t.version!==1||!c(t.tables))return{error:`baseline is malformed or written by an incompatible version (expected version ${String(1)})`,status:"invalid"};for(const[o,r]of Object.entries(t.tables))if(!x(r))return{error:`baseline table "${o}" has an invalid structure`,status:"invalid"};return{snapshot:{jurisdiction:typeof t.jurisdiction=="string"?t.jurisdiction:void 0,migrationIds:Array.isArray(t.migrationIds)?t.migrationIds:[],tables:t.tables,version:1},status:"ok"}},F=(e,t)=>e.unique===t.unique&&e.fields.length===t.fields.length&&e.fields.every((i,o)=>i===t.fields[o]),y=e=>e.unique!==void 0,p=({nullable:e,optional:t,refined:i,unique:o,...r})=>JSON.stringify(w(r)),g=e=>({form:JSON.stringify([p(e),e.optional===!0,e.nullable===!0]),refined:e.refined===!0}),v=e=>e.kind==="union"&&e.members?e.members.map(t=>g(t)):[g({...e,nullable:!1,optional:!1})],T=(e,t)=>{if(t.kind!=="union")return!1;const i=v(t);return v(e).every(o=>i.some(r=>r.form===o.form&&(o.refined||!r.refined)))},a=e=>{switch(e.kind){case"array":return`array(${e.of?a(e.of):"?"})`;case"id":return`id(${e.ref??"?"})`;case"literal":return`literal(${e.literal??"?"})`;case"object":return`object({ ${Object.keys(e.fields??{}).join(", ")} })`;case"record":return`record(${e.key?a(e.key):"?"}, ${e.of?a(e.of):"?"})`;case"union":return(e.members??[]).map(t=>a(t)).join(" | ");default:return e.kind}},l=(e,t,i)=>({remediation:"backfill",scope:"table",severity:"breaking",summary:i,table:e,type:t}),f=(e,t,i)=>({remediation:"none",scope:"table",severity:"safe",summary:i,table:e,type:t}),_=(e,t,i,o,r)=>{if(!(i.kind===o.kind&&(!r||p(i)===p(o))))return r&&T(i,o)?f(e,"widenedFieldShape",`field ${e}.${t} widened: ${a(i)} → ${a(o)} — every stored value stays valid`):i.kind!==o.kind?l(e,"changedFieldKind",`field ${e}.${t} changed type: ${i.kind} → ${o.kind} — add a data migration to convert existing values`):l(e,"changedFieldShape",`field ${e}.${t} changed shape: ${a(i)} → ${a(o)} — stored values were written against the old shape; add a data migration to convert them`)},j=(e,t,i,o)=>{const r=[];return i.unique!==o.unique&&r.push(o.unique===!0?l(e,"addedFieldConstraint",`field ${e}.${t} became unique — existing duplicates would violate it; add a data migration to de-duplicate first`):f(e,"relaxedFieldConstraint",`field ${e}.${t} is no longer unique`)),i.nullable!==o.nullable&&r.push(o.nullable===!0?f(e,"relaxedFieldConstraint",`field ${e}.${t} became nullable`):l(e,"addedFieldConstraint",`field ${e}.${t} is no longer nullable — rows holding NULL would be invalid; add a data migration to backfill them`)),i.refined!==o.refined&&r.push(o.refined===!0?l(e,"addedFieldConstraint",`field ${e}.${t} gained a validation refinement — stored values were never checked against it; add a data migration if any could fail`):f(e,"relaxedFieldConstraint",`field ${e}.${t} dropped its validation refinement`)),r},q=(e,t,i,o)=>{const r=[],n=y(i)&&y(o),s=_(e,t,i,o,n);return s&&r.push(s),n&&r.push(...j(e,t,i,o)),i.optional&&!o.optional?r.push({remediation:"backfill",severity:"breaking",summary:`field ${e}.${t} became required — rows missing it would be invalid; add a data migration to backfill it`,table:e,scope:"table",type:"fieldOptionalToRequired"}):!i.optional&&o.optional&&r.push({remediation:"none",scope:"table",severity:"safe",summary:`field ${e}.${t} became optional`,table:e,type:"fieldRequiredToOptional"}),r},E=(e,t,i)=>i.optional?{remediation:"none",scope:"table",severity:"safe",summary:`added optional field ${e}.${t}`,table:e,type:"addedOptionalField"}:{remediation:"backfill",severity:"breaking",summary:`added required field ${e}.${t} — existing rows have no value; add a data migration to backfill it`,table:e,scope:"table",type:"addedRequiredField"},A=(e,t,i,o)=>{for(const[r,n]of Object.entries(i.fields)){const s=t.fields[r];s===void 0?o.push(E(e,r,n)):o.push(...q(e,r,s,n))}for(const r of Object.keys(t.fields))i.fields[r]===void 0&&o.push({remediation:"backfill",severity:"breaking",summary:`removed field ${e}.${r} — add a data migration if stored data must be cleaned up`,table:e,scope:"table",type:"removedField"})},M=(e,t,i,o)=>{for(const[r,n]of Object.entries(i.indexes)){const s=t.indexes[r];if(s===void 0){o.push(n.unique?{remediation:"backfill",scope:"table",severity:"breaking",summary:`added unique index ${r} on ${e} — existing duplicates would violate it; add a data migration to de-duplicate first`,table:e,type:"addedIndex"}:{remediation:"none",scope:"table",severity:"safe",summary:`added index ${r} on ${e}`,table:e,type:"addedIndex"});continue}F(s,n)||o.push({remediation:"code",severity:"breaking",summary:`index ${r} on ${e} changed shape — a query may have relied on the old index`,table:e,scope:"table",type:"changedIndex"})}for(const r of Object.keys(t.indexes))i.indexes[r]===void 0&&o.push({remediation:"code",severity:"breaking",summary:`removed index ${r} on ${e} — a query that used \`.withIndex("${r}")\` would break`,table:e,scope:"table",type:"removedIndex"})},C=(e,t,i,o)=>{for(const r of Object.keys(i.relations))t.relations[r]===void 0&&o.push({remediation:"none",scope:"schema",severity:"safe",summary:`added relation ${e}.${r}`,table:e,type:"addedRelation"});for(const r of Object.keys(t.relations))i.relations[r]===void 0&&o.push({remediation:"code",scope:"schema",severity:"breaking",summary:`removed relation ${e}.${r}`,table:e,type:"removedRelation"})},$="shardBy:_unknown_",u="global",I=(e,t)=>e===u&&t.startsWith(`${u}:`)||t===u&&e.startsWith(`${u}:`),R=(e,t,i)=>{if(t===i)return i!==$?void 0:{remediation:"rehome",scope:"table",severity:"breaking",summary:`table ${e} declares a non-literal .shardBy(...) key, so codegen cannot read which column partitions it — every such key records as "${$}" and two DIFFERENT keys would compare equal. Pass the shard key as a string literal; until then this is reported on every run, because the alternative is a silent pass on a re-home that strands every row (export/import is the only way back).`,table:e,type:"changedShardMode"};if(!I(t,i))return{remediation:"rehome",severity:"breaking",summary:`table ${e} changed shard mode: ${t} → ${i} — its physical storage moves, and existing rows do NOT follow the schema; re-home them with an export/import round trip (https://lunora.sh/docs/concepts/sharding#migrating-a-populated-table)`,table:e,scope:"table",type:"changedShardMode"}},b=e=>e.memory!==void 0,k=e=>e.after??0,d=e=>e.after===void 0?`.ttl("${e.field}")`:`.ttl("${e.field}", { after: ${String(e.after)} })`,V=(e,t,i)=>{if(t===void 0&&i===void 0)return;const o=h=>({remediation:"backfill",scope:"table",severity:"breaking",summary:h,table:e,type:"changedTtlPolicy"}),r=h=>({remediation:"none",scope:"table",severity:"safe",summary:h,table:e,type:"changedTtlPolicy"});if(i===void 0)return r(`table ${e} dropped its TTL policy — its rows are no longer swept`);if(t===void 0)return o(`table ${e} gained a TTL policy ${d(i)} — every row already past the cutoff is deleted on the next alarm sweep; add a data migration to refresh or clear "${i.field}" on the rows written before it`);if(t.field!==i.field)return o(`table ${e} moved its TTL to a different column: ${d(t)} → ${d(i)} — rows are now expired by a column they were never written against; add a data migration to populate "${i.field}"`);const n=k(t),s=k(i);return s<n?o(`table ${e} shortened its TTL: ${d(t)} → ${d(i)} — rows that were not expired under the old offset are deleted on the next alarm sweep; add a data migration to refresh "${i.field}" on the rows that must survive`):s>n?r(`table ${e} lengthened its TTL: ${d(t)} → ${d(i)}`):void 0},L=(e,t,i)=>{const o=[];return t.memory!==i.memory&&o.push(i.memory===!0?{remediation:"rehome",scope:"table",severity:"breaking",summary:`table ${e} became a .memory() table — every row is deleted in every shard on the next Durable Object cold start, and no data migration survives that; export the rows first if they must be kept, or revert`,table:e,type:"changedMemoryMode"}:{remediation:"none",scope:"table",severity:"safe",summary:`table ${e} is no longer a .memory() table — its rows now survive a cold start`,table:e,type:"changedMemoryMode"}),t.commitOrdered!==i.commitOrdered&&o.push(i.commitOrdered===!0?{remediation:"backfill",scope:"table",severity:"breaking",summary:`table ${e} became .commitOrdered() — rows written before it carry no _commitSeq, so a \`_commitSeq > cursor\` changefeed never offers them; add a data migration over the table to stamp them (the rewrite allocates a sequence)`,table:e,type:"changedCommitOrdering"}:{remediation:"code",scope:"table",severity:"breaking",summary:`table ${e} is no longer .commitOrdered() — new rows carry no _commitSeq, so a \`_commitSeq > cursor\` changefeed stops advancing without erroring; update the consumers before deploying`,table:e,type:"changedCommitOrdering"}),o},D=(e,t,i,o)=>{const r=R(e,t.shardMode,i.shardMode);if(r&&o.push(r),b(t)&&b(i)){o.push(...L(e,t,i));const n=V(e,t.ttl,i.ttl);n&&o.push(n)}A(e,t,i,o),M(e,t,i,o),C(e,t,i,o)},B=(e,t)=>{const i=[],o=e?.tables??{};for(const[r,n]of Object.entries(t.tables)){const s=o[r];if(s===void 0){i.push({remediation:"none",scope:"table",severity:"safe",summary:`added table ${r}`,table:r,type:"addedTable"});continue}D(r,s,n,i)}for(const r of Object.keys(o))t.tables[r]===void 0&&i.push({remediation:"rehome",scope:"table",severity:"breaking",summary:`removed table ${r} — its rows stay in each shard's SQLite, unreachable through the schema; export the shard first if the data must be kept`,table:r,type:"removedTable"});if(e!==void 0&&e.jurisdiction!==t.jurisdiction){const r=e.jurisdiction??"(none)",n=t.jurisdiction??"(none)";i.push({remediation:"rehome",scope:"schema",severity:"breaking",summary:`Durable Object jurisdiction changed from ${r} to ${n} — this re-homes every DO and strands all existing shard, scheduler, and session-DO data in the old region (no in-place migration; export then import to move it). Revert the change, or override the gate to proceed intentionally.`,type:"changedJurisdiction"})}return{changes:i}};export{H as SCHEMA_SNAPSHOT_VERSION,a as describeShape,q as diffExistingField,B as diffSchemaSnapshots,P as hashSchemaSnapshot,x as isValidTableSnapshot,J as parseSnapshotJson,O as serializeSchemaSnapshot,w as sortKeys};
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import{LunoraError as v}from"@lunora/errors";import{SCHEMA_SNAPSHOT_VERSION as E,sortKeys as f,diffSchemaSnapshots as I,parseSnapshotJson as A}from"./SCHEMA_SNAPSHOT_VERSION-C0oHwiJZ.mjs";import{isHyperdriveGlobalTable as L}from"./isD1GlobalTable-udvHAAzD.mjs";const O=e=>{const t=e.shardMode;return t==="global"?`global:${L(e)?"hyperdrive":"d1"}`:t==="root"?t:`shardBy:${t.field}`},_=(e,t)=>{const s=JSON.stringify(e),i=JSON.stringify(t);return s===i?0:s<i?-1:1},l=e=>{const t=e.kind==="optional",s=t?e.inner:void 0,i=s??e,r={kind:t?s?.kind??"unknown":e.kind,nullable:i.column?.notNull===!1||e.column?.notNull===!1,optional:t,unique:i.column?.unique===!0||e.column?.unique===!0,...j[i.kind]?.(i)};return(i.hasRefinement===!0||e.hasRefinement===!0)&&(r.refined=!0),r},N=e=>{const t={};for(const[s,i]of Object.entries(e))t[s]=l(i);return f(t)},j={array:e=>e.inner?{of:l(e.inner)}:{},id:e=>e.tableName===void 0?{}:{ref:e.tableName},literal:e=>e.literalValue===void 0?{}:{literal:e.literalValue},object:e=>e.shape?{fields:N(e.shape)}:{},record:e=>({...e.keyType?{key:l(e.keyType)}:{},...e.valueType?{of:l(e.valueType)}:{}}),union:e=>e.members?{members:e.members.map(t=>l(t)).toSorted(_)}:{}},D=e=>{const t={};for(const[n,a]of Object.entries(e.shape))t[n]=l(a);const s={};for(const n of e.indexes)s[n.name]={fields:[...n.fields],unique:n.unique??!1};const i={};for(const n of e.relations)i[n.name]=n.through===void 0?{field:n.field,kind:n.kind,table:n.table}:{kind:n.kind,table:n.table,through:{...n.through}};const r={commitOrdered:e.commitOrdered===!0,fields:f(t),indexes:f(s),memory:e.memory===!0,relations:f(i),shardMode:O(e)};return e.ttl&&(r.ttl=e.ttl.after===void 0?{field:e.ttl.field}:{after:e.ttl.after,field:e.ttl.field}),r},C=(e,t)=>{const s={};for(const r of e.tables)s[r.name]=D(r);const i=[...t].sort();return{jurisdiction:e.jurisdiction,migrationIds:i,tables:f(s),version:E}};class R extends v{constructor(t){super("SCHEMA_SNAPSHOT_PARSE",t,{name:"SchemaSnapshotParseError"})}}const J=e=>{const t=A(e);if(t.status==="invalid")throw new R(t.error);return t.status==="ok"?t.snapshot:void 0},M={build:{allowDrift:!0,updateBaseline:!1},deploy:{allowDrift:!0,updateBaseline:!0},prepare:{allowDrift:!0,updateBaseline:!0},verify:{allowDrift:!0,updateBaseline:!1}},y=" • For backward-compatible changes (e.g. adding an optional field): pass `--allow-schema-drift` to skip the block.",k=" • To accept the new shape without a migration (you know data is compatible): pass `--update-schema-baseline`.",B=e=>{const t=e===void 0?void 0:M[e];if(e===void 0||t===void 0)return`${y}
|
|
2
|
-
${k}
|
|
3
|
-
`;const s=t.updateBaseline?k:` • To accept the new shape without a migration, run \`lunora prepare --update-schema-baseline\` — \`lunora ${e}\` does not take that flag.`;return`${y}
|
|
4
|
-
${s}
|
|
5
|
-
`},p=e=>e.map(t=>` - ${t.summary}`).join(`
|
|
6
|
-
`),w=e=>e.remediation==="backfill"&&e.table!==void 0,x=/^[A-Za-z_]\w*$/u,F=e=>` lunora migrate create backfill_${e} --table ${e}`,P=(e,t,s)=>{const i=[...new Set(e.filter(n=>w(n)).map(n=>n.table))],r=[];if(i.length>0){r.push(" • Add a `defineMigration({ id, table, up })` in lunora/ for each affected table, then re-run this command — the baseline is re-blessed on a successful deploy, not by `lunora migrate` itself.\n");const n=i.filter(a=>x.test(a));n.length>0&&r.push(`
|
|
7
|
-
Scaffold the missing migration(s) — the generated \`up\` is an identity placeholder you must fill in:
|
|
8
|
-
${n.map(a=>F(a)).join(`
|
|
9
|
-
`)}
|
|
10
|
-
|
|
11
|
-
`)}return t.length>0&&r.push(` • Migration(s) ${t.join(", ")} declare a non-literal \`table\`, so codegen cannot tell which table they visit and they cover nothing. Use a string literal.
|
|
12
|
-
`),r.push(B(s)),[`${s??"deploy"} blocked: ${String(e.length)} unresolved breaking schema change(s) since the last blessed schema baseline:`,p(e),"",`To fix:
|
|
13
|
-
${r.join("")}Docs: https://lunora.dev/docs/migrations`].join(`
|
|
14
|
-
`)},V=e=>{const{allowDrift:t=!1,baseline:s,command:i,current:r,migrations:n}=e,a=I(s,r),u=a.changes.filter(o=>o.severity==="breaking"),b=r.migrationIds.filter(o=>!(s?.migrationIds??[]).includes(o)),m=n.filter(o=>b.includes(o.id)),c=(o,h)=>({blocked:o,changes:a.changes,newMigrationIds:b,reason:h}),T=new Set(m.filter(o=>o.table!=="").map(o=>o.table)),$=m.filter(o=>o.table==="").map(o=>o.id);if(a.changes.length===0||s===void 0)return c(!1,"");if(u.length===0)return c(!1,`schema drift detected (all additive/safe):
|
|
15
|
-
${p(a.changes)}`);const g=u.filter(o=>!w(o)||!T.has(o.table));if(g.length===0){const o=new Set(u.map(d=>d.table)),h=m.filter(d=>o.has(d.table)).map(d=>d.id);return c(!1,`breaking schema drift detected, covered by ${String(h.length)} new migration(s) (${h.join(", ")}):
|
|
16
|
-
${p(u)}`)}const S=P(g,$,i);return t?c(!1,`${S}
|
|
17
|
-
|
|
18
|
-
(overridden by --allow-schema-drift)`):c(!0,S)};export{R as SchemaSnapshotParseError,C as buildSchemaSnapshot,V as evaluateSchemaDrift,J as parseSchemaSnapshot};
|