@lunora/server 1.0.0-alpha.37 → 1.0.0-alpha.39

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 CHANGED
@@ -1053,6 +1053,24 @@ interface MutatorDefinition<Args extends ValidatorMap = ValidatorMap, ServerCont
1053
1053
  * local preview.
1054
1054
  */
1055
1055
  readonly client?: (tx: ClientTx, args: InferValidatorMap<Args>) => Promise<void> | void;
1056
+ /**
1057
+ * Owner-scope the write: names the column carrying the row owner (e.g.
1058
+ * `owner: "userId"`). Before `server` runs, the mutator requires a verified
1059
+ * identity, rejects a client-supplied owner that disagrees with it, and sets
1060
+ * the column to the verified value — so the impl reads `args[owner]` without
1061
+ * trusting the client and never repeats the check by hand.
1062
+ *
1063
+ * This replaces the "every mutator opens with `assertOwner(ctx, args.userId)`"
1064
+ * pattern, and is the write-side counterpart to an `owner`-scoped
1065
+ * {@link import("./shapes").ShapeDefinition}. Unlike a shape it takes the column
1066
+ * NAME rather than `true`: a shape is bound to one `table`, so the table's
1067
+ * `.ownedBy(field)` resolves unambiguously, whereas one mutator may write
1068
+ * several tables and has no single owning table to read it from.
1069
+ *
1070
+ * Declare the column `v.optional(...)` to leave it off the wire entirely; it is
1071
+ * injected either way.
1072
+ */
1073
+ readonly owner?: string;
1056
1074
  /**
1057
1075
  * Authoritative server implementation. Runs inside the shard DO with a full
1058
1076
  * {@link MutationContext} (`ctx.db` writer); its writes append to `__cdc_log`
package/dist/index.d.ts CHANGED
@@ -1053,6 +1053,24 @@ interface MutatorDefinition<Args extends ValidatorMap = ValidatorMap, ServerCont
1053
1053
  * local preview.
1054
1054
  */
1055
1055
  readonly client?: (tx: ClientTx, args: InferValidatorMap<Args>) => Promise<void> | void;
