@lunora/hyperdrive 1.0.0-alpha.8 → 1.0.0-alpha.80

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/LICENSE.md CHANGED
@@ -103,3 +103,9 @@ Unless required by applicable law or agreed to in writing, software distributed
103
103
  under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
104
104
  CONDITIONS OF ANY KIND, either express or implied. See the License for the
105
105
  specific language governing permissions and limitations under the License.
106
+
107
+ <!-- DEPENDENCIES -->
108
+ <!-- /DEPENDENCIES -->
109
+
110
+ <!-- TYPE_DEPENDENCIES -->
111
+ <!-- /TYPE_DEPENDENCIES -->
package/dist/global.d.mts CHANGED
@@ -1,46 +1,71 @@
1
- import { DatabaseWriterLike } from '@lunora/do';
1
+ import { DatabaseWriterLike } from '@lunora/shard-engine';
2
2
  import { SqlExec, SqlDialect, SqlCtxDbOptions } from '@lunora/sql-store';
3
- /** Minimal row-returning client (e.g. `@lunora/hyperdrive`'s `fromPostgresJs`/`fromNodePg` result). */
4
- interface RowClient {
5
- query: <Row = Record<string, unknown>>(text: string, params?: ReadonlyArray<unknown>) => Promise<Row[]>;
6
- }
7
- /** Minimal `mysql2/promise` connection/pool surface `execute` resolves to `[rows | ResultSetHeader, fields]`. */
8
- interface Mysql2Execute {
9
- execute: (text: string, params?: ReadonlyArray<unknown>) => Promise<[unknown, unknown]>;
10
- }
3
+ import { M as Mysql2Like, S as SqlClient } from "./packem_shared/types.d-DE1NYxyA.mjs";
4
+ /**
5
+ * Minimal row-returning client (e.g. `@lunora/hyperdrive`'s `fromPostgresJs`/`fromNodePg`
6
+ * result). Aliases {@link SqlClient} — the exec-facing name is kept so call sites read
7
+ * intent, but the shape is the single source of truth in `./types` (no drift).
8
+ */
9
+ type RowClient = SqlClient;
10
+ /**
11
+ * Minimal `mysql2/promise` connection/pool surface — `execute` resolves to
12
+ * `[rows | ResultSetHeader, fields]`. Aliases {@link Mysql2Like} so the /global entry's
13
+ * driver surface can never drift from the main entry's.
14
+ */
15
+ type Mysql2Execute = Mysql2Like;
11
16
  /**
12
- * Wrap a Postgres row-client (from `@lunora/hyperdrive`'s `fromPostgresJs` /
13
- * `fromNodePg`) as a {@link SqlExec}. The core already renders `$N` placeholders
14
- * for Postgres, so `all`/`run` forward verbatim. Postgres uses `RETURNING` for
15
- * OCC (read via `all`), so `run` reports no affected-row count.
16
- */
17
+ * Wrap a Postgres row-client (from `@lunora/hyperdrive`'s `fromPostgresJs` /
18
+ * `fromNodePg`) as a {@link SqlExec}. The core already renders `$N` placeholders
19
+ * for Postgres, so `all`/`run` forward verbatim. Postgres uses `RETURNING` for
20
+ * OCC (read via `all`), so `run` reports no affected-row count.
21
+ *
22
+ * `batch` dispatches every statement concurrently (`Promise.all`) over `client`
23
+ * rather than awaiting each `query` call in turn — `RowClient` only exposes a
24
+ * single-statement `query`, so there is no wire-level multi-statement command
25
+ * to reach for. When `client` is backed by a pool (the common production
26
+ * shape), this genuinely spreads the statements across multiple physical
27
+ * connections instead of serializing one full round trip at a time; against a
28
+ * single connection it still removes the sequential *await*, though the
29
+ * underlying driver may itself queue the sends. Either way it stays
30
+ * non-atomic, at-least-once, and unordered between elements, same as the
31
+ * sequential fallback minus the ordering — safe only for statements whose
32
+ * effects don't depend on each other, which is what every current caller
33
+ * batches (distinct-keyed companion rows).
34
+ */
17
35
  declare const buildPgExec: (client: RowClient) => SqlExec;
