@lunora/server 1.0.0-alpha.23 → 1.0.0-alpha.25

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
@@ -558,6 +558,7 @@ interface HttpRouteHandlerOptions<SearchParams extends ArgsValidator, Body exten
558
558
  * handler receives. There is no parsed `body` — streams are typically GET, and
559
559
  * the raw `request` is exposed if a handler needs to read the body itself.
560
560
  * `signal` is tripped when the client disconnects.
561
+ * @experimental Part of the HTTP-SSE stream surface; reconnect/POST-body design questions are still open.
561
562
  */
562
563
  interface HttpStreamHandlerOptions<SearchParams extends ArgsValidator, Params extends ArgsValidator> {
563
564
  ctx: HttpActionCtx;
@@ -604,6 +605,7 @@ interface HttpRouteBuilder<SearchParams extends ArgsValidator, Body extends Args
604
605
  * throw, an `event: error` frame is written with `{code, message}` before
605
606
  * the stream closes. The chunks are JSON-encoded; `R` is inferred from the
606
607
  * handler's yielded type.
608
+ * @experimental Reconnect/POST-body/wire-fidelity design questions are still open, so the shape may change.
607
609
  */
608
610
  stream: <R>(handler: (options: HttpStreamHandlerOptions<SearchParams, Params>) => AsyncGenerator<R, void, void> | AsyncIterable<R>) => LunoraRouteHandler;
609
611
  /**
@@ -1141,10 +1143,26 @@ interface DefinePluginOptions<TExtension extends Record<string, TableDefinition>
1141
1143
  middleware?: Middleware<TContextIn, TContextOut>;
1142
1144
  }
1143
1145
  /**
1146
+ * Call signatures for {@link definePlugin}. When `extension` is supplied the
1147
+ * returned plugin's `extension` is typed as PRESENT (not `?`), so the
1148
+ * canonical install pattern `defineSchema(...).extend(plugin.extension)`
1149
+ * typechecks without a non-null assertion — the shape every scaffold template
1150
+ * ships. The bare-options signature keeps `extension` optional for plugins
1151
+ * that carry only middleware.
1152
+ */
1153
+ interface DefinePluginFunction {
1154
+ <TExtension extends Record<string, TableDefinition>, TContextIn = unknown, TContextOut = TContextIn>(key: string, options: DefinePluginOptions<TExtension, TContextIn, TContextOut> & {
1155
+ extension: SchemaExtension<TExtension>;
1156
+ }): Plugin<TExtension, TContextIn, TContextOut> & {
1157
+ readonly extension: SchemaExtension<TExtension>;
1158
+ };
1159
+ <TExtension extends Record<string, TableDefinition>, TContextIn = unknown, TContextOut = TContextIn>(key: string, options: DefinePluginOptions<TExtension, TContextIn, TContextOut>): Plugin<TExtension, TContextIn, TContextOut>;
1160
+ }
1161
+ /**
1144
1162
  * Package a schema extension + middleware as a reusable plugin. Either
1145
1163
  * field is optional — `definePlugin("foo", {})` is valid but degenerate.
1146
1164
  */
1147
- declare const definePlugin: <TExtension extends Record<string, TableDefinition>, TContextIn = unknown, TContextOut = TContextIn>(key: string, options: DefinePluginOptions<TExtension, TContextIn, TContextOut>) => Plugin<TExtension, TContextIn, TContextOut>;
1165
+ declare const definePlugin: DefinePluginFunction;
1148
1166
  /**
1149
1167
  * Bundle of registered functions a {@link Component} ships. Keys are the
1150
1168
  * function's local name (e.g. `check`, `reset`); the registered function
package/dist/index.d.ts CHANGED
@@ -558,6 +558,7 @@ interface HttpRouteHandlerOptions<SearchParams extends ArgsValidator, Body exten
558
558
  * handler receives. There is no parsed `body` — streams are typically GET, and
559
559
  * the raw `request` is exposed if a handler needs to read the body itself.
560
560
  * `signal` is tripped when the client disconnects.
561
+ * @experimental Part of the HTTP-SSE stream surface; reconnect/POST-body design questions are still open.
561
562
  */
562
563
  interface HttpStreamHandlerOptions<SearchParams extends ArgsValidator, Params extends ArgsValidator> {
563
564
  ctx: HttpActionCtx;
@@ -604,6 +605,7 @@ interface HttpRouteBuilder<SearchParams extends ArgsValidator, Body extends Args
604
605
  * throw, an `event: error` frame is written with `{code, message}` before
605
606
  * the stream closes. The chunks are JSON-encoded; `R` is inferred from the
606
607
  * handler's yielded type.
608
+ * @experimental Reconnect/POST-body/wire-fidelity design questions are still open, so the shape may change.
607
609
  */
608
610
  stream: <R>(handler: (options: HttpStreamHandlerOptions<SearchParams, Params>) => AsyncGenerator<R, void, void> | AsyncIterable<R>) => LunoraRouteHandler;
609
611
  /**
@@ -1141,10 +1143,26 @@ interface DefinePluginOptions<TExtension extends Record<string, TableDefinition>
1141
1143
  middleware?: Middleware<TContextIn, TContextOut>;
1142
1144
  }
1143
1145
  /**
1146
+ * Call signatures for {@link definePlugin}. When `extension` is supplied the
1147
+ * returned plugin's `extension` is typed as PRESENT (not `?`), so the
1148
+ * canonical install pattern `defineSchema(...).extend(plugin.extension)`
1149
+ * typechecks without a non-null assertion — the shape every scaffold template
1150
+ * ships. The bare-options signature keeps `extension` optional for plugins
1151
+ * that carry only middleware.
1152
+ */
1153
+ interface DefinePluginFunction {
1154
+ <TExtension extends Record<string, TableDefinition>, TContextIn = unknown, TContextOut = TContextIn>(key: string, options: DefinePluginOptions<TExtension, TContextIn, TContextOut> & {
1155
+ extension: SchemaExtension<TExtension>;
1156
+ }): Plugin<TExtension, TContextIn, TContextOut> & {
1157
+ readonly extension: SchemaExtension<TExtension>;
1158
+ };
1159
+ <TExtension extends Record<string, TableDefinition>, TContextIn = unknown, TContextOut = TContextIn>(key: string, options: DefinePluginOptions<TExtension, TContextIn, TContextOut>): Plugin<TExtension, TContextIn, TContextOut>;
1160
+ }
1161
+ /**
1144
1162
  * Package a schema extension + middleware as a reusable plugin. Either
1145
1163
  * field is optional — `definePlugin("foo", {})` is valid but degenerate.
1146
1164
  */
1147
- declare const definePlugin: <TExtension extends Record<string, TableDefinition>, TContextIn = unknown, TContextOut = TContextIn>(key: string, options: DefinePluginOptions<TExtension, TContextIn, TContextOut>) => Plugin<TExtension, TContextIn, TContextOut>;
1165
+ declare const definePlugin: DefinePluginFunction;
1148
1166
  /**
1149
1167
  * Bundle of registered functions a {@link Component} ships. Keys are the
1150
1168
  * function's local name (e.g. `check`, `reset`); the registered function
package/dist/index.mjs CHANGED
@@ -9,10 +9,10 @@ export { defineIdentity } from './packem_shared/defineIdentity-DiX4zM9x.mjs';
9
9
  export { onConnect, onDisconnect } from './packem_shared/onConnect-CIPXKPyw.mjs';
10
10
  export { defineMigration } from './packem_shared/defineMigration-Hx01yIht.mjs';
11
11
  export { defineMutator } from './packem_shared/defineMutator-EIXAWhs9.mjs';
12
- export { composePluginMiddleware, defineComponent, definePlugin, defineSchemaExtension, installPlugins, mergeSchemaExtension } from './packem_shared/composePluginMiddleware-CcTj1_v2.mjs';
13
- export { PRESENCE_DEFAULT_TTL_MS, PRESENCE_TABLE, definePresence, presenceExtension } from './packem_shared/PRESENCE_DEFAULT_TTL_MS-BAD0QPAg.mjs';
12
+ export { composePluginMiddleware, defineComponent, definePlugin, defineSchemaExtension, installPlugins, mergeSchemaExtension } from './packem_shared/composePluginMiddleware-z62dttBo.mjs';
13
+ export { PRESENCE_DEFAULT_TTL_MS, PRESENCE_TABLE, definePresence, presenceExtension } from './packem_shared/PRESENCE_DEFAULT_TTL_MS-CwRGb41u.mjs';
14
14
  export { protectPublic } from './packem_shared/protectPublic-BlcGpiRc.mjs';
15
- export { defineAggregateIndex, defineRankIndex, defineSchema, defineTable, defineVectorIndex } from './packem_shared/defineAggregateIndex-znq4ygKQ.mjs';
15
+ export { defineAggregateIndex, defineRankIndex, defineSchema, defineTable, defineVectorIndex } from './packem_shared/defineAggregateIndex-DCzUQLMi.mjs';
16
16
  export { defineShape } from './packem_shared/defineShape-C5scNOrf.mjs';
17
17
  export { anyApi } from './types.mjs';
18
18
  export { cronJobs } from '@lunora/scheduler';
@@ -2,8 +2,8 @@ import { v } from '@lunora/values';
2
2
  import { initLunora } from './initLunora-CmMVk4i7.mjs';
3
3
  import { LunoraError } from './LunoraError-WbxmrpxR.mjs';
4
4
  import { onDisconnect } from './onConnect-CIPXKPyw.mjs';
5
- import { defineSchemaExtension, defineComponent } from './composePluginMiddleware-CcTj1_v2.mjs';
6
- import { defineTable } from './defineAggregateIndex-znq4ygKQ.mjs';
5
+ import { defineSchemaExtension, defineComponent } from './composePluginMiddleware-z62dttBo.mjs';
6
+ import { defineTable } from './defineAggregateIndex-DCzUQLMi.mjs';
7
7
 
8
8
  const DEFAULT_TTL_MS = 3e4;
9
9
  const MAX_DATA_BYTES = 4096;
@@ -28,7 +28,7 @@ const defineSchemaExtension = (key, options) => {
28
28
  ...options.vectorIndexes ? { vectorIndexes: options.vectorIndexes } : {}
29
29
  };
30
30
  };
31
- const definePlugin = (key, options) => {
31
+ const definePlugin = ((key, options) => {
32
32
  if (!key) {
33
33
  throw new LunoraError$1("INTERNAL", "definePlugin: `key` is required and must be a non-empty string");
34
34
  }
@@ -40,7 +40,7 @@ const definePlugin = (key, options) => {
40
40
  ...options.extension ? { extension: options.extension } : {},
41
41
  ...options.middleware ? { middleware: options.middleware } : {}
42
42
  };
43
- };
43
+ });
44
44
  const defineComponent = (key, options) => {
45
45
  const plugin = definePlugin(key, {
46
46
  ...options.extension ? { extension: options.extension } : {},
@@ -1,6 +1,6 @@
1
1
  import { LunoraError as LunoraError$1 } from '@lunora/errors';
2
2
  import { isOrWrapsFromValidator, v } from '@lunora/values';
3
- import { mergeSchemaExtension } from './composePluginMiddleware-CcTj1_v2.mjs';
3
+ import { mergeSchemaExtension } from './composePluginMiddleware-z62dttBo.mjs';
4
4
 
5
5
  const relationBuilder = {
6
6
  many: (table, options) => {
@@ -277,10 +277,10 @@ const validateExternalSources = (tables) => {
277
277
  `defineSchema: sourced + .shardBy() table "${name}" needs a \`tenantBy\` mapper — without it every tenant's DO would run the same unscoped query and replicate the whole multitenant table (a cross-tenant leak). Add \`tenantBy: (shardKey) => [shardKey]\` binding the shard key into the query's parameters.`
278
278
  );
279
279
  }
280
- if (source.mode === "incremental") {
280
+ if (source.mode !== void 0 && source.mode !== "full-pull") {
281
281
  throw new LunoraError$1(
282
282
  "INTERNAL",
283
- `defineSchema: table "${name}" uses \`mode: "incremental"\`, which is not yet implemented — only "full-pull" (the default) is supported. Remove \`mode\` or set it to "full-pull".`
283
+ `defineSchema: table "${name}" uses \`mode: ${JSON.stringify(source.mode)}\` — only "full-pull" (the default) is supported. Remove \`mode\` or set it to "full-pull".`
284
284
  );
285
285
  }
286
286
  }
package/dist/types.d.mts CHANGED
@@ -28,12 +28,14 @@ type ExternalSourceRefresh = "manual" | {
28
28
  everyMs: number;
29
29
  };
30
30
  /**
31
- * Delete-detection mode for external-source ingest. `"full-pull"` (default) reads
32
- * the whole tenant membership each tick and diffs it, so it observes upstream
33
- * deletes; `"incremental"` pulls only changed rows (cheap) and is blind to deletes
34
- * unless paired with a soft-delete column or a `reconcileEveryMs` full-pull sweep.
31
+ * Delete-detection mode for external-source ingest. `"full-pull"` (the default and
32
+ * currently the only mode) reads the whole tenant membership each tick and diffs
33
+ * it, so it observes upstream deletes. An `"incremental"` mode (pull only changed
34
+ * rows above the ~10k full-pull cap) is not implemented yet — it needs durable
35
+ * cursor/watermark machinery that does not exist; this alias is the seam it
36
+ * returns through.
35
37
  */
36
- type ExternalSourceMode = "full-pull" | "incremental";
38
+ type ExternalSourceMode = "full-pull";
37
39
  /**
38
40
  * Config for `.source(...)` (plan 077): declares a table as **materialized from an
39
41
  * external Postgres/MySQL behind Cloudflare Hyperdrive**, not written by user
@@ -52,12 +54,10 @@ interface ExternalSourceDefinition {
52
54
  idColumn?: string;
53
55
  /** Transform an external row into the stored document body. Omit ⇒ every selected column except `idColumn` is copied. */
54
56
  map?: (row: Record<string, unknown>) => Record<string, unknown>;
55
- /** Delete-detection mode. Defaults to `"full-pull"`. */
57
+ /** Delete-detection mode. `"full-pull"` (the default) is the only mode today. */
56
58
  mode?: ExternalSourceMode;
57
59
  /** The full tenant-membership query, with driver-native placeholders (`$1` / `?`). `tenantBy` binds its params. */
58
60
  query: string;
59
- /** `"incremental"` only: run a full-pull reconcile this often to garbage-collect tombstones the incremental path can't see. */
60
- reconcileEveryMs?: number;
61
61
  /** Poll cadence, or `"manual"`. Omit ⇒ the runtime's size-scaled default. */
62
62
  refresh?: ExternalSourceRefresh;
63
63
  /**
@@ -684,6 +684,21 @@ interface ScheduledJob {
684
684
  /** Routing hint forwarded so dispatch lands on the right shard. */
685
685
  shardKey?: string;
686
686
  }
687
+ /**
688
+ * A schedulable durable-workflow reference — the generated `workflows.&lt;name>` /
689
+ * `agents.&lt;name>` object, which carries its `WORKFLOW_*`/`AGENT_*` binding and
690
+ * stable name. Structural mirror of `@lunora/scheduler`'s `WorkflowReference` so
691
+ * `ctx.scheduler` can target a workflow/agent without a dependency on
692
+ * `@lunora/scheduler` / `@lunora/workflow`. A scheduled workflow target starts a
693
+ * fresh instance on fire (the args become its `params`).
694
+ */
695
+ interface SchedulableWorkflowReference {
696
+ /** The `WORKFLOW_*`/`AGENT_*` binding name (present on a generated ref). */
697
+ readonly binding?: string;
698
+ readonly isLunoraWorkflow: true;
699
+ /** The workflow/agent export/stable name (present on a generated ref). */
700
+ readonly name?: string;
701
+ }
687
702
  interface Scheduler {
688
703
  /** Cancel a pending job by id. `cancelled` is `false` when no such job exists. */
689
704
  cancel: (id: string) => Promise<{
@@ -693,8 +708,15 @@ interface Scheduler {
693
708
  get: (id: string) => Promise<ScheduledJob | null>;
694
709
  /** List all pending scheduled jobs. */
695
710
  list: () => Promise<ScheduledJob[]>;
696
- runAfter: (delayMs: number, functionPath: string, args?: Record<string, unknown>) => Promise<string>;
697
- runAt: (timestampMs: number, functionPath: string, args?: Record<string, unknown>) => Promise<string>;
711
+ /**
712
+ * Schedule a one-shot run `delayMs` from now. `target` is a function path
713
+ * (`"ns:fn"`) dispatched as a one-shot, or a generated `workflows.&lt;name>` /
714
+ * `agents.&lt;name>` reference which starts a fresh durable instance on fire
715
+ * (the args become its `params`).
716
+ */
717
+ runAfter: (delayMs: number, target: SchedulableWorkflowReference | string, args?: Record<string, unknown>) => Promise<string>;
718
+ /** Like {@link Scheduler.runAfter} but fires at an absolute epoch-ms timestamp. */
719
+ runAt: (timestampMs: number, target: SchedulableWorkflowReference | string, args?: Record<string, unknown>) => Promise<string>;
698
720
  }
699
721
  /**
700
722
  * A workflow instance's lifecycle status. Clean public mirror of
package/dist/types.d.ts CHANGED
@@ -28,12 +28,14 @@ type ExternalSourceRefresh = "manual" | {
28
28
  everyMs: number;
29
29
  };
30
30
  /**
31
- * Delete-detection mode for external-source ingest. `"full-pull"` (default) reads
32
- * the whole tenant membership each tick and diffs it, so it observes upstream
33
- * deletes; `"incremental"` pulls only changed rows (cheap) and is blind to deletes
34
- * unless paired with a soft-delete column or a `reconcileEveryMs` full-pull sweep.
31
+ * Delete-detection mode for external-source ingest. `"full-pull"` (the default and
32
+ * currently the only mode) reads the whole tenant membership each tick and diffs
33
+ * it, so it observes upstream deletes. An `"incremental"` mode (pull only changed
34
+ * rows above the ~10k full-pull cap) is not implemented yet — it needs durable
35
+ * cursor/watermark machinery that does not exist; this alias is the seam it
36
+ * returns through.
35
37
  */
36
- type ExternalSourceMode = "full-pull" | "incremental";
38
+ type ExternalSourceMode = "full-pull";
37
39
  /**
38
40
  * Config for `.source(...)` (plan 077): declares a table as **materialized from an
39
41
  * external Postgres/MySQL behind Cloudflare Hyperdrive**, not written by user
@@ -52,12 +54,10 @@ interface ExternalSourceDefinition {
52
54
  idColumn?: string;
53
55
  /** Transform an external row into the stored document body. Omit ⇒ every selected column except `idColumn` is copied. */
54
56
  map?: (row: Record<string, unknown>) => Record<string, unknown>;
55
- /** Delete-detection mode. Defaults to `"full-pull"`. */
57
+ /** Delete-detection mode. `"full-pull"` (the default) is the only mode today. */
56
58
  mode?: ExternalSourceMode;
57
59
  /** The full tenant-membership query, with driver-native placeholders (`$1` / `?`). `tenantBy` binds its params. */
58
60
  query: string;
59
- /** `"incremental"` only: run a full-pull reconcile this often to garbage-collect tombstones the incremental path can't see. */
60
- reconcileEveryMs?: number;
61
61
  /** Poll cadence, or `"manual"`. Omit ⇒ the runtime's size-scaled default. */
62
62
  refresh?: ExternalSourceRefresh;
63
63
  /**
@@ -684,6 +684,21 @@ interface ScheduledJob {
684
684
  /** Routing hint forwarded so dispatch lands on the right shard. */
685
685
  shardKey?: string;
686
686
  }
687
+ /**
688
+ * A schedulable durable-workflow reference — the generated `workflows.&lt;name>` /
689
+ * `agents.&lt;name>` object, which carries its `WORKFLOW_*`/`AGENT_*` binding and
690
+ * stable name. Structural mirror of `@lunora/scheduler`'s `WorkflowReference` so
691
+ * `ctx.scheduler` can target a workflow/agent without a dependency on
692
+ * `@lunora/scheduler` / `@lunora/workflow`. A scheduled workflow target starts a
693
+ * fresh instance on fire (the args become its `params`).
694
+ */
695
+ interface SchedulableWorkflowReference {
696
+ /** The `WORKFLOW_*`/`AGENT_*` binding name (present on a generated ref). */
697
+ readonly binding?: string;
698
+ readonly isLunoraWorkflow: true;
699
+ /** The workflow/agent export/stable name (present on a generated ref). */
700
+ readonly name?: string;
701
+ }
687
702
  interface Scheduler {
688
703
  /** Cancel a pending job by id. `cancelled` is `false` when no such job exists. */
689
704
  cancel: (id: string) => Promise<{
@@ -693,8 +708,15 @@ interface Scheduler {
693
708
  get: (id: string) => Promise<ScheduledJob | null>;
694
709
  /** List all pending scheduled jobs. */
695
710
  list: () => Promise<ScheduledJob[]>;
696
- runAfter: (delayMs: number, functionPath: string, args?: Record<string, unknown>) => Promise<string>;
697
- runAt: (timestampMs: number, functionPath: string, args?: Record<string, unknown>) => Promise<string>;
711
+ /**
712
+ * Schedule a one-shot run `delayMs` from now. `target` is a function path
713
+ * (`"ns:fn"`) dispatched as a one-shot, or a generated `workflows.&lt;name>` /
714
+ * `agents.&lt;name>` reference which starts a fresh durable instance on fire
715
+ * (the args become its `params`).
716
+ */
717
+ runAfter: (delayMs: number, target: SchedulableWorkflowReference | string, args?: Record<string, unknown>) => Promise<string>;
718
+ /** Like {@link Scheduler.runAfter} but fires at an absolute epoch-ms timestamp. */
719
+ runAt: (timestampMs: number, target: SchedulableWorkflowReference | string, args?: Record<string, unknown>) => Promise<string>;
698
720
  }
699
721
  /**
700
722
  * A workflow instance's lifecycle status. Clean public mirror of
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/server",
3
- "version": "1.0.0-alpha.23",
3
+ "version": "1.0.0-alpha.25",
4
4
  "description": "Server primitives for Lunora: defineSchema, defineTable, query, mutation, and action",
5
5
  "keywords": [
6
6
  "backend",
@@ -62,9 +62,9 @@
62
62
  "access": "public"
63
63
  },
64
64
  "dependencies": {
65
- "@lunora/errors": "1.0.0-alpha.4",
66
- "@lunora/scheduler": "1.0.0-alpha.8",
67
- "@lunora/values": "1.0.0-alpha.7",
65
+ "@lunora/errors": "1.0.0-alpha.5",
66
+ "@lunora/scheduler": "1.0.0-alpha.10",
67
+ "@lunora/values": "1.0.0-alpha.8",
68
68
  "drizzle-orm": "^0.45.2",
69
69
  "hono": "^4.12.28"
70
70
  },