1056
+ /**
1057
+ * Owner-scope the write: names the column carrying the row owner (e.g.
1058
+ * `owner: "userId"`). Before `server` runs, the mutator requires a verified
1059
+ * identity, rejects a client-supplied owner that disagrees with it, and sets
1060
+ * the column to the verified value — so the impl reads `args[owner]` without
1061
+ * trusting the client and never repeats the check by hand.
1062
+ *
1063
+ * This replaces the "every mutator opens with `assertOwner(ctx, args.userId)`"
1064
+ * pattern, and is the write-side counterpart to an `owner`-scoped
1065
+ * {@link import("./shapes").ShapeDefinition}. Unlike a shape it takes the column
1066
+ * NAME rather than `true`: a shape is bound to one `table`, so the table's
1067
+ * `.ownedBy(field)` resolves unambiguously, whereas one mutator may write
1068
+ * several tables and has no single owning table to read it from.
1069
+ *
1070
+ * Declare the column `v.optional(...)` to leave it off the wire entirely; it is
1071
+ * injected either way.
1072
+ */
1073
+ readonly owner?: string;
1056
1074
  /**
1057
1075
  * Authoritative server implementation. Runs inside the shard DO with a full
1058
1076
  * {@link MutationContext} (`ctx.db` writer); its writes append to `__cdc_log`
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{default as t}from"./packem_shared/asBucketStorage-1pFfH-Tn.mjs";import{initLunora as i}from"./packem_shared/initLunora-CHh1EmR4.mjs";import{createSecrets as a}from"./packem_shared/createSecrets-CgVPiW2C.mjs";import{LunoraEnvError as d,defineEnv as m,redactSecrets as x}from"./packem_shared/LunoraEnvError-CgpI2Mm_.mjs";import{LunoraError as c}from"./packem_shared/LunoraError-LVhdU0Lo.mjs";import{bindOrm as u,bindTableFacade as E}from"./packem_shared/bindOrm-Bp9hsM2q.mjs";import{httpAction as g,httpRoute as R,httpRouter as P,isSafeHeaderValue as h,serveStorageObject as b}from"./packem_shared/httpAction-C14NuF3V.mjs";import{defineIdentity as A}from"./packem_shared/defineIdentity-B7gfAgxx.mjs";import{onConnect as L,onDisconnect as T}from"./packem_shared/onConnect-CEtRmUpJ.mjs";import{defineMigration as C}from"./packem_shared/defineMigration-Bfpwxv2f.mjs";import{defineMutator as M}from"./packem_shared/defineMutator-8Kz0j1Kt.mjs";import{composePluginMiddleware as _,defineComponent as k,definePlugin as N,defineSchemaExtension as O,installPlugins as w,mergeSchemaExtension as B}from"./packem_shared/composePluginMiddleware-COr09CXA.mjs";import{PRESENCE_DEFAULT_TTL_MS as W,PRESENCE_TABLE as j,definePresence as H,presenceExtension as J}from"./packem_shared/PRESENCE_DEFAULT_TTL_MS-CF_9uiu1.mjs";import{protectPublic as q}from"./packem_shared/protectPublic-BhKewPqm.mjs";import{defineAggregateIndex as G,defineRankIndex as K,defineSchema as Q,defineTable as X,defineVectorIndex as Y}from"./packem_shared/defineAggregateIndex-CYuH6IbJ.mjs";import{defineShape as $}from"./packem_shared/defineShape-CyuRfwHz.mjs";import{anyApi as oe}from"./types.mjs";import{cronJobs as te}from"@lunora/scheduler";import{ValidationError as ie,v as fe}from"@lunora/values";import{allowAll as pe,deny as de,isDeny as me,toWhereInput as xe}from"./packem_shared/allowAll-BnyNbJZT.mjs";import{buildRlsReadRegistry as ce,composeShapeReadWhere as le}from"./packem_shared/buildRlsReadRegistry-WdiqSj87.mjs";import{createPolicyDsl as Ee,definePermission as Se,definePolicies as ge,definePolicy as Re,defineRole as Pe}from"./packem_shared/createPolicyDsl-sV1swpkD.mjs";import{defineStorageRule as be,defineStorageRules as ye}from"./packem_shared/defineStorageRule-BDu01PUn.mjs";import{mask as Ie}from"./packem_shared/mask-C6Bi78qj.mjs";import{rls as Te}from"./packem_shared/rls-_iVsPvhX.mjs";import{storageRules as Ce}from"./packem_shared/storageRules-BptPZbi8.mjs";const e="0.0.0";export{d as LunoraEnvError,c as LunoraError,W as PRESENCE_DEFAULT_TTL_MS,j as PRESENCE_TABLE,e as VERSION,ie as ValidationError,pe as allowAll,oe as anyApi,t as asBucketStorage,u as bindOrm,E as bindTableFacade,ce as buildRlsReadRegistry,_ as composePluginMiddleware,le as composeShapeReadWhere,Ee as createPolicyDsl,a as createSecrets,te as cronJobs,G as defineAggregateIndex,k as defineComponent,m as defineEnv,A as defineIdentity,C as defineMigration,M as defineMutator,Se as definePermission,N as definePlugin,ge as definePolicies,Re as definePolicy,H as definePresence,K as defineRankIndex,Pe as defineRole,Q as defineSchema,O as defineSchemaExtension,$ as defineShape,be as defineStorageRule,ye as defineStorageRules,X as defineTable,Y as defineVectorIndex,de as deny,g as httpAction,R as httpRoute,P as httpRouter,i as initLunora,w as installPlugins,me as isDeny,h as isSafeHeaderValue,Ie as mask,B as mergeSchemaExtension,L as onConnect,T as onDisconnect,J as presenceExtension,q as protectPublic,x as redactSecrets,Te as rls,b as serveStorageObject,Ce as storageRules,xe as toWhereInput,fe as v};
1
+ import{default as t}from"./packem_shared/asBucketStorage-1pFfH-Tn.mjs";import{initLunora as i}from"./packem_shared/initLunora-CHh1EmR4.mjs";import{createSecrets as a}from"./packem_shared/createSecrets-CgVPiW2C.mjs";import{LunoraEnvError as d,defineEnv as m,redactSecrets as x}from"./packem_shared/LunoraEnvError-CgpI2Mm_.mjs";import{LunoraError as c}from"./packem_shared/LunoraError-LVhdU0Lo.mjs";import{bindOrm as u,bindTableFacade as E}from"./packem_shared/bindOrm-Bp9hsM2q.mjs";import{httpAction as g,httpRoute as R,httpRouter as P,isSafeHeaderValue as h,serveStorageObject as b}from"./packem_shared/httpAction-C14NuF3V.mjs";import{defineIdentity as A}from"./packem_shared/defineIdentity-B7gfAgxx.mjs";import{onConnect as L,onDisconnect as T}from"./packem_shared/onConnect-CEtRmUpJ.mjs";import{defineMigration as C}from"./packem_shared/defineMigration-Bfpwxv2f.mjs";import{defineMutator as M}from"./packem_shared/defineMutator-BgpQ-xUo.mjs";import{composePluginMiddleware as _,defineComponent as k,definePlugin as N,defineSchemaExtension as O,installPlugins as w,mergeSchemaExtension as B}from"./packem_shared/composePluginMiddleware-COr09CXA.mjs";import{PRESENCE_DEFAULT_TTL_MS as W,PRESENCE_TABLE as j,definePresence as H,presenceExtension as J}from"./packem_shared/PRESENCE_DEFAULT_TTL_MS-CF_9uiu1.mjs";import{protectPublic as q}from"./packem_shared/protectPublic-BhKewPqm.mjs";import{defineAggregateIndex as G,defineRankIndex as K,defineSchema as Q,defineTable as X,defineVectorIndex as Y}from"./packem_shared/defineAggregateIndex-CYuH6IbJ.mjs";import{defineShape as $}from"./packem_shared/defineShape-Ds8uNqzX.mjs";import{anyApi as oe}from"./types.mjs";import{cronJobs as te}from"@lunora/scheduler";import{ValidationError as ie,v as fe}from"@lunora/values";import{allowAll as pe,deny as de,isDeny as me,toWhereInput as xe}from"./packem_shared/allowAll-BnyNbJZT.mjs";import{buildRlsReadRegistry as ce,composeShapeReadWhere as le}from"./packem_shared/buildRlsReadRegistry-WdiqSj87.mjs";import{createPolicyDsl as Ee,definePermission as Se,definePolicies as ge,definePolicy as Re,defineRole as Pe}from"./packem_shared/createPolicyDsl-sV1swpkD.mjs";import{defineStorageRule as be,defineStorageRules as ye}from"./packem_shared/defineStorageRule-BDu01PUn.mjs";import{mask as Ie}from"./packem_shared/mask-C6Bi78qj.mjs";import{rls as Te}from"./packem_shared/rls-_iVsPvhX.mjs";import{storageRules as Ce}from"./packem_shared/storageRules-BptPZbi8.mjs";const e="0.0.0";export{d as LunoraEnvError,c as LunoraError,W as PRESENCE_DEFAULT_TTL_MS,j as PRESENCE_TABLE,e as VERSION,ie as ValidationError,pe as allowAll,oe as anyApi,t as asBucketStorage,u as bindOrm,E as bindTableFacade,ce as buildRlsReadRegistry,_ as composePluginMiddleware,le as composeShapeReadWhere,Ee as createPolicyDsl,a as createSecrets,te as cronJobs,G as defineAggregateIndex,k as defineComponent,m as defineEnv,A as defineIdentity,C as defineMigration,M as defineMutator,Se as definePermission,N as definePlugin,ge as definePolicies,Re as definePolicy,H as definePresence,K as defineRankIndex,Pe as defineRole,Q as defineSchema,O as defineSchemaExtension,$ as defineShape,be as defineStorageRule,ye as defineStorageRules,X as defineTable,Y as defineVectorIndex,de as deny,g as httpAction,R as httpRoute,P as httpRouter,i as initLunora,w as installPlugins,me as isDeny,h as isSafeHeaderValue,Ie as mask,B as mergeSchemaExtension,L as onConnect,T as onDisconnect,J as presenceExtension,q as protectPublic,x as redactSecrets,Te as rls,b as serveStorageObject,Ce as storageRules,xe as toWhereInput,fe as v};
@@ -0,0 +1 @@
1
+ const o=e=>e?.auth?.userId??void 0;export{o as e};
@@ -0,0 +1 @@
1
+ import{LunoraError as i}from"@lunora/errors";import{e as s}from"./context-identity-GunnA6La.mjs";import{s as u}from"./functions-CDC08CWY.mjs";const d=(o,r,t)=>{if(o.trim()==="")throw new i("INTERNAL",'defineMutator: `owner` must name the column carrying the row owner (e.g. `owner: "userId"`)');const e=s(r);if(e===void 0)throw new i("UNAUTHORIZED","defineMutator: an owner-scoped mutator requires a verified identity; none was resolved for this request");const n=t,a=n[o];if(a!==void 0&&a!==e)throw new i("FORBIDDEN",`defineMutator: \`${o}\` does not match the verified identity — a mutator may only write rows its caller owns`);return n[o]=e,t},c=o=>({__lunoraMutator:!0,...o,handler:async(r,t)=>{const e=u(o.args??{},t),n=o.owner===void 0?e:d(o.owner,r,e);return o.server(r,n)},kind:"mutation"});export{c as defineMutator};
@@ -0,0 +1 @@
1
+ import{LunoraError as r}from"@lunora/errors";import{e as w}from"./context-identity-GunnA6La.mjs";import{s}from"./functions-CDC08CWY.mjs";import{toWhereInput as u,deny as m}from"./allowAll-BnyNbJZT.mjs";const N=e=>{if(e.table.trim()==="")throw new r("INTERNAL","defineShape: `table` must be a non-empty string");if(e.columns?.length===0)throw new r("INTERNAL","defineShape: `columns` must list at least one column when provided");if(!e.where&&e.owner===void 0)throw new r("INTERNAL",`defineShape: shape on table "${e.table}" needs a \`where\` predicate or an \`owner\` (\`owner: true\` uses the table's .ownedBy(field), \`owner: "field"\` names the column) — a shape with neither would replicate the whole table`);return{__lunoraShape:!0,...e,compileWhere:(n,h,l)=>{const d=s(e.args??{},h),t=e.where?u(e.where(n,d)):void 0;if(e.owner===void 0)return t;const o=e.owner===!0?l?.ownerField:e.owner;if(o===void 0||o==="")throw new r("INTERNAL",`defineShape: shape on table "${e.table}" declares \`owner: true\` but the table has no \`.ownedBy(field)\` — add it to the table, or name the column directly with \`owner: "field"\``);const a=w(n);if(a===void 0)return m();const i={[o]:a};return t===void 0?i:{AND:[i,t]}}}};export{N as defineShape};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/server",
3
- "version": "1.0.0-alpha.37",
3
+ "version": "1.0.0-alpha.39",
4
4
  "description": "Server primitives for Lunora: defineSchema, defineTable, query, mutation, and action",
5
5
  "keywords": [
6
6
  "backend",
@@ -1 +0,0 @@
1
- import{s as e}from"./functions-CDC08CWY.mjs";const s=r=>({__lunoraMutator:!0,...r,handler:async(n,t)=>{const o=e(r.args??{},t);return r.server(n,o)},kind:"mutation"});export{s as defineMutator};
@@ -1 +0,0 @@
1
- import{LunoraError as t}from"@lunora/errors";import{s}from"./functions-CDC08CWY.mjs";import{toWhereInput as w,deny as u}from"./allowAll-BnyNbJZT.mjs";const p=e=>e?.auth?.userId??void 0,b=e=>{if(e.table.trim()==="")throw new t("INTERNAL","defineShape: `table` must be a non-empty string");if(e.columns?.length===0)throw new t("INTERNAL","defineShape: `columns` must list at least one column when provided");if(!e.where&&e.owner===void 0)throw new t("INTERNAL",`defineShape: shape on table "${e.table}" needs a \`where\` predicate or an \`owner\` (\`owner: true\` uses the table's .ownedBy(field), \`owner: "field"\` names the column) — a shape with neither would replicate the whole table`);return{__lunoraShape:!0,...e,compileWhere:(n,h,d)=>{const l=s(e.args??{},h),r=e.where?w(e.where(n,l)):void 0;if(e.owner===void 0)return r;const o=e.owner===!0?d?.ownerField:e.owner;if(o===void 0||o==="")throw new t("INTERNAL",`defineShape: shape on table "${e.table}" declares \`owner: true\` but the table has no \`.ownedBy(field)\` — add it to the table, or name the column directly with \`owner: "field"\``);const a=p(n);if(a===void 0)return u();const i={[o]:a};return r===void 0?i:{AND:[i,r]}}}};export{b as defineShape};