18
36
  /**
19
- * Wrap a `mysql2/promise` connection/pool as a {@link SqlExec}. The core already
20
- * renders backtick identifiers and `?` placeholders for MySQL, so `all`/`run`
21
- * forward verbatim. MySQL has no `RETURNING`, so `run` surfaces `affectedRows`
22
- * for the store's affected-rows OCC guard.
23
- *
24
- * **The connection MUST be created with the `CLIENT_FOUND_ROWS` flag**
25
- * (mysql2: `createPool({ flags: ["FOUND_ROWS"] })`). Without it, `affectedRows`
26
- * counts *changed* rows, so an idempotent `patch`/`replace` that re-writes the
27
- * same values reports 0 and the OCC guard raises a spurious conflict.
28
- */
37
+ * Wrap a `mysql2/promise` connection/pool as a {@link SqlExec}. The core already
38
+ * renders backtick identifiers and `?` placeholders for MySQL, so `all`/`run`
39
+ * forward verbatim. MySQL has no `RETURNING`, so `run` surfaces `affectedRows`
40
+ * for the store's affected-rows OCC guard.
41
+ *
42
+ * **The connection MUST be created with the `CLIENT_FOUND_ROWS` flag**
43
+ * (mysql2: `createPool({ flags: ["FOUND_ROWS"] })`). Without it, `affectedRows`
44
+ * counts *changed* rows, so an idempotent `patch`/`replace` that re-writes the
45
+ * same values reports 0 and the OCC guard raises a spurious conflict.
46
+ *
47
+ * `batch` dispatches every statement concurrently (`Promise.all`), same
48
+ * rationale as {@link buildPgExec}'s `batch` — `Mysql2Like` only exposes a
49
+ * single-statement `execute`, so this is "spread across a pool's connections"
50
+ * rather than one wire-level multi-statement command; still non-atomic,
51
+ * at-least-once, and unordered between elements, safe only for statements
52
+ * with no cross-effect (what every current caller batches).
53
+ */
29
54
  declare const buildMysqlExec: (connection: Mysql2Execute) => SqlExec;
30
55
  /**
31
- * **Postgres** dialect. Differs from SQLite only in column types
32
- * (`DOUBLE PRECISION`/`BYTEA`/`BIGSERIAL`), the `information_schema` catalog
33
- * probe, and unique-violation detection (SQLSTATE `23505`).
34
- */
56
+ * **Postgres** dialect. Differs from SQLite only in column types
57
+ * (`DOUBLE PRECISION`/`BYTEA`/`BIGSERIAL`), the `information_schema` catalog
58
+ * probe, and unique-violation detection (SQLSTATE `23505`).
59
+ */
35
60
  declare const postgresDialect: SqlDialect;
36
61
  /**
37
- * **MySQL** dialect. Diverges in: **no `RETURNING`** (the store's OCC falls back
38
- * to affected-rows — which requires the connection's `CLIENT_FOUND_ROWS` flag so
39
- * a no-op update still reports a matched row, see `buildMysqlExec`); bounded
40
- * `VARCHAR` keys (TEXT can't be a primary key / unindexed); a TEXT/BLOB index key
41
- * prefix; and `ER_DUP_ENTRY` (errno 1062) unique violations. (Drizzle's MySQL
42
- * dialect supplies the backtick identifiers + `ON DUPLICATE KEY` upserts.)
43
- */
62
+ * **MySQL** dialect. Diverges in: **no `RETURNING`** (the store's OCC falls back
63
+ * to affected-rows — which requires the connection's `CLIENT_FOUND_ROWS` flag so
64
+ * a no-op update still reports a matched row, see `buildMysqlExec`); bounded
65
+ * `VARCHAR` keys (TEXT can't be a primary key / unindexed); a TEXT/BLOB index key
66
+ * prefix; and `ER_DUP_ENTRY` (errno 1062) unique violations. (Drizzle's MySQL
67
+ * dialect supplies the backtick identifiers + `ON DUPLICATE KEY` upserts.)
68
+ */
44
69
  declare const mysqlDialect: SqlDialect;
45
70
  /** Which engine a Hyperdrive-backed `.global()` store targets. */
46
71
  type HyperdriveEngine = "mysql" | "postgres";
@@ -52,16 +77,12 @@ interface CreateHyperdriveGlobalCtxDbOptions extends Omit<SqlCtxDbOptions, "dial
52
77
  exec: SqlExec;
53
78
  }
54
79
  /**
55
- * Build a reactive `.global()` writer backed by a Hyperdrive-reachable
56
- * Postgres/MySQL database. Pass a built {@link SqlExec} (via {@link buildPgExec}/
57
- * {@link buildMysqlExec}) and the matching `engine`; everything else mirrors the
58
- * D1 store options.
59
- */
60
- declare const createHyperdriveGlobalCtxDb: ({
61
- engine,
62
- exec,
63
- ...rest
64
- }: CreateHyperdriveGlobalCtxDbOptions) => DatabaseWriterLike;
80
+ * Build a reactive `.global()` writer backed by a Hyperdrive-reachable
81
+ * Postgres/MySQL database. Pass a built {@link SqlExec} (via {@link buildPgExec}/
82
+ * {@link buildMysqlExec}) and the matching `engine`; everything else mirrors the
83
+ * D1 store options.
84
+ */
85
+ declare const createHyperdriveGlobalCtxDb: ({ engine, exec, ...rest }: CreateHyperdriveGlobalCtxDbOptions) => DatabaseWriterLike;
65
86
  /** Convenience: a **Postgres** `.global()` writer from a row-client (postgres.js/pg over Hyperdrive). */
66
87
  declare const createPostgresGlobalCtxDb: (client: RowClient, options: Omit<CreateHyperdriveGlobalCtxDbOptions, "engine" | "exec">) => DatabaseWriterLike;
