@supalive/core 1.1.0 → 1.2.1
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/README.md +28 -0
- package/dist/db-ClCicssQ.js +28 -0
- package/dist/db-ClCicssQ.js.map +1 -0
- package/dist/{index-DouKwYL6.d.ts → index-DJYvJYR4.d.ts} +214 -9
- package/dist/index-DJYvJYR4.d.ts.map +1 -0
- package/dist/{mysql-Bxurg_PH.d.ts → mysql-53W9lRh9.d.ts} +8 -3
- package/dist/mysql-53W9lRh9.d.ts.map +1 -0
- package/dist/{mysql-bvnjYWvZ.js → mysql-C0mysDQ_.js} +57 -25
- package/dist/mysql-C0mysDQ_.js.map +1 -0
- package/dist/{overlap-checker-Ct_HP_iB.js → overlap-checker-ClJC0nxW.js} +52 -4
- package/dist/overlap-checker-ClJC0nxW.js.map +1 -0
- package/dist/{postgres-Ck-xt72U.d.ts → postgres-7d6R9P7w.d.ts} +8 -3
- package/dist/postgres-7d6R9P7w.d.ts.map +1 -0
- package/dist/{postgres-B8u1YN8X.js → postgres-SvdXfb0w.js} +55 -22
- package/dist/postgres-SvdXfb0w.js.map +1 -0
- package/dist/{procedure-DX87tyef.js → procedure-Ze1GE-N9.js} +33 -2
- package/dist/procedure-Ze1GE-N9.js.map +1 -0
- package/dist/{query-Bh0RNxDz.js → query-CrbJ_W0W.js} +21 -1
- package/dist/query-CrbJ_W0W.js.map +1 -0
- package/dist/{realtime_db-DOCgqbwi.js → realtime_db-BtwBABDY.js} +76 -51
- package/dist/realtime_db-BtwBABDY.js.map +1 -0
- package/dist/{router-DlTYWpop.js → router-CiWYeWUR.js} +8 -2
- package/dist/router-CiWYeWUR.js.map +1 -0
- package/dist/src/client/index.d.ts +1 -1
- package/dist/src/client/index.js +44 -5
- package/dist/src/client/index.js.map +1 -1
- package/dist/src/exports/mysql.d.ts +1 -1
- package/dist/src/exports/mysql.js +1 -1
- package/dist/src/exports/postgres.d.ts +1 -1
- package/dist/src/exports/postgres.js +1 -1
- package/dist/src/exports/procedure.d.ts +2 -2
- package/dist/src/exports/procedure.js +4 -4
- package/dist/src/exports/schema-sql.d.ts +36 -2
- package/dist/src/exports/schema-sql.d.ts.map +1 -1
- package/dist/src/exports/schema-sql.js +74 -19
- package/dist/src/exports/schema-sql.js.map +1 -1
- package/dist/src/exports/server.d.ts +65 -17
- package/dist/src/exports/server.d.ts.map +1 -1
- package/dist/src/exports/server.js +724 -63
- package/dist/src/exports/server.js.map +1 -1
- package/dist/src/exports/subscription-manager-worker-entry.js +8 -5
- package/dist/src/exports/subscription-manager-worker-entry.js.map +1 -1
- package/dist/src/exports/types.d.ts +3 -3
- package/dist/src/exports/types.js +1 -1
- package/dist/{subscription-worker-CqoWp6zB.js → subscription-worker-B2XtjFWY.js} +307 -69
- package/dist/subscription-worker-B2XtjFWY.js.map +1 -0
- package/dist/{types_db-DXj_l9n-.js → types_db-CTRm_awX.js} +7 -2
- package/dist/types_db-CTRm_awX.js.map +1 -0
- package/dist/types_server-wW3ZgE7l.d.ts +420 -0
- package/dist/types_server-wW3ZgE7l.d.ts.map +1 -0
- package/package.json +5 -4
- package/dist/index-CaWMDqq0.d.ts +0 -1754
- package/dist/index-CaWMDqq0.d.ts.map +0 -1
- package/dist/index-DouKwYL6.d.ts.map +0 -1
- package/dist/mysql-Bxurg_PH.d.ts.map +0 -1
- package/dist/mysql-Cxd4Uq5p.d.ts +0 -104
- package/dist/mysql-Cxd4Uq5p.d.ts.map +0 -1
- package/dist/mysql-bvnjYWvZ.js.map +0 -1
- package/dist/overlap-checker-Ct_HP_iB.js.map +0 -1
- package/dist/postgres-B8u1YN8X.js.map +0 -1
- package/dist/postgres-CfT_aDx3.d.ts +0 -108
- package/dist/postgres-CfT_aDx3.d.ts.map +0 -1
- package/dist/postgres-Ck-xt72U.d.ts.map +0 -1
- package/dist/procedure-DX87tyef.js.map +0 -1
- package/dist/query-Bh0RNxDz.js.map +0 -1
- package/dist/realtime_db-DOCgqbwi.js.map +0 -1
- package/dist/router-DlTYWpop.js.map +0 -1
- package/dist/src/exports/codegen.d.ts +0 -38
- package/dist/src/exports/codegen.d.ts.map +0 -1
- package/dist/src/exports/codegen.js +0 -134
- package/dist/src/exports/codegen.js.map +0 -1
- package/dist/subscription-worker-CqoWp6zB.js.map +0 -1
- package/dist/subscription-worker-PtmJWEj1.js +0 -511
- package/dist/subscription-worker-PtmJWEj1.js.map +0 -1
- package/dist/subscription-worker-pahX0zxg.js +0 -511
- package/dist/subscription-worker-pahX0zxg.js.map +0 -1
- package/dist/types_db-DXj_l9n-.js.map +0 -1
- package/dist/types_server-BW1ys_SK.d.ts +0 -216
- package/dist/types_server-BW1ys_SK.d.ts.map +0 -1
- package/dist/types_server-Dpsi0wpG.d.ts +0 -216
- package/dist/types_server-Dpsi0wpG.d.ts.map +0 -1
- package/dist/types_server-DzrIccyO.d.ts +0 -216
- package/dist/types_server-DzrIccyO.d.ts.map +0 -1
- package/dist/types_server-TFo6SWDH.d.ts +0 -216
- package/dist/types_server-TFo6SWDH.d.ts.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Cn as schemaRegistry, En as trackSchema, yn as SchemaDefinition } from "../../index-DJYvJYR4.js";
|
|
2
2
|
|
|
3
3
|
//#region src/db/schema-sql.d.ts
|
|
4
4
|
type SqlDialect = "postgres" | "mysql";
|
|
@@ -11,8 +11,42 @@ interface GenerateSchemaSqlOptions {
|
|
|
11
11
|
dialect?: SqlDialect;
|
|
12
12
|
ifNotExists?: boolean;
|
|
13
13
|
header?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Prepend the framework-owned core tables (`commit_logs`, `metadata`) and
|
|
16
|
+
* their indexes so the generated SQL fully describes the database. Default
|
|
17
|
+
* true. Non-table core bootstrap (sequences, seed rows) is handled at
|
|
18
|
+
* runtime by `initCore`, not emitted here.
|
|
19
|
+
*/
|
|
20
|
+
includeCoreTables?: boolean;
|
|
14
21
|
}
|
|
15
22
|
declare function generateSchemaSql(schemas?: Map<string, SchemaDefinition<string, any, any>> | SchemaDefinition<string, any, any>[], options?: GenerateSchemaSqlOptions): string;
|
|
16
23
|
//#endregion
|
|
17
|
-
|
|
24
|
+
//#region src/db/core_tables.d.ts
|
|
25
|
+
/**
|
|
26
|
+
* DDL for the core, framework-owned database objects that every Supalive
|
|
27
|
+
* database must have alongside the user's own tables:
|
|
28
|
+
*
|
|
29
|
+
* - `commit_logs` — the append-only OCC change log (+ its lookup indexes).
|
|
30
|
+
* - `metadata` — the small key/value table holding the OCC watermarks
|
|
31
|
+
* (`latest_committed_ts`, `min_retained_ts`) and the
|
|
32
|
+
* core schema version (`core_version`).
|
|
33
|
+
* - `global_commit_ts` — the monotonic commit-timestamp source: a SEQUENCE on
|
|
34
|
+
* Postgres, a single-row `BIGINT` counter table on MySQL.
|
|
35
|
+
*
|
|
36
|
+
* These are all pure schema (DDL), so they belong in the generated `schema.sql`
|
|
37
|
+
* (see {@link generateSchemaSql}, which prepends them by default) and get
|
|
38
|
+
* migrated ahead of runtime by your normal migration pipeline — a single
|
|
39
|
+
* generated file fully describes the database.
|
|
40
|
+
*
|
|
41
|
+
* Data seeding (the `metadata` rows and the MySQL counter's initial `0`) and
|
|
42
|
+
* any runtime-only schema changes live in `initCore` — see
|
|
43
|
+
* {@link file://./init_db.ts}.
|
|
44
|
+
*/
|
|
45
|
+
interface CoreTablesSqlOptions {
|
|
46
|
+
/** Emit `IF NOT EXISTS` on `CREATE TABLE`/`CREATE INDEX`/`CREATE SEQUENCE`. Default true. */
|
|
47
|
+
ifNotExists?: boolean;
|
|
48
|
+
}
|
|
49
|
+
declare function coreTablesSql(dialect?: SqlDialect, options?: CoreTablesSqlOptions): string[];
|
|
50
|
+
//#endregion
|
|
51
|
+
export { type CoreTablesSqlOptions, type GenerateSchemaSqlOptions, type SchemaToCreateTableOptions, type SqlDialect, coreTablesSql, generateSchemaSql, schemaRegistry, schemaToCreateTable, trackSchema };
|
|
18
52
|
//# sourceMappingURL=schema-sql.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-sql.d.ts","names":[],"sources":["../../../src/db/schema-sql.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"schema-sql.d.ts","names":[],"sources":["../../../src/db/schema-sql.ts","../../../src/db/core_tables.ts"],"mappings":";;;KAMY,UAAA;AAAA,UAsKK,0BAAA;EACb,OAAA,GAAU,UAAU;EACpB,WAAA;AAAA;AAAA,iBAGY,mBAAA,CACZ,MAAA,EAAQ,gBAAA,oBACR,OAAA,GAAU,0BAA0B;AAAA,UAoFvB,wBAAA;EACb,OAAA,GAAU,UAAU;EACpB,WAAA;EACA,MAAA;EAzF+B;;;;;;EAgG/B,iBAAA;AAAA;AAAA,iBAGY,iBAAA,CACZ,OAAA,GAAU,GAAA,SAAY,gBAAA,sBAAsC,gBAAA,sBAC5D,OAAA,GAAU,wBAAA;;;;;AAhRd;;;;AAAsB;AAsKtB;;;;;;;;AAEe;AAGf;;;;UC1JiB,oBAAA;ED2Jb;ECzJA,WAAW;AAAA;AAAA,iBAGC,aAAA,CACZ,OAAA,GAAS,UAAA,EACT,OAAA,GAAU,oBAAoB"}
|
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
import { r as unwrapZodType } from "../../codec-BHAmGEIQ.js";
|
|
2
2
|
import { o as trackSchema, r as schemaRegistry } from "../../schema-Dd7u0A1L.js";
|
|
3
3
|
import { z as z$1 } from "zod";
|
|
4
|
+
//#region src/db/core_tables.ts
|
|
5
|
+
function coreTablesSql(dialect = "postgres", options) {
|
|
6
|
+
const ifNotExists = options?.ifNotExists ?? true;
|
|
7
|
+
const t = ifNotExists ? "IF NOT EXISTS " : "";
|
|
8
|
+
const i = ifNotExists ? "IF NOT EXISTS " : "";
|
|
9
|
+
if (dialect === "mysql") return [
|
|
10
|
+
`CREATE TABLE ${t}global_commit_ts (\n id BIGINT NOT NULL\n) ENGINE=InnoDB;`,
|
|
11
|
+
`CREATE TABLE ${t}commit_logs (\n id BINARY(16) NOT NULL,\n ts BIGINT NOT NULL,\n table_id BINARY(16) NOT NULL,\n data LONGBLOB NOT NULL,\n PRIMARY KEY (ts, table_id, id),\n INDEX commit_logs_by_table_and_id (table_id, id, ts)\n) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;`,
|
|
12
|
+
`CREATE TABLE ${t}metadata (\n meta_key VARCHAR(255) PRIMARY KEY,\n meta_value BIGINT NOT NULL\n) ENGINE=InnoDB;`
|
|
13
|
+
];
|
|
14
|
+
return [
|
|
15
|
+
`CREATE SEQUENCE ${t}global_commit_ts START 1 INCREMENT 1 NO CYCLE;`,
|
|
16
|
+
`CREATE TABLE ${t}commit_logs (\n id BYTEA NOT NULL,\n ts BIGINT NOT NULL,\n table_id BYTEA NOT NULL,\n data BYTEA NOT NULL,\n PRIMARY KEY (ts, table_id, id)\n);`,
|
|
17
|
+
`CREATE INDEX ${i}commit_logs_by_table_and_id ON commit_logs (table_id, id, ts);`,
|
|
18
|
+
`CREATE INDEX ${i}commit_logs_by_table_ts_and_id ON commit_logs (table_id, ts, id);`,
|
|
19
|
+
`CREATE TABLE ${t}metadata (\n meta_key TEXT PRIMARY KEY,\n meta_value BIGINT NOT NULL\n);`
|
|
20
|
+
];
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
4
23
|
//#region src/db/schema-sql.ts
|
|
5
24
|
function getFieldMeta(field) {
|
|
6
25
|
const f = field;
|
|
@@ -15,10 +34,10 @@ function getFieldMeta(field) {
|
|
|
15
34
|
function getStringMaxLength(field) {
|
|
16
35
|
const unwrapped = unwrapZodType(field);
|
|
17
36
|
if (!(unwrapped instanceof z$1.ZodString)) return void 0;
|
|
18
|
-
const checks = unwrapped.
|
|
37
|
+
const checks = unwrapped.def?.checks ?? [];
|
|
19
38
|
let maxLength;
|
|
20
39
|
for (const check of checks) {
|
|
21
|
-
const c = check.def ?? check;
|
|
40
|
+
const c = check._zod?.def ?? check.def ?? check;
|
|
22
41
|
if (c.check === "length_equals" || c.check === "size_equals") {
|
|
23
42
|
const len = c.length ?? c.size;
|
|
24
43
|
if (typeof len === "number") maxLength = maxLength === void 0 ? len : Math.min(maxLength, len);
|
|
@@ -41,7 +60,7 @@ function getDefaultFromZod(field) {
|
|
|
41
60
|
try {
|
|
42
61
|
const f = field;
|
|
43
62
|
let value = f.defaultValue;
|
|
44
|
-
if (value === void 0) value = f.
|
|
63
|
+
if (value === void 0) value = f.def?.defaultValue;
|
|
45
64
|
if (typeof value === "function") value = value();
|
|
46
65
|
if (value === void 0) return void 0;
|
|
47
66
|
if (value === null) return "NULL";
|
|
@@ -55,14 +74,10 @@ function getDefaultFromZod(field) {
|
|
|
55
74
|
}
|
|
56
75
|
}
|
|
57
76
|
const VARCHAR_MAX = 65535;
|
|
58
|
-
function
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (typeof meta[dialectKey] === "string") return meta[dialectKey];
|
|
63
|
-
if (typeof meta.sql_type === "string") return meta.sql_type;
|
|
64
|
-
}
|
|
65
|
-
const unwrapped = unwrapZodType(field);
|
|
77
|
+
function jsonType(dialect) {
|
|
78
|
+
return dialect === "mysql" ? "JSON" : "JSONB";
|
|
79
|
+
}
|
|
80
|
+
function getScalarSqlType(unwrapped, field, dialect) {
|
|
66
81
|
if (unwrapped instanceof z$1.ZodString) {
|
|
67
82
|
const maxLen = getStringMaxLength(field);
|
|
68
83
|
if (maxLen !== void 0 && maxLen <= VARCHAR_MAX) return `VARCHAR(${maxLen})`;
|
|
@@ -72,10 +87,33 @@ function getSqlType(field, dialect) {
|
|
|
72
87
|
if (unwrapped instanceof z$1.ZodBoolean) return dialect === "mysql" ? "TINYINT(1)" : "BOOLEAN";
|
|
73
88
|
if (unwrapped instanceof z$1.ZodDate) return dialect === "mysql" ? "DATETIME(3)" : "TIMESTAMPTZ";
|
|
74
89
|
if (unwrapped instanceof z$1.ZodBigInt) return "BIGINT";
|
|
75
|
-
if (unwrapped instanceof z$1.ZodArray) return dialect === "mysql" ? "JSON" : "JSONB";
|
|
76
|
-
if (unwrapped instanceof z$1.ZodObject || unwrapped instanceof z$1.ZodRecord) return dialect === "mysql" ? "JSON" : "JSONB";
|
|
77
90
|
if (unwrapped instanceof z$1.ZodEnum) return "TEXT";
|
|
78
|
-
|
|
91
|
+
}
|
|
92
|
+
function getArrayElement(arr) {
|
|
93
|
+
return arr.element ?? arr.def?.element ?? arr.def?.type;
|
|
94
|
+
}
|
|
95
|
+
function getArraySqlType(arr, dialect) {
|
|
96
|
+
if (dialect === "mysql") return "JSON";
|
|
97
|
+
const rawElement = getArrayElement(arr);
|
|
98
|
+
const element = unwrapZodType(rawElement);
|
|
99
|
+
const elementMeta = getFieldMeta(rawElement);
|
|
100
|
+
if (elementMeta) {
|
|
101
|
+
if (typeof elementMeta.pgType === "string") return `${elementMeta.pgType}[]`;
|
|
102
|
+
}
|
|
103
|
+
const scalar = getScalarSqlType(element, rawElement, dialect);
|
|
104
|
+
if (scalar !== void 0) return `${scalar}[]`;
|
|
105
|
+
return "JSONB";
|
|
106
|
+
}
|
|
107
|
+
function getSqlType(field, dialect) {
|
|
108
|
+
const meta = getFieldMeta(field);
|
|
109
|
+
if (meta) {
|
|
110
|
+
const dialectKey = dialect === "mysql" ? "mysqlType" : "pgType";
|
|
111
|
+
if (typeof meta[dialectKey] === "string") return meta[dialectKey];
|
|
112
|
+
}
|
|
113
|
+
const unwrapped = unwrapZodType(field);
|
|
114
|
+
if (unwrapped instanceof z$1.ZodArray) return getArraySqlType(unwrapped, dialect);
|
|
115
|
+
if (unwrapped instanceof z$1.ZodObject || unwrapped instanceof z$1.ZodRecord) return jsonType(dialect);
|
|
116
|
+
return getScalarSqlType(unwrapped, field, dialect) ?? "TEXT";
|
|
79
117
|
}
|
|
80
118
|
function isPrimaryKey(field) {
|
|
81
119
|
return getFieldMeta(field)?.primaryKey === true;
|
|
@@ -122,15 +160,27 @@ function formatDeclarativeIndex(idx, tableName, columns) {
|
|
|
122
160
|
if (idx.where) sql += ` WHERE ${idx.where}`;
|
|
123
161
|
return sql + ";";
|
|
124
162
|
}
|
|
125
|
-
function schemaIndexes(schema) {
|
|
126
|
-
|
|
163
|
+
function schemaIndexes(schema, options) {
|
|
164
|
+
const out = (schema.indexes ?? []).map((idx) => {
|
|
127
165
|
if (typeof idx === "string") return idx;
|
|
128
166
|
return formatDeclarativeIndex(idx, schema.table, schema.columns);
|
|
129
167
|
});
|
|
168
|
+
const commitCol = schema.columns["commitTs"] ?? "commit_ts";
|
|
169
|
+
const autoName = `${schema.table}_commit_ts_idx`;
|
|
170
|
+
if (!(schema.indexes ?? []).some((idx) => {
|
|
171
|
+
if (typeof idx === "string") return idx.includes(autoName);
|
|
172
|
+
if (idx.name === autoName) return true;
|
|
173
|
+
return idx.columns.length === 1 && (idx.columns[0] === "commitTs" || idx.columns[0] === commitCol);
|
|
174
|
+
})) {
|
|
175
|
+
const ifNot = options?.ifNotExists ?? true ? "IF NOT EXISTS " : "";
|
|
176
|
+
out.push(`CREATE INDEX ${ifNot}${autoName} ON ${schema.table} (${commitCol});`);
|
|
177
|
+
}
|
|
178
|
+
return out;
|
|
130
179
|
}
|
|
131
180
|
function generateSchemaSql(schemas, options) {
|
|
132
181
|
const dialect = options?.dialect ?? "postgres";
|
|
133
182
|
const header = options?.header ?? true;
|
|
183
|
+
const includeCoreTables = options?.includeCoreTables ?? true;
|
|
134
184
|
let list;
|
|
135
185
|
if (schemas instanceof Map) list = [...schemas.values()];
|
|
136
186
|
else if (Array.isArray(schemas)) list = schemas;
|
|
@@ -141,7 +191,12 @@ function generateSchemaSql(schemas, options) {
|
|
|
141
191
|
if (header) {
|
|
142
192
|
parts.push("-- Generated by Supalive Schema Generator");
|
|
143
193
|
parts.push(`-- Dialect: ${dialect}`);
|
|
144
|
-
parts.push(`-- Tables: ${list.length}`);
|
|
194
|
+
parts.push(`-- Tables: ${list.length}${includeCoreTables ? " (+ core)" : ""}`);
|
|
195
|
+
parts.push("");
|
|
196
|
+
}
|
|
197
|
+
if (includeCoreTables) {
|
|
198
|
+
parts.push("-- Core tables (framework-owned)");
|
|
199
|
+
for (const stmt of coreTablesSql(dialect, { ifNotExists: options?.ifNotExists })) parts.push(stmt);
|
|
145
200
|
parts.push("");
|
|
146
201
|
}
|
|
147
202
|
for (const schema of list) {
|
|
@@ -149,13 +204,13 @@ function generateSchemaSql(schemas, options) {
|
|
|
149
204
|
...options,
|
|
150
205
|
dialect
|
|
151
206
|
}));
|
|
152
|
-
const indexStmts = schemaIndexes(schema);
|
|
207
|
+
const indexStmts = schemaIndexes(schema, { ifNotExists: options?.ifNotExists });
|
|
153
208
|
for (const stmt of indexStmts) parts.push(stmt);
|
|
154
209
|
parts.push("");
|
|
155
210
|
}
|
|
156
211
|
return parts.join("\n");
|
|
157
212
|
}
|
|
158
213
|
//#endregion
|
|
159
|
-
export { generateSchemaSql, schemaRegistry, schemaToCreateTable, trackSchema };
|
|
214
|
+
export { coreTablesSql, generateSchemaSql, schemaRegistry, schemaToCreateTable, trackSchema };
|
|
160
215
|
|
|
161
216
|
//# sourceMappingURL=schema-sql.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-sql.js","names":["z"],"sources":["../../../src/db/schema-sql.ts"],"sourcesContent":["import { z, ZodRawShape } from \"zod\";\nimport { SchemaDefinition, schemaRegistry } from \"./schema\";\nimport type { DeclarativeIndex } from \"./schema\";\nimport { unwrapZodType } from \"./codec\";\n\nexport type SqlDialect = \"postgres\" | \"mysql\";\n\nfunction getFieldMeta(field: unknown): Record<string, unknown> | undefined {\n const f = field as any;\n const meta = typeof f.meta === \"function\" ? f.meta() : undefined;\n if (meta) return meta;\n\n const unwrapped = unwrapZodType(field);\n if (unwrapped !== field) {\n const innerMeta = typeof (unwrapped as any).meta === \"function\" ? (unwrapped as any).meta() : undefined;\n if (innerMeta) return innerMeta;\n }\n\n return undefined;\n}\n\nfunction getStringMaxLength(field: unknown): number | undefined {\n const unwrapped = unwrapZodType(field);\n if (!(unwrapped instanceof z.ZodString)) return undefined;\n\n const checks: any[] = (unwrapped as any)._def?.checks ?? [];\n let maxLength: number | undefined;\n\n for (const check of checks) {\n const c = check.def ?? check;\n if (c.check === \"length_equals\" || c.check === \"size_equals\") {\n const len = c.length ?? c.size;\n if (typeof len === \"number\") maxLength = maxLength === undefined ? len : Math.min(maxLength, len);\n }\n if (c.check === \"max_length\" || c.check === \"max_size\") {\n const len = c.maximum ?? c.max;\n if (typeof len === \"number\") maxLength = maxLength === undefined ? len : Math.min(maxLength, len);\n }\n }\n\n return maxLength;\n}\n\nfunction isOptional(field: unknown): boolean {\n return (\n field instanceof z.ZodOptional ||\n field instanceof z.ZodNullable\n );\n}\n\nfunction escapeSQLString(s: string): string {\n return `'${s.replace(/'/g, \"''\")}'`;\n}\n\nfunction getDefaultFromZod(field: unknown): string | undefined {\n if (!(field instanceof z.ZodDefault)) return undefined;\n\n try {\n const f = field as any;\n let value = f.defaultValue;\n if (value === undefined) value = f._def?.defaultValue;\n if (typeof value === \"function\") value = value();\n\n if (value === undefined) return undefined;\n if (value === null) return \"NULL\";\n if (typeof value === \"string\") return escapeSQLString(value);\n if (typeof value === \"number\") return value.toString();\n if (typeof value === \"boolean\") return value ? \"TRUE\" : \"FALSE\";\n if (typeof value === \"bigint\") return value.toString();\n\n return undefined;\n } catch {\n return undefined;\n }\n}\n\nconst VARCHAR_MAX = 65535;\n\nfunction getSqlType(field: unknown, dialect: SqlDialect): string {\n const meta = getFieldMeta(field);\n if (meta) {\n const dialectKey = dialect === \"mysql\" ? \"mysqlType\" : \"pgType\";\n if (typeof meta[dialectKey] === \"string\") return meta[dialectKey] as string;\n if (typeof meta.sql_type === \"string\") return meta.sql_type;\n }\n\n const unwrapped = unwrapZodType(field);\n\n if (unwrapped instanceof z.ZodString) {\n const maxLen = getStringMaxLength(field);\n if (maxLen !== undefined && maxLen <= VARCHAR_MAX) return `VARCHAR(${maxLen})`;\n return \"TEXT\";\n }\n\n if (unwrapped instanceof z.ZodNumber) return \"BIGINT\";\n\n if (unwrapped instanceof z.ZodBoolean) {\n return dialect === \"mysql\" ? \"TINYINT(1)\" : \"BOOLEAN\";\n }\n\n if (unwrapped instanceof z.ZodDate) {\n return dialect === \"mysql\" ? \"DATETIME(3)\" : \"TIMESTAMPTZ\";\n }\n\n if (unwrapped instanceof z.ZodBigInt) return \"BIGINT\";\n\n if (unwrapped instanceof z.ZodArray) {\n return dialect === \"mysql\" ? \"JSON\" : \"JSONB\";\n }\n\n if (unwrapped instanceof z.ZodObject || unwrapped instanceof z.ZodRecord) {\n return dialect === \"mysql\" ? \"JSON\" : \"JSONB\";\n }\n\n if (unwrapped instanceof z.ZodEnum) return \"TEXT\";\n\n return \"TEXT\";\n}\n\nfunction isPrimaryKey(field: unknown): boolean {\n const meta = getFieldMeta(field);\n return meta?.primaryKey === true;\n}\n\nfunction getDefaultValue(field: unknown): string | undefined {\n const meta = getFieldMeta(field);\n if (meta && typeof meta.defaultValue === \"string\") {\n return meta.defaultValue;\n }\n\n return getDefaultFromZod(field);\n}\n\nexport interface SchemaToCreateTableOptions {\n dialect?: SqlDialect;\n ifNotExists?: boolean;\n}\n\nexport function schemaToCreateTable(\n schema: SchemaDefinition<string, any, any>,\n options?: SchemaToCreateTableOptions,\n): string {\n const dialect = options?.dialect ?? \"postgres\";\n const ifNotExists = options?.ifNotExists ?? true;\n\n const tableName = schema.table;\n const shape = schema.schema.shape;\n const columns: Record<string, string> = schema.columns;\n\n const userKeys = Object.keys(shape).filter(k => k !== \"id\" && k !== \"commitTs\");\n const orderedKeys = [\"id\", ...userKeys, \"commitTs\"];\n\n const lines: string[] = [];\n\n for (const fieldName of orderedKeys) {\n const field = shape[fieldName];\n if (!field) continue;\n\n const colName = columns[fieldName] ?? fieldName;\n if (!colName) continue;\n\n const sqlType = getSqlType(field, dialect);\n const notNull = !isOptional(field);\n const pk = isPrimaryKey(field);\n const defaultVal = fieldName === \"commitTs\" ? \"0\" : getDefaultValue(field);\n\n let line = ` ${colName} ${sqlType}`;\n if (notNull) line += \" NOT NULL\";\n if (pk) line += \" PRIMARY KEY\";\n if (defaultVal !== undefined) line += ` DEFAULT ${defaultVal}`;\n\n lines.push(line);\n }\n\n const ifNot = ifNotExists ? \"IF NOT EXISTS \" : \"\";\n return `CREATE TABLE ${ifNot}${tableName} (\\n${lines.join(\",\\n\")}\\n);`;\n}\n\nexport function formatDeclarativeIndex(\n idx: DeclarativeIndex,\n tableName: string,\n columns: Record<string, string>,\n): string {\n const colNames = idx.columns.map(c => columns[c] ?? c).join(\", \");\n let sql = `CREATE ${idx.unique ? \"UNIQUE \" : \"\"}INDEX IF NOT EXISTS ${idx.name} ON ${tableName}`;\n if (idx.type) sql += ` USING ${idx.type}`;\n sql += ` (${colNames})`;\n if (idx.where) sql += ` WHERE ${idx.where}`;\n return sql + \";\";\n}\n\nexport function schemaIndexes(\n schema: SchemaDefinition<string, any, any>,\n): string[] {\n return (schema.indexes ?? []).map(idx => {\n if (typeof idx === \"string\") return idx;\n return formatDeclarativeIndex(idx, schema.table, schema.columns);\n });\n}\n\nexport interface GenerateSchemaSqlOptions {\n dialect?: SqlDialect;\n ifNotExists?: boolean;\n header?: boolean;\n}\n\nexport function generateSchemaSql(\n schemas?: Map<string, SchemaDefinition<string, any, any>> | SchemaDefinition<string, any, any>[],\n options?: GenerateSchemaSqlOptions,\n): string {\n const dialect = options?.dialect ?? \"postgres\";\n const header = options?.header ?? true;\n\n let list: SchemaDefinition<string, any, any>[];\n\n if (schemas instanceof Map) {\n list = [...schemas.values()];\n } else if (Array.isArray(schemas)) {\n list = schemas;\n } else {\n list = [...schemaRegistry.values()];\n }\n\n list = list.filter(s => s?.table);\n list.sort((a, b) => a.table.localeCompare(b.table));\n\n const parts: string[] = [];\n\n if (header) {\n parts.push(\"-- Generated by Supalive Schema Generator\");\n parts.push(`-- Dialect: ${dialect}`);\n parts.push(`-- Tables: ${list.length}`);\n parts.push(\"\");\n }\n\n for (const schema of list) {\n parts.push(schemaToCreateTable(schema, { ...options, dialect }));\n const indexStmts = schemaIndexes(schema);\n for (const stmt of indexStmts) {\n parts.push(stmt);\n }\n parts.push(\"\");\n }\n\n return parts.join(\"\\n\");\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"schema-sql.js","names":["z"],"sources":["../../../src/db/core_tables.ts","../../../src/db/schema-sql.ts"],"sourcesContent":["import type { SqlDialect } from \"./schema-sql\";\n\n/**\n * DDL for the core, framework-owned database objects that every Supalive\n * database must have alongside the user's own tables:\n *\n * - `commit_logs` — the append-only OCC change log (+ its lookup indexes).\n * - `metadata` — the small key/value table holding the OCC watermarks\n * (`latest_committed_ts`, `min_retained_ts`) and the\n * core schema version (`core_version`).\n * - `global_commit_ts` — the monotonic commit-timestamp source: a SEQUENCE on\n * Postgres, a single-row `BIGINT` counter table on MySQL.\n *\n * These are all pure schema (DDL), so they belong in the generated `schema.sql`\n * (see {@link generateSchemaSql}, which prepends them by default) and get\n * migrated ahead of runtime by your normal migration pipeline — a single\n * generated file fully describes the database.\n *\n * Data seeding (the `metadata` rows and the MySQL counter's initial `0`) and\n * any runtime-only schema changes live in `initCore` — see\n * {@link file://./init_db.ts}.\n */\n\nexport interface CoreTablesSqlOptions {\n /** Emit `IF NOT EXISTS` on `CREATE TABLE`/`CREATE INDEX`/`CREATE SEQUENCE`. Default true. */\n ifNotExists?: boolean;\n}\n\nexport function coreTablesSql(\n dialect: SqlDialect = \"postgres\",\n options?: CoreTablesSqlOptions,\n): string[] {\n const ifNotExists = options?.ifNotExists ?? true;\n const t = ifNotExists ? \"IF NOT EXISTS \" : \"\";\n const i = ifNotExists ? \"IF NOT EXISTS \" : \"\";\n\n if (dialect === \"mysql\") {\n return [\n // MySQL has no sequences: a single-row counter table advanced via\n // LAST_INSERT_ID (see MySqlDatabase.getNextTimestamp). Seeded to 0\n // by initCore.\n `CREATE TABLE ${t}global_commit_ts (\\n` +\n ` id BIGINT NOT NULL\\n` +\n `) ENGINE=InnoDB;`,\n `CREATE TABLE ${t}commit_logs (\\n` +\n ` id BINARY(16) NOT NULL,\\n` +\n ` ts BIGINT NOT NULL,\\n` +\n ` table_id BINARY(16) NOT NULL,\\n` +\n ` data LONGBLOB NOT NULL,\\n` +\n ` PRIMARY KEY (ts, table_id, id),\\n` +\n ` INDEX commit_logs_by_table_and_id (table_id, id, ts)\\n` +\n `) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;`,\n `CREATE TABLE ${t}metadata (\\n` +\n ` meta_key VARCHAR(255) PRIMARY KEY,\\n` +\n ` meta_value BIGINT NOT NULL\\n` +\n `) ENGINE=InnoDB;`,\n ];\n }\n\n return [\n // Monotonic OCC commit-timestamp source (see PgDatabase.getNextTimestamp).\n `CREATE SEQUENCE ${t}global_commit_ts START 1 INCREMENT 1 NO CYCLE;`,\n `CREATE TABLE ${t}commit_logs (\\n` +\n ` id BYTEA NOT NULL,\\n` +\n ` ts BIGINT NOT NULL,\\n` +\n ` table_id BYTEA NOT NULL,\\n` +\n ` data BYTEA NOT NULL,\\n` +\n ` PRIMARY KEY (ts, table_id, id)\\n` +\n `);`,\n `CREATE INDEX ${i}commit_logs_by_table_and_id ON commit_logs (table_id, id, ts);`,\n `CREATE INDEX ${i}commit_logs_by_table_ts_and_id ON commit_logs (table_id, ts, id);`,\n `CREATE TABLE ${t}metadata (\\n` +\n ` meta_key TEXT PRIMARY KEY,\\n` +\n ` meta_value BIGINT NOT NULL\\n` +\n `);`,\n ];\n}\n","import { z } from \"zod\";\nimport { SchemaDefinition, schemaRegistry } from \"./schema\";\nimport type { DeclarativeIndex } from \"./schema\";\nimport { unwrapZodType } from \"./codec\";\nimport { coreTablesSql } from \"./core_tables\";\n\nexport type SqlDialect = \"postgres\" | \"mysql\";\n\nfunction getFieldMeta(field: unknown): Record<string, unknown> | undefined {\n const f = field as any;\n const meta = typeof f.meta === \"function\" ? f.meta() : undefined;\n if (meta) return meta;\n\n const unwrapped = unwrapZodType(field);\n if (unwrapped !== field) {\n const innerMeta = typeof (unwrapped as any).meta === \"function\" ? (unwrapped as any).meta() : undefined;\n if (innerMeta) return innerMeta;\n }\n\n return undefined;\n}\n\nfunction getStringMaxLength(field: unknown): number | undefined {\n const unwrapped = unwrapZodType(field);\n if (!(unwrapped instanceof z.ZodString)) return undefined;\n\n const checks: any[] = (unwrapped as any).def?.checks ?? [];\n let maxLength: number | undefined;\n\n for (const check of checks) {\n const c = check._zod?.def ?? check.def ?? check;\n if (c.check === \"length_equals\" || c.check === \"size_equals\") {\n const len = c.length ?? c.size;\n if (typeof len === \"number\") maxLength = maxLength === undefined ? len : Math.min(maxLength, len);\n }\n if (c.check === \"max_length\" || c.check === \"max_size\") {\n const len = c.maximum ?? c.max;\n if (typeof len === \"number\") maxLength = maxLength === undefined ? len : Math.min(maxLength, len);\n }\n }\n\n return maxLength;\n}\n\nfunction isOptional(field: unknown): boolean {\n return (\n field instanceof z.ZodOptional ||\n field instanceof z.ZodNullable\n );\n}\n\nfunction escapeSQLString(s: string): string {\n return `'${s.replace(/'/g, \"''\")}'`;\n}\n\nfunction getDefaultFromZod(field: unknown): string | undefined {\n if (!(field instanceof z.ZodDefault)) return undefined;\n\n try {\n const f = field as any;\n let value = f.defaultValue;\n if (value === undefined) value = f.def?.defaultValue;\n if (typeof value === \"function\") value = value();\n\n if (value === undefined) return undefined;\n if (value === null) return \"NULL\";\n if (typeof value === \"string\") return escapeSQLString(value);\n if (typeof value === \"number\") return value.toString();\n if (typeof value === \"boolean\") return value ? \"TRUE\" : \"FALSE\";\n if (typeof value === \"bigint\") return value.toString();\n\n return undefined;\n } catch {\n return undefined;\n }\n}\n\nconst VARCHAR_MAX = 65535;\n\nfunction jsonType(dialect: SqlDialect): string {\n return dialect === \"mysql\" ? \"JSON\" : \"JSONB\";\n}\n\n// Maps a scalar (non-collection) Zod type to a native SQL column type.\n// Returns undefined for types that don't have a simple scalar mapping\n// (objects, records, nested arrays, unknown types), so callers can decide\n// how to fall back. `field` is the original (possibly wrapped) node used to\n// read length constraints; `unwrapped` is the underlying scalar type.\nfunction getScalarSqlType(unwrapped: unknown, field: unknown, dialect: SqlDialect): string | undefined {\n if (unwrapped instanceof z.ZodString) {\n const maxLen = getStringMaxLength(field);\n if (maxLen !== undefined && maxLen <= VARCHAR_MAX) return `VARCHAR(${maxLen})`;\n return \"TEXT\";\n }\n\n if (unwrapped instanceof z.ZodNumber) return \"BIGINT\";\n\n if (unwrapped instanceof z.ZodBoolean) {\n return dialect === \"mysql\" ? \"TINYINT(1)\" : \"BOOLEAN\";\n }\n\n if (unwrapped instanceof z.ZodDate) {\n return dialect === \"mysql\" ? \"DATETIME(3)\" : \"TIMESTAMPTZ\";\n }\n\n if (unwrapped instanceof z.ZodBigInt) return \"BIGINT\";\n\n if (unwrapped instanceof z.ZodEnum) return \"TEXT\";\n\n return undefined;\n}\n\nfunction getArrayElement(arr: z.ZodArray): unknown {\n return arr.element ?? arr.def?.element ?? arr.def?.type;\n}\n\n// Resolves the SQL type for an array field. MySQL has no native array column\n// type, so arrays are stored as JSON. Postgres supports native arrays of\n// scalar types (e.g. TEXT[], BIGINT[]); arrays of objects/records or nested\n// arrays fall back to JSONB.\nfunction getArraySqlType(arr: z.ZodArray, dialect: SqlDialect): string {\n if (dialect === \"mysql\") return \"JSON\";\n\n const rawElement = getArrayElement(arr);\n const element = unwrapZodType(rawElement);\n\n // Honor an explicit SQL type declared on the element's meta.\n const elementMeta = getFieldMeta(rawElement);\n if (elementMeta) {\n if (typeof elementMeta.pgType === \"string\") return `${elementMeta.pgType}[]`;\n }\n\n const scalar = getScalarSqlType(element, rawElement, dialect);\n if (scalar !== undefined) return `${scalar}[]`;\n\n return \"JSONB\";\n}\n\nfunction getSqlType(field: unknown, dialect: SqlDialect): string {\n const meta = getFieldMeta(field);\n if (meta) {\n const dialectKey = dialect === \"mysql\" ? \"mysqlType\" : \"pgType\";\n if (typeof meta[dialectKey] === \"string\") return meta[dialectKey] as string;\n }\n\n const unwrapped = unwrapZodType(field);\n\n if (unwrapped instanceof z.ZodArray) {\n return getArraySqlType(unwrapped, dialect);\n }\n\n if (unwrapped instanceof z.ZodObject || unwrapped instanceof z.ZodRecord) {\n return jsonType(dialect);\n }\n\n return getScalarSqlType(unwrapped, field, dialect) ?? \"TEXT\";\n}\n\nfunction isPrimaryKey(field: unknown): boolean {\n const meta = getFieldMeta(field);\n return meta?.primaryKey === true;\n}\n\nfunction getDefaultValue(field: unknown): string | undefined {\n const meta = getFieldMeta(field);\n if (meta && typeof meta.defaultValue === \"string\") {\n return meta.defaultValue;\n }\n\n return getDefaultFromZod(field);\n}\n\nexport interface SchemaToCreateTableOptions {\n dialect?: SqlDialect;\n ifNotExists?: boolean;\n}\n\nexport function schemaToCreateTable(\n schema: SchemaDefinition<string, any, any>,\n options?: SchemaToCreateTableOptions,\n): string {\n const dialect = options?.dialect ?? \"postgres\";\n const ifNotExists = options?.ifNotExists ?? true;\n\n const tableName = schema.table;\n const shape = schema.schema.shape;\n const columns: Record<string, string> = schema.columns;\n\n const userKeys = Object.keys(shape).filter(k => k !== \"id\" && k !== \"commitTs\");\n const orderedKeys = [\"id\", ...userKeys, \"commitTs\"];\n\n const lines: string[] = [];\n\n for (const fieldName of orderedKeys) {\n const field = shape[fieldName];\n if (!field) continue;\n\n const colName = columns[fieldName] ?? fieldName;\n if (!colName) continue;\n\n const sqlType = getSqlType(field, dialect);\n const notNull = !isOptional(field);\n const pk = isPrimaryKey(field);\n const defaultVal = fieldName === \"commitTs\" ? \"0\" : getDefaultValue(field);\n\n let line = ` ${colName} ${sqlType}`;\n if (notNull) line += \" NOT NULL\";\n if (pk) line += \" PRIMARY KEY\";\n if (defaultVal !== undefined) line += ` DEFAULT ${defaultVal}`;\n\n lines.push(line);\n }\n\n const ifNot = ifNotExists ? \"IF NOT EXISTS \" : \"\";\n return `CREATE TABLE ${ifNot}${tableName} (\\n${lines.join(\",\\n\")}\\n);`;\n}\n\nexport function formatDeclarativeIndex(\n idx: DeclarativeIndex,\n tableName: string,\n columns: Record<string, string>,\n): string {\n const colNames = idx.columns.map(c => columns[c] ?? c).join(\", \");\n let sql = `CREATE ${idx.unique ? \"UNIQUE \" : \"\"}INDEX IF NOT EXISTS ${idx.name} ON ${tableName}`;\n if (idx.type) sql += ` USING ${idx.type}`;\n sql += ` (${colNames})`;\n if (idx.where) sql += ` WHERE ${idx.where}`;\n return sql + \";\";\n}\n\nexport interface SchemaIndexesOptions {\n /** Emit `IF NOT EXISTS` on the auto-generated commit_ts index. Default true. */\n ifNotExists?: boolean;\n}\n\nexport function schemaIndexes(\n schema: SchemaDefinition<string, any, any>,\n options?: SchemaIndexesOptions,\n): string[] {\n const out = (schema.indexes ?? []).map(idx => {\n if (typeof idx === \"string\") return idx;\n return formatDeclarativeIndex(idx, schema.table, schema.columns);\n });\n\n // Every table has a `commit_ts` column (OCC) that is otherwise unindexed.\n // Auto-add an index on it unless the user already declared one covering\n // the commit_ts field or one with the same generated name.\n const commitCol = schema.columns[\"commitTs\"] ?? \"commit_ts\";\n const autoName = `${schema.table}_commit_ts_idx`;\n const alreadyDeclared = (schema.indexes ?? []).some(idx => {\n if (typeof idx === \"string\") return idx.includes(autoName);\n if (idx.name === autoName) return true;\n return idx.columns.length === 1 &&\n (idx.columns[0] === \"commitTs\" || idx.columns[0] === commitCol);\n });\n if (!alreadyDeclared) {\n const ifNot = (options?.ifNotExists ?? true) ? \"IF NOT EXISTS \" : \"\";\n out.push(`CREATE INDEX ${ifNot}${autoName} ON ${schema.table} (${commitCol});`);\n }\n\n return out;\n}\n\nexport interface GenerateSchemaSqlOptions {\n dialect?: SqlDialect;\n ifNotExists?: boolean;\n header?: boolean;\n /**\n * Prepend the framework-owned core tables (`commit_logs`, `metadata`) and\n * their indexes so the generated SQL fully describes the database. Default\n * true. Non-table core bootstrap (sequences, seed rows) is handled at\n * runtime by `initCore`, not emitted here.\n */\n includeCoreTables?: boolean;\n}\n\nexport function generateSchemaSql(\n schemas?: Map<string, SchemaDefinition<string, any, any>> | SchemaDefinition<string, any, any>[],\n options?: GenerateSchemaSqlOptions,\n): string {\n const dialect = options?.dialect ?? \"postgres\";\n const header = options?.header ?? true;\n const includeCoreTables = options?.includeCoreTables ?? true;\n\n let list: SchemaDefinition<string, any, any>[];\n\n if (schemas instanceof Map) {\n list = [...schemas.values()];\n } else if (Array.isArray(schemas)) {\n list = schemas;\n } else {\n list = [...schemaRegistry.values()];\n }\n\n list = list.filter(s => s?.table);\n list.sort((a, b) => a.table.localeCompare(b.table));\n\n const parts: string[] = [];\n\n if (header) {\n parts.push(\"-- Generated by Supalive Schema Generator\");\n parts.push(`-- Dialect: ${dialect}`);\n parts.push(`-- Tables: ${list.length}${includeCoreTables ? \" (+ core)\" : \"\"}`);\n parts.push(\"\");\n }\n\n if (includeCoreTables) {\n parts.push(\"-- Core tables (framework-owned)\");\n for (const stmt of coreTablesSql(dialect, { ifNotExists: options?.ifNotExists })) {\n parts.push(stmt);\n }\n parts.push(\"\");\n }\n\n for (const schema of list) {\n parts.push(schemaToCreateTable(schema, { ...options, dialect }));\n const indexStmts = schemaIndexes(schema, { ifNotExists: options?.ifNotExists });\n for (const stmt of indexStmts) {\n parts.push(stmt);\n }\n parts.push(\"\");\n }\n\n return parts.join(\"\\n\");\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as MySqlDatabase } from "../../mysql-
|
|
3
|
-
import { t as PgDatabase } from "../../postgres-
|
|
4
|
-
import {
|
|
1
|
+
import { At as SupaliveDb, Bn as InvalidateWritesetParamsSchema, E as Context, Gn as UnregisterSubscriptionParams, Hn as RegisterSubscriptionParams, Jn as UnregisterSubscriptionsParams, Kn as UnregisterSubscriptionParamsSchema, Ln as CacheLayer, On as Database, Qn as UpdateSubscriptionReadSetResult, Rn as AffectedSubscription, Un as RegisterSubscriptionParamsSchema, Vn as InvalidateWritesetResult, Wn as RegisterSubscriptionResult, Xn as UpdateSubscriptionReadSetParams, Yn as UnregisterSubscriptionsResult, Zn as UpdateSubscriptionReadSetParamsSchema, qn as UnregisterSubscriptionResult, rt as Router, zn as InvalidateWritesetParams } from "../../index-DJYvJYR4.js";
|
|
2
|
+
import { t as MySqlDatabase } from "../../mysql-53W9lRh9.js";
|
|
3
|
+
import { t as PgDatabase } from "../../postgres-7d6R9P7w.js";
|
|
4
|
+
import { A as ScheduledJobDef, C as EnqueueOptions, D as QStashScheduler, E as JobScheduler, O as QStashSchedulerOptions, S as DevSchedulerOptions, T as JobClient, b as UpstashConfig, f as DatabaseConfig, k as ScheduleHandle, u as SubId, v as SubscriptionManagerConfig, w as IncomingJobRequest, x as DevScheduler, y as SupaliveServerConfig } from "../../types_server-wW3ZgE7l.js";
|
|
5
5
|
import pino, { Level } from "pino";
|
|
6
6
|
import Redis$1 from "ioredis";
|
|
7
7
|
|
|
@@ -19,6 +19,12 @@ declare class SupaliveWebSocketServer<TContext extends Context> {
|
|
|
19
19
|
private db;
|
|
20
20
|
private contextRegistry;
|
|
21
21
|
private router?;
|
|
22
|
+
private retentionWatermark;
|
|
23
|
+
private oneShotDeps;
|
|
24
|
+
private scheduler?;
|
|
25
|
+
private jobPath;
|
|
26
|
+
private jobClient?;
|
|
27
|
+
private rpcHandler?;
|
|
22
28
|
private sessions;
|
|
23
29
|
private serverSubscriptions;
|
|
24
30
|
private subManagerClient;
|
|
@@ -40,6 +46,28 @@ declare class SupaliveWebSocketServer<TContext extends Context> {
|
|
|
40
46
|
private clearSessionTimers;
|
|
41
47
|
registerRouter(router: Router<any, TContext>): void;
|
|
42
48
|
start(): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* Reconcile every registered recurring (cron) job with the scheduler. Safe
|
|
51
|
+
* to call more than once. No-op when no scheduler is configured or the router
|
|
52
|
+
* declares no cron jobs. Runs after the HTTP listener is up so the endpoints
|
|
53
|
+
* the scheduler registers are already reachable.
|
|
54
|
+
*/
|
|
55
|
+
private syncJobSchedules;
|
|
56
|
+
/** Absolute URL the scheduler POSTs to for a given job name. */
|
|
57
|
+
endpointFor(name: string): string;
|
|
58
|
+
/**
|
|
59
|
+
* Enqueue a precise, one-shot run of a job (e.g. "expire this record at
|
|
60
|
+
* exactly `expiresAt`"). Returns a handle whose `id` can be passed to
|
|
61
|
+
* {@link cancelJob}. Requires a configured scheduler.
|
|
62
|
+
*/
|
|
63
|
+
scheduleJob(name: string, body: unknown, opts?: EnqueueOptions): Promise<ScheduleHandle>;
|
|
64
|
+
/** Cancel a one-shot previously created by {@link scheduleJob}. */
|
|
65
|
+
cancelJob(handleId: string): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* The app-facing {@link JobClient} — hand it to your service layer so
|
|
68
|
+
* procedures can schedule/cancel one-shots without reaching for the server.
|
|
69
|
+
*/
|
|
70
|
+
getJobClient(): JobClient | undefined;
|
|
43
71
|
stop(): Promise<void>;
|
|
44
72
|
getStats(): {
|
|
45
73
|
instanceId: string;
|
|
@@ -48,6 +76,12 @@ declare class SupaliveWebSocketServer<TContext extends Context> {
|
|
|
48
76
|
activeSubscriptions: number;
|
|
49
77
|
};
|
|
50
78
|
getInstanceId(): string;
|
|
79
|
+
/**
|
|
80
|
+
* Plain-HTTP entrypoint (non-WS). Serves a liveness probe and the job
|
|
81
|
+
* webhook: `POST {jobPath}/<jobName>`. Every job POST is authenticated by the
|
|
82
|
+
* configured scheduler before the (server-only) job handler runs.
|
|
83
|
+
*/
|
|
84
|
+
private handleHttpRequest;
|
|
51
85
|
private setupWebSocketHandlers;
|
|
52
86
|
private handleConnection;
|
|
53
87
|
private handleMessage;
|
|
@@ -113,18 +147,6 @@ declare class SupaliveWebSocketServer<TContext extends Context> {
|
|
|
113
147
|
private publishRecomputeRace;
|
|
114
148
|
private reexecuteAffectedQuery;
|
|
115
149
|
private executeLiveQuery;
|
|
116
|
-
/**
|
|
117
|
-
* Resolve the segmentation key used in the subId/cacheKey hash for a
|
|
118
|
-
* query subscription. Priority:
|
|
119
|
-
*
|
|
120
|
-
* 1. Procedure-level `queryIdentity` override:
|
|
121
|
-
* - `false` → identity = `ANONYMOUS_IDENTITY` (cache shared across users)
|
|
122
|
-
* - `string` → that literal
|
|
123
|
-
* - `function` → ctx + input → string | null | undefined
|
|
124
|
-
* 2. `config.getUserId(serverCtx)` → falls back to ANONYMOUS_IDENTITY if it
|
|
125
|
-
* returns null/undefined or isn't configured.
|
|
126
|
-
*/
|
|
127
|
-
private resolveQueryIdentity;
|
|
128
150
|
private sendMessage;
|
|
129
151
|
private sendMessageRaw;
|
|
130
152
|
private sendError;
|
|
@@ -173,6 +195,10 @@ declare class SubscriptionManager {
|
|
|
173
195
|
start(): Promise<void>;
|
|
174
196
|
stop(): Promise<void>;
|
|
175
197
|
private pruneCommitLogs;
|
|
198
|
+
/** Fan a watermark value out to every worker's in-memory copy. Worker 0 (the
|
|
199
|
+
* pruner/seeder) already has it, but re-sending is harmless — {@link
|
|
200
|
+
* SubscriptionWorker.setRetentionWatermark} is monotonic. */
|
|
201
|
+
private broadcastRetentionWatermark;
|
|
176
202
|
workerCount(): number;
|
|
177
203
|
workerIndexFor(subId: string): number;
|
|
178
204
|
private workerFor;
|
|
@@ -303,6 +329,28 @@ declare class SubManagerClient {
|
|
|
303
329
|
}
|
|
304
330
|
//#endregion
|
|
305
331
|
//#region src/db/init_db.d.ts
|
|
332
|
+
/**
|
|
333
|
+
* Current core runtime-bootstrap version. Bump this whenever core needs a new
|
|
334
|
+
* runtime database operation — a data seed, a backfill, or a schema change that
|
|
335
|
+
* must be applied directly at runtime rather than through the migration
|
|
336
|
+
* pipeline. Each increment adds a case to `Database.coreMigrationStatements`.
|
|
337
|
+
*
|
|
338
|
+
* The core *schema* (the `commit_logs`/`metadata` tables and the
|
|
339
|
+
* `global_commit_ts` sequence/counter) is NOT versioned here — it comes from
|
|
340
|
+
* the generated schema (`coreTablesSql` / `generateSchemaSql`), which must be
|
|
341
|
+
* applied to the database BEFORE `initCore` runs.
|
|
342
|
+
*/
|
|
343
|
+
declare const CORE_VERSION = 1n;
|
|
344
|
+
/**
|
|
345
|
+
* Bring the core runtime state up to {@link CORE_VERSION}. Idempotent and safe
|
|
346
|
+
* to call from every process at startup: a lock-free version read short-circuits
|
|
347
|
+
* the common "already current" case, and the actual migration runs under a
|
|
348
|
+
* cross-process lock with a re-check so only one process applies it.
|
|
349
|
+
*
|
|
350
|
+
* Assumes the core schema already exists (apply the generated schema first);
|
|
351
|
+
* the `metadata` table is where the version and seed rows live.
|
|
352
|
+
*/
|
|
353
|
+
declare function initCore(db: Database): Promise<void>;
|
|
306
354
|
/**
|
|
307
355
|
* Default and env override for the per-statement DB timeout. PG enforces
|
|
308
356
|
* this via `statement_timeout` (server cancels), MySQL via the per-query
|
|
@@ -365,5 +413,5 @@ declare function generateSubscriptionId(procedure: string, input: unknown | stri
|
|
|
365
413
|
*/
|
|
366
414
|
declare function generateCacheKey(queryName: string, input: unknown | string, queryIdentity: string): Promise<string>;
|
|
367
415
|
//#endregion
|
|
368
|
-
export { ANONYMOUS_IDENTITY, type AffectedSubscription, CacheLayer, DB_QUERY_TIMEOUT_MS, InitCacheLayerOptions, InitDbOptions, type InvalidateWritesetParams, InvalidateWritesetParamsSchema, type InvalidateWritesetResult, type RegisterSubscriptionParams, RegisterSubscriptionParamsSchema, type RegisterSubscriptionResult, type SubId, SubManagerClient, SubscriptionManager, SupaliveWebSocketServer, type UnregisterSubscriptionParams, UnregisterSubscriptionParamsSchema, type UnregisterSubscriptionResult, type UpdateSubscriptionReadSetParams, UpdateSubscriptionReadSetParamsSchema, type UpdateSubscriptionReadSetResult, appInstanceId, bootstrapDbTypes, createDatabase, generateCacheKey, generateSubscriptionId, getHashOf, initCacheLayer, initDatabase, isProduction, logLevelOf, logger, serializeMapValue };
|
|
416
|
+
export { ANONYMOUS_IDENTITY, type AffectedSubscription, CORE_VERSION, CacheLayer, DB_QUERY_TIMEOUT_MS, DevScheduler, type DevSchedulerOptions, type EnqueueOptions, type IncomingJobRequest, InitCacheLayerOptions, InitDbOptions, type InvalidateWritesetParams, InvalidateWritesetParamsSchema, type InvalidateWritesetResult, JobClient, type JobScheduler, QStashScheduler, type QStashSchedulerOptions, type RegisterSubscriptionParams, RegisterSubscriptionParamsSchema, type RegisterSubscriptionResult, type ScheduleHandle, type ScheduledJobDef, type SubId, SubManagerClient, SubscriptionManager, SupaliveWebSocketServer, type UnregisterSubscriptionParams, UnregisterSubscriptionParamsSchema, type UnregisterSubscriptionResult, type UpdateSubscriptionReadSetParams, UpdateSubscriptionReadSetParamsSchema, type UpdateSubscriptionReadSetResult, appInstanceId, bootstrapDbTypes, createDatabase, generateCacheKey, generateSubscriptionId, getHashOf, initCacheLayer, initCore, initDatabase, isProduction, logLevelOf, logger, serializeMapValue };
|
|
369
417
|
//# sourceMappingURL=server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","names":[],"sources":["../../../src/server/supalive-server.ts","../../../src/logger.ts","../../../src/server/subscription-manager.ts","../../../src/server/subscription-manager-client.ts","../../../src/db/init_db.ts","../../../src/server/sub_hash.ts"],"mappings":";;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"server.d.ts","names":[],"sources":["../../../src/server/supalive-server.ts","../../../src/logger.ts","../../../src/server/subscription-manager.ts","../../../src/server/subscription-manager-client.ts","../../../src/db/init_db.ts","../../../src/server/sub_hash.ts"],"mappings":"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"}
|