67
88
  /** Convenience: a **MySQL** `.global()` writer from a `mysql2/promise` connection/pool (created with `flags: ["FOUND_ROWS"]`). */
package/dist/global.d.ts CHANGED
@@ -1,46 +1,71 @@
1
- import { DatabaseWriterLike } from '@lunora/do';
1
+ import { DatabaseWriterLike } from '@lunora/shard-engine';
2
2
  import { SqlExec, SqlDialect, SqlCtxDbOptions } from '@lunora/sql-store';
3
- /** Minimal row-returning client (e.g. `@lunora/hyperdrive`'s `fromPostgresJs`/`fromNodePg` result). */
4
- interface RowClient {
5
- query: <Row = Record<string, unknown>>(text: string, params?: ReadonlyArray<unknown>) => Promise<Row[]>;
6
- }
7
- /** Minimal `mysql2/promise` connection/pool surface `execute` resolves to `[rows | ResultSetHeader, fields]`. */
8
- interface Mysql2Execute {
9
- execute: (text: string, params?: ReadonlyArray<unknown>) => Promise<[unknown, unknown]>;
10
- }
3
+ import { M as Mysql2Like, S as SqlClient } from "./packem_shared/types.d-DE1NYxyA.js";
4
+ /**
5
+ * Minimal row-returning client (e.g. `@lunora/hyperdrive`'s `fromPostgresJs`/`fromNodePg`
6
+ * result). Aliases {@link SqlClient} — the exec-facing name is kept so call sites read
7
+ * intent, but the shape is the single source of truth in `./types` (no drift).
8
+ */
9
+ type RowClient = SqlClient;
10
+ /**
11
+ * Minimal `mysql2/promise` connection/pool surface — `execute` resolves to
12
+ * `[rows | ResultSetHeader, fields]`. Aliases {@link Mysql2Like} so the /global entry's
13
+ * driver surface can never drift from the main entry's.
14
+ */
15
+ type Mysql2Execute = Mysql2Like;
11
16
  /**
12
- * Wrap a Postgres row-client (from `@lunora/hyperdrive`'s `fromPostgresJs` /
13
- * `fromNodePg`) as a {@link SqlExec}. The core already renders `$N` placeholders
14
- * for Postgres, so `all`/`run` forward verbatim. Postgres uses `RETURNING` for
15
- * OCC (read via `all`), so `run` reports no affected-row count.
16
- */
17
+ * Wrap a Postgres row-client (from `@lunora/hyperdrive`'s `fromPostgresJs` /
18
+ * `fromNodePg`) as a {@link SqlExec}. The core already renders `$N` placeholders
19
+ * for Postgres, so `all`/`run` forward verbatim. Postgres uses `RETURNING` for
20
+ * OCC (read via `all`), so `run` reports no affected-row count.
21
+ *
22
+ * `batch` dispatches every statement concurrently (`Promise.all`) over `client`
23
+ * rather than awaiting each `query` call in turn — `RowClient` only exposes a
24
+ * single-statement `query`, so there is no wire-level multi-statement command
25
+ * to reach for. When `client` is backed by a pool (the common production
26
+ * shape), this genuinely spreads the statements across multiple physical
27
+ * connections instead of serializing one full round trip at a time; against a
28
+ * single connection it still removes the sequential *await*, though the
29
+ * underlying driver may itself queue the sends. Either way it stays
30
+ * non-atomic, at-least-once, and unordered between elements, same as the
31
+ * sequential fallback minus the ordering — safe only for statements whose
32
+ * effects don't depend on each other, which is what every current caller
33
+ * batches (distinct-keyed companion rows).
34
+ */
17
35
  declare const buildPgExec: (client: RowClient) => SqlExec;
18
36
  /**
19
- * Wrap a `mysql2/promise` connection/pool as a {@link SqlExec}. The core already
20
- * renders backtick identifiers and `?` placeholders for MySQL, so `all`/`run`
21
- * forward verbatim. MySQL has no `RETURNING`, so `run` surfaces `affectedRows`
22
- * for the store's affected-rows OCC guard.
23
- *
24
- * **The connection MUST be created with the `CLIENT_FOUND_ROWS` flag**
25
- * (mysql2: `createPool({ flags: ["FOUND_ROWS"] })`). Without it, `affectedRows`
26
- * counts *changed* rows, so an idempotent `patch`/`replace` that re-writes the
27
- * same values reports 0 and the OCC guard raises a spurious conflict.
28
- */
37
+ * Wrap a `mysql2/promise` connection/pool as a {@link SqlExec}. The core already
38
+ * renders backtick identifiers and `?` placeholders for MySQL, so `all`/`run`
39
+ * forward verbatim. MySQL has no `RETURNING`, so `run` surfaces `affectedRows`
40
+ * for the store's affected-rows OCC guard.
41
+ *
42
+ * **The connection MUST be created with the `CLIENT_FOUND_ROWS` flag**
43
+ * (mysql2: `createPool({ flags: ["FOUND_ROWS"] })`). Without it, `affectedRows`
44
+ * counts *changed* rows, so an idempotent `patch`/`replace` that re-writes the
45
+ * same values reports 0 and the OCC guard raises a spurious conflict.
46
+ *
47
+ * `batch` dispatches every statement concurrently (`Promise.all`), same
48
+ * rationale as {@link buildPgExec}'s `batch` — `Mysql2Like` only exposes a
49
+ * single-statement `execute`, so this is "spread across a pool's connections"
50
+ * rather than one wire-level multi-statement command; still non-atomic,
51
+ * at-least-once, and unordered between elements, safe only for statements
52
+ * with no cross-effect (what every current caller batches).
53
+ */
29
54
  declare const buildMysqlExec: (connection: Mysql2Execute) => SqlExec;
30
55
  /**
31
- * **Postgres** dialect. Differs from SQLite only in column types
32
- * (`DOUBLE PRECISION`/`BYTEA`/`BIGSERIAL`), the `information_schema` catalog
33
- * probe, and unique-violation detection (SQLSTATE `23505`).
34
- */
56
+ * **Postgres** dialect. Differs from SQLite only in column types
57
+ * (`DOUBLE PRECISION`/`BYTEA`/`BIGSERIAL`), the `information_schema` catalog
58
+ * probe, and unique-violation detection (SQLSTATE `23505`).
59
+ */
35
60
  declare const postgresDialect: SqlDialect;
36
61
  /**
37
- * **MySQL** dialect. Diverges in: **no `RETURNING`** (the store's OCC falls back
38
- * to affected-rows — which requires the connection's `CLIENT_FOUND_ROWS` flag so
39
- * a no-op update still reports a matched row, see `buildMysqlExec`); bounded
40
- * `VARCHAR` keys (TEXT can't be a primary key / unindexed); a TEXT/BLOB index key
41
- * prefix; and `ER_DUP_ENTRY` (errno 1062) unique violations. (Drizzle's MySQL
42
- * dialect supplies the backtick identifiers + `ON DUPLICATE KEY` upserts.)
43
- */
62
+ * **MySQL** dialect. Diverges in: **no `RETURNING`** (the store's OCC falls back
63
+ * to affected-rows — which requires the connection's `CLIENT_FOUND_ROWS` flag so
64
+ * a no-op update still reports a matched row, see `buildMysqlExec`); bounded
65
+ * `VARCHAR` keys (TEXT can't be a primary key / unindexed); a TEXT/BLOB index key
66
+ * prefix; and `ER_DUP_ENTRY` (errno 1062) unique violations. (Drizzle's MySQL
67
+ * dialect supplies the backtick identifiers + `ON DUPLICATE KEY` upserts.)
68
+ */
44
69
  declare const mysqlDialect: SqlDialect;
45
70
  /** Which engine a Hyperdrive-backed `.global()` store targets. */
46
71
  type HyperdriveEngine = "mysql" | "postgres";
@@ -52,16 +77,12 @@ interface CreateHyperdriveGlobalCtxDbOptions extends Omit<SqlCtxDbOptions, "dial
52
77
  exec: SqlExec;
53
78
  }
54
79
  /**
55
- * Build a reactive `.global()` writer backed by a Hyperdrive-reachable
56
- * Postgres/MySQL database. Pass a built {@link SqlExec} (via {@link buildPgExec}/
57
- * {@link buildMysqlExec}) and the matching `engine`; everything else mirrors the
58
- * D1 store options.
59
- */
60
- declare const createHyperdriveGlobalCtxDb: ({
61
- engine,
62
- exec,
63
- ...rest
64
- }: CreateHyperdriveGlobalCtxDbOptions) => DatabaseWriterLike;
80
+ * Build a reactive `.global()` writer backed by a Hyperdrive-reachable
81
+ * Postgres/MySQL database. Pass a built {@link SqlExec} (via {@link buildPgExec}/
82
+ * {@link buildMysqlExec}) and the matching `engine`; everything else mirrors the
83
+ * D1 store options.
84
+ */
85
+ declare const createHyperdriveGlobalCtxDb: ({ engine, exec, ...rest }: CreateHyperdriveGlobalCtxDbOptions) => DatabaseWriterLike;
65
86
  /** Convenience: a **Postgres** `.global()` writer from a row-client (postgres.js/pg over Hyperdrive). */
66
87
  declare const createPostgresGlobalCtxDb: (client: RowClient, options: Omit<CreateHyperdriveGlobalCtxDbOptions, "engine" | "exec">) => DatabaseWriterLike;
67
88
  /** Convenience: a **MySQL** `.global()` writer from a `mysql2/promise` connection/pool (created with `flags: ["FOUND_ROWS"]`). */
package/dist/global.mjs CHANGED
@@ -1,9 +1 @@
1
- import { createSqlCtxDb } from '@lunora/sql-store';
2
- import { postgresDialect, mysqlDialect } from './packem_shared/mysqlDialect-oNhZ58s8.mjs';
3
- import { buildMysqlExec, buildPgExec } from './packem_shared/buildMysqlExec-DBbCjyq3.mjs';
4
-
5
- const createHyperdriveGlobalCtxDb = ({ engine, exec, ...rest }) => createSqlCtxDb({ ...rest, dialect: engine === "postgres" ? postgresDialect : mysqlDialect, exec });
6
- const createPostgresGlobalCtxDb = (client, options) => createHyperdriveGlobalCtxDb({ ...options, engine: "postgres", exec: buildPgExec(client) });
7
- const createMysqlGlobalCtxDb = (connection, options) => createHyperdriveGlobalCtxDb({ ...options, engine: "mysql", exec: buildMysqlExec(connection) });
8
-
9
- export { buildMysqlExec, buildPgExec, createHyperdriveGlobalCtxDb, createMysqlGlobalCtxDb, createPostgresGlobalCtxDb, mysqlDialect, postgresDialect };
1
+ import{createSqlCtxDb as l}from"@lunora/sql-store";import{postgresDialect as s,mysqlDialect as c}from"./packem_shared/mysqlDialect-DitNAlpV.mjs";import{buildMysqlExec as i,buildPgExec as a}from"./packem_shared/buildMysqlExec-DriYb1l9.mjs";const o=({engine:e,exec:t,...r})=>l({...r,dialect:e==="postgres"?s:c,exec:t}),p=(e,t)=>o({...t,engine:"postgres",exec:a(e)}),g=(e,t)=>o({...t,engine:"mysql",exec:i(e)});export{i as buildMysqlExec,a as buildPgExec,o as createHyperdriveGlobalCtxDb,g as createMysqlGlobalCtxDb,p as createPostgresGlobalCtxDb,c as mysqlDialect,s as postgresDialect};
package/dist/index.d.mts CHANGED
@@ -1,165 +1,148 @@
1
+ import { H as HyperdriveLike, a as HyperdriveConnection, M as Mysql2Like, S as SqlClient, N as NodePgLike, P as PostgresJsLike } from "./packem_shared/types.d-DE1NYxyA.mjs";
1
2
  /**
2
- * Public types for `@lunora/hyperdrive`.
3
- *
4
- * Hyperdrive points at a database **Lunora does not own**. Everything here is
5
- * deliberately structural (no hard dependency on `@cloudflare/workers-types` or
6
- * any SQL driver) so unit tests can pass plain-object doubles, exactly like the
7
- * `D1DatabaseLike` projection in `@lunora/d1`.
8
- *
9
- * The hard constraint, restated wherever this surface is used: Hyperdrive
10
- * queries are **non-deterministic** (forbidden in `query`/`mutation`, allowed
11
- * only in `action`s — see the `hyperdrive_outside_action` advisor lint), and
12
- * external writes are **invisible to Lunora live queries** — a subscription will
13
- * NOT re-run when an external Postgres/MySQL row changes.
14
- */
15
- /**
16
- * Structural projection of the Cloudflare `Hyperdrive` binding (`env.HYPERDRIVE`).
17
- *
18
- * Mirrors the fields of the real `Hyperdrive` from `@cloudflare/workers-types`
19
- * but stays structural so a unit test can pass a plain object. At runtime only
20
- * `connectionString` is needed to construct a driver; the discrete connection
21
- * parts are surfaced for drivers that prefer a config object over a DSN.
22
- */
23
- interface HyperdriveLike {
24
- /** A connection string Hyperdrive routes through its pooled, cached edge connection. */
3
+ * Surface a Cloudflare Hyperdrive binding as a connection ready to feed a
4
+ * user-supplied SQL driver.
5
+ *
6
+ * `@lunora/hyperdrive` deliberately **bundles no driver** `postgres`, `pg` and
7
+ * `mysql2` are heavy and the choice is the user's (they are `optional`
8
+ * `peerDependencies`, never `dependencies`). This factory's only job is to lift
9
+ * the binding's connection details out; the user constructs their own driver
10
+ * from `connectionString` and wraps it with one of the {@link fromPostgresJs} /
11
+ * {@link fromNodePg} / {@link fromMysql2} adapters to get a {@link SqlClient}.
12
+ * @example
13
+ * ```ts
14
+ * import { createHyperdrive, fromPostgresJs } from "@lunora/hyperdrive";
15
+ * import postgres from "postgres";
16
+ *
17
+ * // inside an action (never a query/mutation):
18
+ * const { connectionString } = createHyperdrive(env.HYPERDRIVE);
19
+ * ctx.sql = fromPostgresJs(postgres(connectionString));
20
+ * const rows = await ctx.sql.query("select id from users where org = $1", [orgId]);
21
+ * ```
22
+ * @remarks
23
+ * Hyperdrive talks to an **external** database Lunora has no visibility into.
24
+ * Queries through `ctx.sql` are non-deterministic (action-only — enforced by the
25
+ * `hyperdrive_outside_action` advisor lint) and external writes are NOT tracked
26
+ * by Lunora live queries: subscriptions will not re-run when external rows
27
+ * change. Use Hyperdrive to *integrate* an existing DB from an action; if you
28
+ * want that data to be reactive, write a projection of it into a `defineSchema`
29
+ * DO/D1 table.
30
+ * @param binding The `env.HYPERDRIVE` binding (or a structural double).
31
+ * @returns The raw `connectionString` plus the discrete connection parts.
32
+ */
33
+ declare const createHyperdrive: (binding: HyperdriveLike) => {
34
+ config: HyperdriveConnection;
25
35
  connectionString: string;
26
- /** Database name component of the connection. */
27
- database: string;
28
- /** Host Hyperdrive presents to the driver (the local proxy, not your origin DB). */
29
- host: string;
30
- /** Password component of the connection. */
31
- password: string;
32
- /** Port Hyperdrive presents to the driver. */
33
- port: number;
34
- /** User component of the connection. */
35
- user: string;
36
- }
36
+ };
37
37
  /**
38
- * The connection config surfaced by {@link import("./create-hyperdrive").createHyperdrive | createHyperdrive}: the raw
39
- * `connectionString` plus the discrete parts, ready to hand to a driver.
40
- */
41
- interface HyperdriveConnection {
42
- /** Database name. */
43
- database: string;
44
- /** Host (Hyperdrive's local proxy). */
45
- host: string;
46
- /** Password. */
47
- password: string;
48
- /** Port. */
49
- port: number;
50
- /** User. */
51
- user: string;
52
- }
38
+ * Wrap a `postgres` (postgres.js) client as a {@link SqlClient}.
39
+ *
40
+ * Uses the driver's `.unsafe(text, params)` escape hatch so the caller supplies
41
+ * a plain SQL string with `$1, $2, …` placeholders and a positional params
42
+ * array. postgres.js's `.unsafe` resolves to a row array.
43
+ */
44
+ declare const fromPostgresJs: (client: PostgresJsLike) => SqlClient;
45
+ /**
46
+ * Wrap a `pg` (node-postgres) `Client` or `Pool` as a {@link SqlClient}.
47
+ *
48
+ * node-postgres returns a result object whose `rows` field holds the row array.
49
+ */
50
+ declare const fromNodePg: (client: NodePgLike) => SqlClient;
53
51
  /**
54
- * The driver-agnostic SQL surface bound to `ctx.sql` on **`ActionCtx` only**.
55
- *
56
- * This is the exact type the generated ctx imports as
57
- * `import("@lunora/hyperdrive").SqlClient`. Keep the name and shape stable the
58
- * codegen ctx wiring (Phase 1) depends on it.
59
- *
60
- * It is intentionally minimal a single parameterised `query` — so it maps onto
61
- * `postgres` (postgres.js), `pg` (node-postgres) and `mysql2` alike via the
62
- * {@link import("./create-hyperdrive").fromPostgresJs | fromPostgresJs} /
63
- * {@link import("./create-hyperdrive").fromNodePg | fromNodePg} /
64
- * {@link import("./create-hyperdrive").fromMysql2 | fromMysql2} adapters. Use
65
- * positional placeholders that match your driver (`$1, $2` for Postgres, `?` for
66
- * MySQL); the package does not rewrite SQL.
67
- *
68
- * Reminder (also on the emitted JSDoc): non-deterministic, action-only,
69
- * non-reactive — writes here are not tracked by Lunora live queries.
70
- */
71
- interface SqlClient {
52
+ * Wrap a `mysql2/promise` connection or pool as a {@link SqlClient}.
53
+ *
54
+ * Use `?` placeholders (MySQL positional syntax). `mysql2`'s `execute` resolves
55
+ * to a `[rows, fields]` tuple; the adapter returns the first element. For a
56
+ * non-`SELECT` (DML), `mysql2` yields a `ResultSetHeader` object rather than a
57
+ * row array, so the adapter normalises that to `[]` — matching the empty-array
58
+ * contract the postgres.js / node-postgres adapters already honour.
59
+ */
60
+ declare const fromMysql2: (connection: Mysql2Like) => SqlClient;
61
+ /** How an external row maps to a Lunora document. */
62
+ interface ProjectOptions {
63
+ /**
64
+ * Column whose value becomes the Lunora `_id` (stringified). Defaults to `"id"`.
65
+ * With no `map`, this column is dropped from the document body (it lives on as
66
+ * `_id`); with a `map`, the mapper owns the body and `_id` is added from here.
67
+ */
68
+ idColumn?: string;
72
69
  /**
73
- * Run a parameterised SQL statement and return the result rows.
74
- * @param text SQL text with driver-native positional placeholders.
75
- * @param params Bound parameter values, positionally matched to `text`.
76
- * @returns The rows the statement produced (empty for non-`SELECT`s that
77
- * return no rows).
78
- */
79
- query: <Row = Record<string, unknown>>(text: string, params?: ReadonlyArray<unknown>) => Promise<Row[]>;
70
+ * Transform an external row into the stored document body. Omit for the default:
71
+ * every selected column except `idColumn` is copied verbatim. The returned object
72
+ * must not include `_id` it is set from `idColumn`.
73
+ */
74
+ map?: (row: Record<string, unknown>) => Record<string, unknown>;
80
75
  }
81
- /**
82
- * Structural projection of a `pg` (node-postgres) `Client`/`Pool`. Only the
83
- * `query` method `fromNodePg` calls is required, kept structural for testing.
84
- */
85
- interface NodePgLike {
86
- query: (text: string, params?: ReadonlyArray<unknown>) => Promise<{
87
- rows: unknown[];
88
- }>;
76
+ /** Options for {@link pullSourceRows}: the parameterised tenant query plus the row projection. */
77
+ interface PullSourceOptions extends ProjectOptions {
78
+ /** Bound parameter values, positionally matched to `query` (the tenant scope binds here). */
79
+ params?: ReadonlyArray<unknown>;
80
+ /** The full tenant-membership query with driver-native placeholders (`$1` / `?`). */
81
+ query: string;
89
82
  }
90
83
  /**
91
- * Structural projection of a `postgres` (postgres.js) tagged-template client.
92
- * The adapter uses the `.unsafe(text, params)` escape hatch so callers keep
93
- * full control of the parameter list.
94
- */
95
- interface PostgresJsLike {
96
- unsafe: (text: string, params?: ReadonlyArray<unknown>) => Promise<unknown>;
97
- }
84
+ * Project one external row to a Lunora document: lift `idColumn` to a stringified
85
+ * `_id`, then either apply `map` or copy every other column verbatim. Throws when
86
+ * the id column is missing/nullish so a misconfigured query fails loudly rather than
87
+ * materializing rows under an `"undefined"` id.
88
+ *
89
+ * Delegates to `@lunora/shard-engine`'s `liftSourceId` — the single id-lift the declarative
90
+ * `.source()` poll loop also uses — so the manual bridge and the codegen path can
91
+ * never diverge in their missing-id handling.
92
+ */
93
+ declare const projectSourceRow: (row: Record<string, unknown>, options?: ProjectOptions) => Record<string, unknown>;
98
94
  /**
99
- * Structural projection of a `mysql2/promise` connection/pool. `mysql2`'s
100
- * `execute` resolves to a `[rows, fields]` tuple; the adapter takes the first
101
- * element as the rows.
102
- */
103
- interface Mysql2Like {
104
- execute: (text: string, params?: ReadonlyArray<unknown>) => Promise<[unknown, unknown]>;
105
- }
95
+ * Run a parameterised tenant query against Hyperdrive and project every row to a
96
+ * Lunora document ready to hand to `materializeExternalRows`. Call this inside an
97
+ * **action** (where `ctx.sql` lives); pass the result to a mutation for the write.
98
+ */
99
+ declare const pullSourceRows: (sql: SqlClient, options: PullSourceOptions) => Promise<Record<string, unknown>[]>;
100
+ export { type HyperdriveConnection, type HyperdriveLike, type Mysql2Like, type NodePgLike, type PostgresJsLike, type ProjectOptions, type PullSourceOptions, type SqlClient,
106
101
  /**
107
- * Surface a Cloudflare Hyperdrive binding as a connection ready to feed a
108
- * user-supplied SQL driver.
109
- *
110
- * `@lunora/hyperdrive` deliberately **bundles no driver** `postgres`, `pg` and
111
- * `mysql2` are heavy and the choice is the user's (they are `optional`
112
- * `peerDependencies`, never `dependencies`). This factory's only job is to lift
113
- * the binding's connection details out; the user constructs their own driver
114
- * from `connectionString` and wraps it with one of the {@link fromPostgresJs} /
115
- * {@link fromNodePg} / {@link fromMysql2} adapters to get a {@link SqlClient}.
116
- * @example
117
- * ```ts
118
- * import { createHyperdrive, fromPostgresJs } from "@lunora/hyperdrive";
119
- * import postgres from "postgres";
120
- *
121
- * // inside an action (never a query/mutation):
122
- * const { connectionString } = createHyperdrive(env.HYPERDRIVE);
123
- * ctx.sql = fromPostgresJs(postgres(connectionString));
124
- * const rows = await ctx.sql.query("select id from users where org = $1", [orgId]);
125
- * ```
126
- * @remarks
127
- * Hyperdrive talks to an **external** database Lunora has no visibility into.
128
- * Queries through `ctx.sql` are non-deterministic (action-only — enforced by the
129
- * `hyperdrive_outside_action` advisor lint) and external writes are NOT tracked
130
- * by Lunora live queries: subscriptions will not re-run when external rows
131
- * change. Use Hyperdrive to *integrate* an existing DB from an action; if you
132
- * want that data to be reactive, write a projection of it into a `defineSchema`
133
- * DO/D1 table.
134
- * @param binding The `env.HYPERDRIVE` binding (or a structural double).
135
- * @returns The raw `connectionString` plus the discrete connection parts.
136
- */
137
- declare const createHyperdrive: (binding: HyperdriveLike) => {
138
- config: HyperdriveConnection;
139
- connectionString: string;
140
- };
102
+ * `@lunora/hyperdrive` bring-your-own Postgres/MySQL for Lunora via Cloudflare
103
+ * Hyperdrive.
104
+ *
105
+ * Surfaces a Hyperdrive binding's connection string and a driver-agnostic
106
+ * {@link import("./types").SqlClient | SqlClient} bound to `ctx.sql` on
107
+ * **`ActionCtx` only**. External SQL is non-deterministic (action-only) and
108
+ * non-reactive (live queries do not track external writes) integrate an
109
+ * existing DB, do not replace the Lunora data layer. See the README and
110
+ * {@link import("./create-hyperdrive").createHyperdrive | createHyperdrive} JSDoc.
111
+ */
112
+ createHyperdrive,
141
113
  /**
142
- * Wrap a `postgres` (postgres.js) client as a {@link SqlClient}.
143
- *
144
- * Uses the driver's `.unsafe(text, params)` escape hatch so the caller supplies
145
- * a plain SQL string with `$1, $2, …` placeholders and a positional params
146
- * array. postgres.js's `.unsafe` resolves to a row array.
147
- */
148
- declare const fromPostgresJs: (client: PostgresJsLike) => SqlClient;
114
+ * `@lunora/hyperdrive` bring-your-own Postgres/MySQL for Lunora via Cloudflare
115
+ * Hyperdrive.
116
+ *
117
+ * Surfaces a Hyperdrive binding's connection string and a driver-agnostic
118
+ * {@link import("./types").SqlClient | SqlClient} bound to `ctx.sql` on
119
+ * **`ActionCtx` only**. External SQL is non-deterministic (action-only) and
120
+ * non-reactive (live queries do not track external writes) integrate an
121
+ * existing DB, do not replace the Lunora data layer. See the README and
122
+ * {@link import("./create-hyperdrive").createHyperdrive | createHyperdrive} JSDoc.
123
+ */
124
+ fromMysql2,
149
125
  /**
150
- * Wrap a `pg` (node-postgres) `Client` or `Pool` as a {@link SqlClient}.
151
- *
152
- * node-postgres returns a result object whose `rows` field holds the row array.
153
- */
154
- declare const fromNodePg: (client: NodePgLike) => SqlClient;
126
+ * `@lunora/hyperdrive` bring-your-own Postgres/MySQL for Lunora via Cloudflare
127
+ * Hyperdrive.
128
+ *
129
+ * Surfaces a Hyperdrive binding's connection string and a driver-agnostic
130
+ * {@link import("./types").SqlClient | SqlClient} bound to `ctx.sql` on
131
+ * **`ActionCtx` only**. External SQL is non-deterministic (action-only) and
132
+ * non-reactive (live queries do not track external writes) — integrate an
133
+ * existing DB, do not replace the Lunora data layer. See the README and
134
+ * {@link import("./create-hyperdrive").createHyperdrive | createHyperdrive} JSDoc.
135
+ */
136
+ fromNodePg,
155
137
  /**
156
- * Wrap a `mysql2/promise` connection or pool as a {@link SqlClient}.
157
- *
158
- * Use `?` placeholders (MySQL positional syntax). `mysql2`'s `execute` resolves
159
- * to a `[rows, fields]` tuple; the adapter returns the first element. For a
160
- * non-`SELECT` (DML), `mysql2` yields a `ResultSetHeader` object rather than a
161
- * row array, so the adapter normalises that to `[]` — matching the empty-array
162
- * contract the postgres.js / node-postgres adapters already honour.
163
- */
164
- declare const fromMysql2: (connection: Mysql2Like) => SqlClient;
165
- export { type HyperdriveConnection, type HyperdriveLike, type Mysql2Like, type NodePgLike, type PostgresJsLike, type SqlClient, createHyperdrive, fromMysql2, fromNodePg, fromPostgresJs };
138
+ * `@lunora/hyperdrive` bring-your-own Postgres/MySQL for Lunora via Cloudflare
139
+ * Hyperdrive.
140
+ *
141
+ * Surfaces a Hyperdrive binding's connection string and a driver-agnostic
142
+ * {@link import("./types").SqlClient | SqlClient} bound to `ctx.sql` on
143
+ * **`ActionCtx` only**. External SQL is non-deterministic (action-only) and
144
+ * non-reactive (live queries do not track external writes) — integrate an
145
+ * existing DB, do not replace the Lunora data layer. See the README and
146
+ * {@link import("./create-hyperdrive").createHyperdrive | createHyperdrive} JSDoc.
147
+ */
148
+ fromPostgresJs, projectSourceRow, pullSourceRows };