@shapio/local 0.5.9 → 0.5.11
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/{advisoryLocks-ajVNBhfa.js → advisoryLocks-DGbxw3_E.js} +13 -13
- package/dist/advisoryLocks-DGbxw3_E.js.map +1 -0
- package/dist/errors-nQvt9bs7.js.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/{migrator-CO5sXosL.js → migrator-BfVtncOo.js} +269 -148
- package/dist/migrator-BfVtncOo.js.map +1 -0
- package/package.json +4 -4
- package/dist/advisoryLocks-ajVNBhfa.js.map +0 -1
- package/dist/migrator-CO5sXosL.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as mysqlDriverOf, r as sqliteDriverOf } from "./advisoryLocks-
|
|
1
|
+
import { a as mysqlDriverOf, r as sqliteDriverOf } from "./advisoryLocks-DGbxw3_E.js";
|
|
2
2
|
import { sql } from "kysely";
|
|
3
3
|
import { Migrator } from "kysely/migration";
|
|
4
4
|
//#region \0rolldown/runtime.js
|
|
@@ -15,14 +15,14 @@ var __exportAll = (all, no_symbols) => {
|
|
|
15
15
|
//#endregion
|
|
16
16
|
//#region ../../apps/api/src/db/migrations/20261001120000_create_platform_tables.ts
|
|
17
17
|
var _20261001120000_create_platform_tables_exports = /* @__PURE__ */ __exportAll({
|
|
18
|
-
down: () => down$
|
|
19
|
-
up: () => up$
|
|
18
|
+
down: () => down$37,
|
|
19
|
+
up: () => up$37
|
|
20
20
|
});
|
|
21
21
|
/**
|
|
22
22
|
* Foundation tables shared by every package: durable versions, the job queue, the transactional outbox
|
|
23
23
|
* and the audit log. Statuses are text with CHECK constraints so new states need only a constraint change.
|
|
24
24
|
*/
|
|
25
|
-
const up$
|
|
25
|
+
const up$37 = async (db) => {
|
|
26
26
|
await db.schema.createTable("system_versions").addColumn("id", "boolean", (col) => col.primaryKey().defaultTo(true).check(sql`id`)).addColumn("schema_version", "integer", (col) => col.notNull().defaultTo(0)).addColumn("permissions_version", "integer", (col) => col.notNull().defaultTo(0)).addColumn("updated_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).execute();
|
|
27
27
|
await sql`insert into system_versions default values`.execute(db);
|
|
28
28
|
await db.schema.createTable("jobs").addColumn("id", "uuid", (col) => col.primaryKey().defaultTo(sql`gen_random_uuid()`)).addColumn("type", "text", (col) => col.notNull()).addColumn("payload", "jsonb", (col) => col.notNull().defaultTo(sql`'{}'::jsonb`)).addColumn("status", "text", (col) => col.notNull().defaultTo("pending").check(sql`status in ('pending', 'running', 'succeeded', 'dead')`)).addColumn("priority", "integer", (col) => col.notNull().defaultTo(0)).addColumn("run_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).addColumn("attempts", "integer", (col) => col.notNull().defaultTo(0)).addColumn("max_attempts", "integer", (col) => col.notNull().defaultTo(10).check(sql`max_attempts > 0`)).addColumn("idempotency_key", "text").addColumn("locked_by", "text").addColumn("locked_until", "timestamptz").addColumn("checkpoint", "jsonb").addColumn("result", "jsonb").addColumn("last_error", "text").addColumn("created_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).addColumn("updated_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).addColumn("finished_at", "timestamptz").execute();
|
|
@@ -44,7 +44,7 @@ const up$34 = async (db) => {
|
|
|
44
44
|
"occurred_at desc"
|
|
45
45
|
]).execute();
|
|
46
46
|
};
|
|
47
|
-
const down$
|
|
47
|
+
const down$37 = async (db) => {
|
|
48
48
|
await db.schema.dropTable("audit_events").execute();
|
|
49
49
|
await db.schema.dropTable("outbox_events").execute();
|
|
50
50
|
await db.schema.dropTable("jobs").execute();
|
|
@@ -53,8 +53,8 @@ const down$34 = async (db) => {
|
|
|
53
53
|
//#endregion
|
|
54
54
|
//#region ../../apps/api/src/db/migrations/20261001130000_create_admin_identity.ts
|
|
55
55
|
var _20261001130000_create_admin_identity_exports = /* @__PURE__ */ __exportAll({
|
|
56
|
-
down: () => down$
|
|
57
|
-
up: () => up$
|
|
56
|
+
down: () => down$36,
|
|
57
|
+
up: () => up$36
|
|
58
58
|
});
|
|
59
59
|
/**
|
|
60
60
|
* Admin identity (package B, ADR 0005): admin users, roles and their permission grants, server-side
|
|
@@ -63,7 +63,7 @@ var _20261001130000_create_admin_identity_exports = /* @__PURE__ */ __exportAll(
|
|
|
63
63
|
*/
|
|
64
64
|
const withTimestamps$3 = (table) => table.addColumn("created_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).addColumn("updated_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`));
|
|
65
65
|
const uuidPrimaryKey$3 = (table) => table.addColumn("id", "uuid", (col) => col.primaryKey().defaultTo(sql`gen_random_uuid()`));
|
|
66
|
-
const up$
|
|
66
|
+
const up$36 = async (db) => {
|
|
67
67
|
await withTimestamps$3(uuidPrimaryKey$3(db.schema.createTable("admin_users")).addColumn("email", "text", (col) => col.notNull().unique()).addColumn("name", "text", (col) => col.notNull().defaultTo("")).addColumn("password_hash", "text", (col) => col.notNull()).addColumn("status", "text", (col) => col.notNull().defaultTo("active").check(sql`status in ('active', 'disabled')`)).addColumn("last_login_at", "timestamptz").addColumn("password_changed_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`))).execute();
|
|
68
68
|
await withTimestamps$3(uuidPrimaryKey$3(db.schema.createTable("admin_roles")).addColumn("key", "text", (col) => col.notNull().unique().check(sql`key ~ '^[a-z][a-z0-9-]{0,62}$'`)).addColumn("name", "text", (col) => col.notNull()).addColumn("description", "text", (col) => col.notNull().defaultTo("")).addColumn("kind", "text", (col) => col.notNull().defaultTo("admin").check(sql`kind in ('admin', 'delivery')`)).addColumn("is_system", "boolean", (col) => col.notNull().defaultTo(false)).addColumn("version", "integer", (col) => col.notNull().defaultTo(1))).execute();
|
|
69
69
|
await withTimestamps$3(uuidPrimaryKey$3(db.schema.createTable("admin_role_permissions")).addColumn("role_id", "uuid", (col) => col.notNull().references("admin_roles.id").onDelete("cascade")).addColumn("action", "text", (col) => col.notNull()).addColumn("model_id", "text").addColumn("condition", "text", (col) => col.check(sql`condition in ('ownedByPrincipal')`)).addColumn("field_ids", sql`text[]`).addUniqueConstraint("admin_role_permissions_grant_uq", [
|
|
@@ -83,7 +83,7 @@ const up$33 = async (db) => {
|
|
|
83
83
|
await withTimestamps$3(uuidPrimaryKey$3(db.schema.createTable("api_tokens")).addColumn("name", "text", (col) => col.notNull()).addColumn("token_hash", "text", (col) => col.notNull().unique()).addColumn("token_prefix", "text", (col) => col.notNull()).addColumn("role_id", "uuid", (col) => col.notNull().references("admin_roles.id").onDelete("restrict")).addColumn("created_by", "uuid", (col) => col.references("admin_users.id").onDelete("set null")).addColumn("expires_at", "timestamptz").addColumn("last_used_at", "timestamptz").addColumn("revoked_at", "timestamptz")).execute();
|
|
84
84
|
await db.schema.createIndex("api_tokens_role_idx").on("api_tokens").column("role_id").execute();
|
|
85
85
|
};
|
|
86
|
-
const down$
|
|
86
|
+
const down$36 = async (db) => {
|
|
87
87
|
await db.schema.dropTable("api_tokens").execute();
|
|
88
88
|
await db.schema.dropTable("setup_tokens").execute();
|
|
89
89
|
await db.schema.dropTable("password_resets").execute();
|
|
@@ -97,31 +97,31 @@ const down$33 = async (db) => {
|
|
|
97
97
|
//#endregion
|
|
98
98
|
//#region ../../apps/api/src/db/migrations/20261001130500_create_system_settings.ts
|
|
99
99
|
var _20261001130500_create_system_settings_exports = /* @__PURE__ */ __exportAll({
|
|
100
|
-
down: () => down$
|
|
101
|
-
up: () => up$
|
|
100
|
+
down: () => down$35,
|
|
101
|
+
up: () => up$35
|
|
102
102
|
});
|
|
103
103
|
/**
|
|
104
104
|
* Instance-wide key/value settings that must survive restarts and be shared by every instance, e.g. the
|
|
105
105
|
* generated signing secret. General purpose: later packages add keys, not tables.
|
|
106
106
|
*/
|
|
107
|
-
const up$
|
|
107
|
+
const up$35 = async (db) => {
|
|
108
108
|
await db.schema.createTable("system_settings").addColumn("key", "text", (col) => col.primaryKey()).addColumn("value", "text", (col) => col.notNull()).addColumn("updated_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).execute();
|
|
109
109
|
};
|
|
110
|
-
const down$
|
|
110
|
+
const down$35 = async (db) => {
|
|
111
111
|
await db.schema.dropTable("system_settings").execute();
|
|
112
112
|
};
|
|
113
113
|
//#endregion
|
|
114
114
|
//#region ../../apps/api/src/db/migrations/20261001140000_create_schema_tables.ts
|
|
115
115
|
var _20261001140000_create_schema_tables_exports = /* @__PURE__ */ __exportAll({
|
|
116
|
-
down: () => down$
|
|
117
|
-
up: () => up$
|
|
116
|
+
down: () => down$34,
|
|
117
|
+
up: () => up$34
|
|
118
118
|
});
|
|
119
119
|
/**
|
|
120
120
|
* Schema registry (package D, ADR 0002): models and components (one table, `kind` discriminator), immutable
|
|
121
121
|
* schema revisions, the per-model active pointer, schema change jobs, locales and schema settings.
|
|
122
122
|
* Model definitions are data: creating or changing a model never runs DDL (CONTRIBUTING.md rule 1).
|
|
123
123
|
*/
|
|
124
|
-
const up$
|
|
124
|
+
const up$34 = async (db) => {
|
|
125
125
|
await db.schema.createTable("models").addColumn("id", "uuid", (col) => col.primaryKey()).addColumn("kind", "text", (col) => col.notNull().check(sql`kind in ('collection', 'singleton', 'component')`)).addColumn("api_key", "text", (col) => col.notNull()).addColumn("created_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).addColumn("updated_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).addColumn("deleted_at", "timestamptz").execute();
|
|
126
126
|
await sql`create unique index models_api_key_uq on models (lower(api_key)) where deleted_at is null`.execute(db);
|
|
127
127
|
await db.schema.createTable("schema_revisions").addColumn("id", "uuid", (col) => col.primaryKey().defaultTo(sql`gen_random_uuid()`)).addColumn("model_id", "uuid", (col) => col.notNull().references("models.id").onDelete("restrict")).addColumn("version", "integer", (col) => col.notNull().check(sql`version > 0`)).addColumn("definition", "jsonb", (col) => col.notNull()).addColumn("hash", "text", (col) => col.notNull()).addColumn("parent_revision_id", "uuid", (col) => col.references("schema_revisions.id")).addColumn("created_by_type", "text", (col) => col.notNull()).addColumn("created_by_id", "text").addColumn("created_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).addUniqueConstraint("schema_revisions_model_version_uq", ["model_id", "version"]).execute();
|
|
@@ -149,7 +149,7 @@ const up$31 = async (db) => {
|
|
|
149
149
|
await db.schema.createTable("schema_settings").addColumn("id", "boolean", (col) => col.primaryKey().defaultTo(true).check(sql`id`)).addColumn("read_only", "boolean", (col) => col.notNull().defaultTo(false)).addColumn("read_only_reason", "text").addColumn("updated_by_type", "text").addColumn("updated_by_id", "text").addColumn("updated_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).execute();
|
|
150
150
|
await sql`insert into schema_settings default values`.execute(db);
|
|
151
151
|
};
|
|
152
|
-
const down$
|
|
152
|
+
const down$34 = async (db) => {
|
|
153
153
|
await db.schema.dropTable("schema_settings").execute();
|
|
154
154
|
await db.schema.dropTable("locales").execute();
|
|
155
155
|
await db.schema.dropTable("schema_change_jobs").execute();
|
|
@@ -161,8 +161,8 @@ const down$31 = async (db) => {
|
|
|
161
161
|
//#endregion
|
|
162
162
|
//#region ../../apps/api/src/db/migrations/20261001150000_create_content_tables.ts
|
|
163
163
|
var _20261001150000_create_content_tables_exports = /* @__PURE__ */ __exportAll({
|
|
164
|
-
down: () => down$
|
|
165
|
-
up: () => up$
|
|
164
|
+
down: () => down$33,
|
|
165
|
+
up: () => up$33
|
|
166
166
|
});
|
|
167
167
|
/**
|
|
168
168
|
* Content storage (package E, ADR 0001): entries, immutable content revisions, mutable heads (one per
|
|
@@ -170,7 +170,7 @@ var _20261001150000_create_content_tables_exports = /* @__PURE__ */ __exportAll(
|
|
|
170
170
|
* and the publication log behind `?snapshot=N`. User content models never get tables of their own
|
|
171
171
|
* (CONTRIBUTING.md rule 1): their values are JSONB keyed by stable field IDs.
|
|
172
172
|
*/
|
|
173
|
-
const up$
|
|
173
|
+
const up$33 = async (db) => {
|
|
174
174
|
await db.schema.createTable("entries").addColumn("id", "uuid", (col) => col.primaryKey().defaultTo(sql`gen_random_uuid()`)).addColumn("model_id", "uuid", (col) => col.notNull().references("models.id").onDelete("restrict")).addColumn("owner_app_user_id", "uuid").addColumn("created_by_admin_id", "uuid", (col) => col.references("admin_users.id").onDelete("set null")).addColumn("created_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).addColumn("updated_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).addColumn("deleted_at", "timestamptz").execute();
|
|
175
175
|
await sql`create index entries_model_idx on entries (model_id, created_at) where deleted_at is null`.execute(db);
|
|
176
176
|
await sql`create index entries_owner_idx on entries (owner_app_user_id) where owner_app_user_id is not null`.execute(db);
|
|
@@ -234,7 +234,7 @@ const up$30 = async (db) => {
|
|
|
234
234
|
await sql`create unique index publication_log_open_uq on publication_log (entry_id, locale) where to_seq is null`.execute(db);
|
|
235
235
|
await db.schema.createIndex("publication_log_model_seq_idx").on("publication_log").columns(["model_id", "from_seq"]).execute();
|
|
236
236
|
};
|
|
237
|
-
const down$
|
|
237
|
+
const down$33 = async (db) => {
|
|
238
238
|
await db.schema.dropTable("publication_log").execute();
|
|
239
239
|
await db.schema.dropTable("publication_state").execute();
|
|
240
240
|
await db.schema.dropTable("unique_values").execute();
|
|
@@ -247,8 +247,8 @@ const down$30 = async (db) => {
|
|
|
247
247
|
//#endregion
|
|
248
248
|
//#region ../../apps/api/src/db/migrations/20261001160000_create_media_tables.ts
|
|
249
249
|
var _20261001160000_create_media_tables_exports = /* @__PURE__ */ __exportAll({
|
|
250
|
-
down: () => down$
|
|
251
|
-
up: () => up$
|
|
250
|
+
down: () => down$32,
|
|
251
|
+
up: () => up$32
|
|
252
252
|
});
|
|
253
253
|
/**
|
|
254
254
|
* Media library (package G): folders, assets, image variants, references from content and upload grants.
|
|
@@ -259,7 +259,7 @@ const withTimestamps$2 = (table) => table.addColumn("created_at", "timestamptz",
|
|
|
259
259
|
const uuidPrimaryKey$2 = (table) => table.addColumn("id", "uuid", (col) => col.primaryKey().defaultTo(sql`gen_random_uuid()`));
|
|
260
260
|
const STORAGE_DRIVER_CHECK = sql`storage_driver in ('local', 's3')`;
|
|
261
261
|
const VISIBILITY_CHECK = sql`visibility in ('public', 'private')`;
|
|
262
|
-
const up$
|
|
262
|
+
const up$32 = async (db) => {
|
|
263
263
|
await withTimestamps$2(uuidPrimaryKey$2(db.schema.createTable("media_folders")).addColumn("parent_id", "uuid", (col) => col.references("media_folders.id").onDelete("restrict")).addColumn("name", "text", (col) => col.notNull().check(sql`length(name) between 1 and 255`)).addColumn("created_by", "uuid", (col) => col.references("admin_users.id").onDelete("set null")).addColumn("version", "integer", (col) => col.notNull().defaultTo(1))).execute();
|
|
264
264
|
await sql`create unique index media_folders_sibling_name_uq on media_folders
|
|
265
265
|
(coalesce(parent_id, '00000000-0000-0000-0000-000000000000'::uuid), lower(name))`.execute(db);
|
|
@@ -288,7 +288,7 @@ const up$29 = async (db) => {
|
|
|
288
288
|
]).execute();
|
|
289
289
|
await db.schema.createTable("media_upload_grants").addColumn("id", "uuid", (col) => col.primaryKey().defaultTo(sql`gen_random_uuid()`)).addColumn("asset_id", "uuid", (col) => col.notNull()).addColumn("kind", "text", (col) => col.notNull().check(sql`kind in ('create', 'replace')`)).addColumn("storage_driver", "text", (col) => col.notNull().check(STORAGE_DRIVER_CHECK)).addColumn("storage_key", "text", (col) => col.notNull().unique()).addColumn("original_filename", "text", (col) => col.notNull()).addColumn("declared_mime_type", "text", (col) => col.notNull()).addColumn("max_size_bytes", "bigint", (col) => col.notNull()).addColumn("folder_id", "uuid").addColumn("visibility", "text", (col) => col.notNull().check(VISIBILITY_CHECK)).addColumn("created_by", "uuid", (col) => col.references("admin_users.id").onDelete("set null")).addColumn("created_by_principal", "text", (col) => col.notNull()).addColumn("status", "text", (col) => col.notNull().defaultTo("pending").check(sql`status in ('pending', 'consumed', 'rejected', 'expired')`)).addColumn("expires_at", "timestamptz", (col) => col.notNull()).addColumn("consumed_at", "timestamptz").addColumn("created_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).execute();
|
|
290
290
|
};
|
|
291
|
-
const down$
|
|
291
|
+
const down$32 = async (db) => {
|
|
292
292
|
await db.schema.dropTable("media_upload_grants").execute();
|
|
293
293
|
await db.schema.dropTable("media_references").execute();
|
|
294
294
|
await db.schema.dropTable("media_variants").execute();
|
|
@@ -298,8 +298,8 @@ const down$29 = async (db) => {
|
|
|
298
298
|
//#endregion
|
|
299
299
|
//#region ../../apps/api/src/db/migrations/20261001170000_create_publishing_tables.ts
|
|
300
300
|
var _20261001170000_create_publishing_tables_exports = /* @__PURE__ */ __exportAll({
|
|
301
|
-
down: () => down$
|
|
302
|
-
up: () => up$
|
|
301
|
+
down: () => down$31,
|
|
302
|
+
up: () => up$31
|
|
303
303
|
});
|
|
304
304
|
/**
|
|
305
305
|
* Publishing (package H): scheduled publications, releases, webhooks and their delivery log, deployment
|
|
@@ -338,13 +338,13 @@ const createPreviewTables = async (db) => {
|
|
|
338
338
|
await uuidPrimaryKey$1(db.schema.createTable("preview_tokens")).addColumn("token_hash", "text", (col) => col.notNull().unique()).addColumn("token_prefix", "text", (col) => col.notNull()).addColumn("model_id", "uuid", (col) => col.notNull()).addColumn("entry_id", "uuid", (col) => col.references("entries.id").onDelete("cascade")).addColumn("locale", "text").addColumn("connection_id", "uuid", (col) => col.references("deployment_connections.id").onDelete("set null")).addColumn("delivery_role_id", "uuid", (col) => col.references("admin_roles.id").onDelete("set null")).addColumn("created_by", "uuid", (col) => col.notNull().references("admin_users.id").onDelete("cascade")).addColumn("expires_at", "timestamptz", (col) => col.notNull()).addColumn("revoked_at", "timestamptz").addColumn("last_used_at", "timestamptz").addColumn("created_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).execute();
|
|
339
339
|
await db.schema.createIndex("preview_tokens_entry_idx").on("preview_tokens").columns(["entry_id", "created_at desc"]).execute();
|
|
340
340
|
};
|
|
341
|
-
const up$
|
|
341
|
+
const up$31 = async (db) => {
|
|
342
342
|
await createSchedulingTables(db);
|
|
343
343
|
await createWebhookTables(db);
|
|
344
344
|
await createDeploymentTables(db);
|
|
345
345
|
await createPreviewTables(db);
|
|
346
346
|
};
|
|
347
|
-
const down$
|
|
347
|
+
const down$31 = async (db) => {
|
|
348
348
|
await db.schema.dropTable("preview_tokens").execute();
|
|
349
349
|
await db.schema.dropTable("deployment_runs").execute();
|
|
350
350
|
await db.schema.dropTable("deployment_connections").execute();
|
|
@@ -357,8 +357,8 @@ const down$28 = async (db) => {
|
|
|
357
357
|
//#endregion
|
|
358
358
|
//#region ../../apps/api/src/db/migrations/20261001180000_create_app_users.ts
|
|
359
359
|
var _20261001180000_create_app_users_exports = /* @__PURE__ */ __exportAll({
|
|
360
|
-
down: () => down$
|
|
361
|
-
up: () => up$
|
|
360
|
+
down: () => down$30,
|
|
361
|
+
up: () => up$30
|
|
362
362
|
});
|
|
363
363
|
/**
|
|
364
364
|
* App users (package I, ADR 0005): the end users of sites and apps built on Shapio, with their own roles
|
|
@@ -409,7 +409,7 @@ const createCredentials = async (db) => {
|
|
|
409
409
|
}
|
|
410
410
|
await db.schema.createTable("app_login_codes").addColumn("id", "uuid", (col) => col.primaryKey().defaultTo(sql`gen_random_uuid()`)).addColumn("app_user_id", "uuid", (col) => col.notNull().references("app_users.id").onDelete("cascade")).addColumn("code_hash", "text", (col) => col.notNull().unique()).addColumn("expires_at", "timestamptz", (col) => col.notNull()).addColumn("used_at", "timestamptz").addColumn("created_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).execute();
|
|
411
411
|
};
|
|
412
|
-
const up$
|
|
412
|
+
const up$30 = async (db) => {
|
|
413
413
|
await createUsers(db);
|
|
414
414
|
await createRoles(db);
|
|
415
415
|
await createCredentials(db);
|
|
@@ -419,7 +419,7 @@ const up$27 = async (db) => {
|
|
|
419
419
|
foreign key (owner_app_user_id) references app_users (id) on delete set null
|
|
420
420
|
`.execute(db);
|
|
421
421
|
};
|
|
422
|
-
const down$
|
|
422
|
+
const down$30 = async (db) => {
|
|
423
423
|
await sql`alter table entries drop constraint if exists entries_owner_app_user_fk`.execute(db);
|
|
424
424
|
await db.schema.dropTable("app_login_codes").execute();
|
|
425
425
|
await db.schema.dropTable("app_password_resets").execute();
|
|
@@ -434,8 +434,8 @@ const down$27 = async (db) => {
|
|
|
434
434
|
//#endregion
|
|
435
435
|
//#region ../../apps/api/src/db/migrations/20261002120000_create_extension_hook_runs.ts
|
|
436
436
|
var _20261002120000_create_extension_hook_runs_exports = /* @__PURE__ */ __exportAll({
|
|
437
|
-
down: () => down$
|
|
438
|
-
up: () => up$
|
|
437
|
+
down: () => down$29,
|
|
438
|
+
up: () => up$29
|
|
439
439
|
});
|
|
440
440
|
/**
|
|
441
441
|
* Extension points (package K, ADR 0009): the ledger of post-commit lifecycle hooks (`afterCreate`,
|
|
@@ -443,17 +443,17 @@ var _20261002120000_create_extension_hook_runs_exports = /* @__PURE__ */ __expor
|
|
|
443
443
|
* as the hook's own database work, so a hook re-run after a worker crash finds its row and is skipped:
|
|
444
444
|
* exactly once for everything the hook does through its transaction.
|
|
445
445
|
*/
|
|
446
|
-
const up$
|
|
446
|
+
const up$29 = async (db) => {
|
|
447
447
|
await db.schema.createTable("extension_hook_runs").addColumn("event_id", "uuid", (col) => col.notNull()).addColumn("hook", "text", (col) => col.notNull()).addColumn("job_id", "uuid").addColumn("completed_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).addPrimaryKeyConstraint("extension_hook_runs_pkey", ["event_id", "hook"]).execute();
|
|
448
448
|
};
|
|
449
|
-
const down$
|
|
449
|
+
const down$29 = async (db) => {
|
|
450
450
|
await db.schema.dropTable("extension_hook_runs").execute();
|
|
451
451
|
};
|
|
452
452
|
//#endregion
|
|
453
453
|
//#region ../../apps/api/src/db/migrations/20261002130000_app_auth_token_version_and_login_code_pkce.ts
|
|
454
454
|
var _20261002130000_app_auth_token_version_and_login_code_pkce_exports = /* @__PURE__ */ __exportAll({
|
|
455
|
-
down: () => down$
|
|
456
|
-
up: () => up$
|
|
455
|
+
down: () => down$28,
|
|
456
|
+
up: () => up$28
|
|
457
457
|
});
|
|
458
458
|
/**
|
|
459
459
|
* App users (ADR 0005):
|
|
@@ -464,20 +464,20 @@ var _20261002130000_app_auth_token_version_and_login_code_pkce_exports = /* @__P
|
|
|
464
464
|
* sign-in; the one-time login code is only exchanged with the matching verifier. Codes live a minute, so
|
|
465
465
|
* any pending ones (issued without a challenge) are dropped rather than given a placeholder.
|
|
466
466
|
*/
|
|
467
|
-
const up$
|
|
467
|
+
const up$28 = async (db) => {
|
|
468
468
|
await db.schema.alterTable("app_users").addColumn("token_version", "integer", (col) => col.notNull().defaultTo(0)).execute();
|
|
469
469
|
await sql`delete from app_login_codes`.execute(db);
|
|
470
470
|
await db.schema.alterTable("app_login_codes").addColumn("code_challenge", "text", (col) => col.notNull()).execute();
|
|
471
471
|
};
|
|
472
|
-
const down$
|
|
472
|
+
const down$28 = async (db) => {
|
|
473
473
|
await db.schema.alterTable("app_login_codes").dropColumn("code_challenge").execute();
|
|
474
474
|
await db.schema.alterTable("app_users").dropColumn("token_version").execute();
|
|
475
475
|
};
|
|
476
476
|
//#endregion
|
|
477
477
|
//#region ../../apps/api/src/db/migrations/20261002180000_add_publication_log_diff_indexes.ts
|
|
478
478
|
var _20261002180000_add_publication_log_diff_indexes_exports = /* @__PURE__ */ __exportAll({
|
|
479
|
-
down: () => down$
|
|
480
|
-
up: () => up$
|
|
479
|
+
down: () => down$27,
|
|
480
|
+
up: () => up$27
|
|
481
481
|
});
|
|
482
482
|
/**
|
|
483
483
|
* The snapshot diff (repositories/snapshotDiff.ts) finds the (entry, locale) pairs whose live period opened
|
|
@@ -486,7 +486,7 @@ var _20261002180000_add_publication_log_diff_indexes_exports = /* @__PURE__ */ _
|
|
|
486
486
|
* - `(entry_id, locale, from_seq)`: "the row live at seq N" is the latest row starting at or before N.
|
|
487
487
|
* Periods that opened in the range use the existing `(model_id, from_seq)` index.
|
|
488
488
|
*/
|
|
489
|
-
const up$
|
|
489
|
+
const up$27 = async (db) => {
|
|
490
490
|
await sql`create index publication_log_to_seq_idx on publication_log (to_seq) where to_seq is not null`.execute(db);
|
|
491
491
|
await db.schema.createIndex("publication_log_entry_locale_from_idx").on("publication_log").columns([
|
|
492
492
|
"entry_id",
|
|
@@ -494,15 +494,15 @@ const up$24 = async (db) => {
|
|
|
494
494
|
"from_seq"
|
|
495
495
|
]).execute();
|
|
496
496
|
};
|
|
497
|
-
const down$
|
|
497
|
+
const down$27 = async (db) => {
|
|
498
498
|
await db.schema.dropIndex("publication_log_entry_locale_from_idx").execute();
|
|
499
499
|
await db.schema.dropIndex("publication_log_to_seq_idx").execute();
|
|
500
500
|
};
|
|
501
501
|
//#endregion
|
|
502
502
|
//#region ../../apps/api/src/db/migrations/20261002180100_create_usage_tables.ts
|
|
503
503
|
var _20261002180100_create_usage_tables_exports = /* @__PURE__ */ __exportAll({
|
|
504
|
-
down: () => down$
|
|
505
|
-
up: () => up$
|
|
504
|
+
down: () => down$26,
|
|
505
|
+
up: () => up$26
|
|
506
506
|
});
|
|
507
507
|
/**
|
|
508
508
|
* Field usage from delivery traffic (plan developer-face §5): daily counters written by the in-memory
|
|
@@ -510,7 +510,7 @@ var _20261002180100_create_usage_tables_exports = /* @__PURE__ */ __exportAll({
|
|
|
510
510
|
* payloads. `principal_key` is `token:<id>`, `app_users` or `anonymous`. Pruned by the retention job
|
|
511
511
|
* after USAGE_RETENTION_DAYS.
|
|
512
512
|
*/
|
|
513
|
-
const up$
|
|
513
|
+
const up$26 = async (db) => {
|
|
514
514
|
await db.schema.createTable("field_reads").addColumn("day", "date", (col) => col.notNull()).addColumn("model_id", "uuid", (col) => col.notNull()).addColumn("field_path", "text", (col) => col.notNull()).addColumn("principal_key", "text", (col) => col.notNull()).addColumn("selection", "text", (col) => col.notNull().check(sql`selection in ('explicit', 'implicit')`)).addColumn("reads", "bigint", (col) => col.notNull().defaultTo(0)).addColumn("last_read_at", "timestamptz", (col) => col.notNull()).addPrimaryKeyConstraint("field_reads_pkey", [
|
|
515
515
|
"day",
|
|
516
516
|
"model_id",
|
|
@@ -521,15 +521,15 @@ const up$23 = async (db) => {
|
|
|
521
521
|
await db.schema.createIndex("field_reads_model_day_idx").on("field_reads").columns(["model_id", "day"]).execute();
|
|
522
522
|
await db.schema.createTable("token_reads").addColumn("day", "date", (col) => col.notNull()).addColumn("principal_key", "text", (col) => col.notNull()).addColumn("requests", "bigint", (col) => col.notNull().defaultTo(0)).addColumn("last_snapshot", "bigint").addColumn("last_read_at", "timestamptz", (col) => col.notNull()).addPrimaryKeyConstraint("token_reads_pkey", ["day", "principal_key"]).execute();
|
|
523
523
|
};
|
|
524
|
-
const down$
|
|
524
|
+
const down$26 = async (db) => {
|
|
525
525
|
await db.schema.dropTable("token_reads").execute();
|
|
526
526
|
await db.schema.dropTable("field_reads").execute();
|
|
527
527
|
};
|
|
528
528
|
//#endregion
|
|
529
529
|
//#region ../../apps/api/src/db/migrations/20261002180200_create_change_sets.ts
|
|
530
530
|
var _20261002180200_create_change_sets_exports = /* @__PURE__ */ __exportAll({
|
|
531
|
-
down: () => down$
|
|
532
|
-
up: () => up$
|
|
531
|
+
down: () => down$25,
|
|
532
|
+
up: () => up$25
|
|
533
533
|
});
|
|
534
534
|
/**
|
|
535
535
|
* Change sets (developer-face plan §5, ADR 0010): schema drafts and entry publications that ship as ONE
|
|
@@ -708,7 +708,7 @@ const migrateReleases = async (db) => {
|
|
|
708
708
|
await sql`drop table release_items`.execute(db);
|
|
709
709
|
await sql`drop table releases`.execute(db);
|
|
710
710
|
};
|
|
711
|
-
const up$
|
|
711
|
+
const up$25 = async (db) => {
|
|
712
712
|
await createTables(db);
|
|
713
713
|
await linkExecutionRecords(db);
|
|
714
714
|
await allowConversionRevisions(db);
|
|
@@ -780,7 +780,7 @@ const restoreReleases = async (db) => {
|
|
|
780
780
|
await sql`update webhooks set events = array_remove(array_remove(events, 'change_set.shipping'),
|
|
781
781
|
'change_set.discarded')`.execute(db);
|
|
782
782
|
};
|
|
783
|
-
const down$
|
|
783
|
+
const down$25 = async (db) => {
|
|
784
784
|
await restoreReleases(db);
|
|
785
785
|
await sql`alter table content_revisions drop constraint content_revisions_reason_check`.execute(db);
|
|
786
786
|
await sql`alter table content_revisions add constraint content_revisions_reason_check
|
|
@@ -801,8 +801,8 @@ const down$22 = async (db) => {
|
|
|
801
801
|
//#endregion
|
|
802
802
|
//#region ../../apps/api/src/db/migrations/20261002190000_create_editor_presence_and_content_health.ts
|
|
803
803
|
var _20261002190000_create_editor_presence_and_content_health_exports = /* @__PURE__ */ __exportAll({
|
|
804
|
-
down: () => down$
|
|
805
|
-
up: () => up$
|
|
804
|
+
down: () => down$24,
|
|
805
|
+
up: () => up$24
|
|
806
806
|
});
|
|
807
807
|
/**
|
|
808
808
|
* Editor experience (plan editor-experience §9):
|
|
@@ -813,7 +813,7 @@ var _20261002190000_create_editor_presence_and_content_health_exports = /* @__PU
|
|
|
813
813
|
* - `content_health_findings`: open and recently resolved findings of the health rules per entry and
|
|
814
814
|
* locale (`*` for the entry as a whole). An evaluation upserts what it found and resolves the rest.
|
|
815
815
|
*/
|
|
816
|
-
const up$
|
|
816
|
+
const up$24 = async (db) => {
|
|
817
817
|
await sql`
|
|
818
818
|
create unlogged table editor_presence (
|
|
819
819
|
entry_id uuid not null,
|
|
@@ -850,15 +850,15 @@ const up$21 = async (db) => {
|
|
|
850
850
|
await sql`create index content_health_findings_resolved_idx on content_health_findings (resolved_at)
|
|
851
851
|
where resolved_at is not null`.execute(db);
|
|
852
852
|
};
|
|
853
|
-
const down$
|
|
853
|
+
const down$24 = async (db) => {
|
|
854
854
|
await sql`drop table content_health_findings`.execute(db);
|
|
855
855
|
await sql`drop table editor_presence`.execute(db);
|
|
856
856
|
};
|
|
857
857
|
//#endregion
|
|
858
858
|
//#region ../../apps/api/src/db/migrations/20261003120000_add_changes_ship_permission.ts
|
|
859
859
|
var _20261003120000_add_changes_ship_permission_exports = /* @__PURE__ */ __exportAll({
|
|
860
|
-
down: () => down$
|
|
861
|
-
up: () => up$
|
|
860
|
+
down: () => down$23,
|
|
861
|
+
up: () => up$23
|
|
862
862
|
});
|
|
863
863
|
/**
|
|
864
864
|
* `changes.ship` (agentic plan §I): shipping a change set (and scheduling a ship) becomes its own global
|
|
@@ -866,7 +866,7 @@ var _20261003120000_add_changes_ship_permission_exports = /* @__PURE__ */ __expo
|
|
|
866
866
|
* live. Every role that holds `changes.manage` today keeps what it could do: it gets `changes.ship` too.
|
|
867
867
|
* The permissions version moves only when grants changed, so running instances reload exactly then.
|
|
868
868
|
*/
|
|
869
|
-
const up$
|
|
869
|
+
const up$23 = async (db) => {
|
|
870
870
|
await sql`
|
|
871
871
|
with granted as (
|
|
872
872
|
insert into admin_role_permissions (role_id, action, model_id, condition, field_ids)
|
|
@@ -880,7 +880,7 @@ const up$20 = async (db) => {
|
|
|
880
880
|
where exists (select 1 from granted)
|
|
881
881
|
`.execute(db);
|
|
882
882
|
};
|
|
883
|
-
const down$
|
|
883
|
+
const down$23 = async (db) => {
|
|
884
884
|
await sql`
|
|
885
885
|
with revoked as (
|
|
886
886
|
delete from admin_role_permissions where action = 'changes.ship' returning 1
|
|
@@ -892,8 +892,8 @@ const down$20 = async (db) => {
|
|
|
892
892
|
//#endregion
|
|
893
893
|
//#region ../../apps/api/src/db/migrations/20261003130000_create_sites.ts
|
|
894
894
|
var _20261003130000_create_sites_exports = /* @__PURE__ */ __exportAll({
|
|
895
|
-
down: () => down$
|
|
896
|
-
up: () => up$
|
|
895
|
+
down: () => down$22,
|
|
896
|
+
up: () => up$22
|
|
897
897
|
});
|
|
898
898
|
/**
|
|
899
899
|
* Sites (plan agentic-ecosystem §H, ADR 0011): one instance hosts many sites with one schema and one login.
|
|
@@ -1081,7 +1081,7 @@ const siteRoleAssignments = async (db) => {
|
|
|
1081
1081
|
`.execute(db);
|
|
1082
1082
|
await sql`alter table admin_invitations drop column role_ids`.execute(db);
|
|
1083
1083
|
};
|
|
1084
|
-
const up$
|
|
1084
|
+
const up$22 = async (db) => {
|
|
1085
1085
|
await createSites(db);
|
|
1086
1086
|
await addSiteColumns(db);
|
|
1087
1087
|
await tieCopiesToEntries(db);
|
|
@@ -1094,7 +1094,7 @@ const assertSingleSite = async (db) => {
|
|
|
1094
1094
|
const { rows } = await sql`select count(*)::text as count from sites`.execute(db);
|
|
1095
1095
|
if (Number(rows[0]?.count ?? 0) > 1) throw new Error("Cannot roll back sites while more than one site exists: merging them would merge their snapshot ledgers and uniqueness and widen role assignments. Delete the other sites first.");
|
|
1096
1096
|
};
|
|
1097
|
-
const down$
|
|
1097
|
+
const down$22 = async (db) => {
|
|
1098
1098
|
await assertSingleSite(db);
|
|
1099
1099
|
await sql`alter table admin_invitations add column role_ids uuid[] not null default '{}'::uuid[]`.execute(db);
|
|
1100
1100
|
await sql`
|
|
@@ -1165,8 +1165,8 @@ const down$19 = async (db) => {
|
|
|
1165
1165
|
//#endregion
|
|
1166
1166
|
//#region ../../apps/api/src/db/migrations/20261003140200_enqueue_field_index_layout.ts
|
|
1167
1167
|
var _20261003140200_enqueue_field_index_layout_exports = /* @__PURE__ */ __exportAll({
|
|
1168
|
-
down: () => down$
|
|
1169
|
-
up: () => up$
|
|
1168
|
+
down: () => down$21,
|
|
1169
|
+
up: () => up$21
|
|
1170
1170
|
});
|
|
1171
1171
|
/**
|
|
1172
1172
|
* Field index layout v2 (sites plan §H): per-field expression indexes on `entry_heads` lead with `site_id`,
|
|
@@ -1178,7 +1178,7 @@ var _20261003140200_enqueue_field_index_layout_exports = /* @__PURE__ */ __expor
|
|
|
1178
1178
|
*/
|
|
1179
1179
|
const JOB_TYPE$1 = "schema.fieldIndexLayout";
|
|
1180
1180
|
const IDEMPOTENCY_KEY$1 = "schema.fieldIndexLayout:v2";
|
|
1181
|
-
const up$
|
|
1181
|
+
const up$21 = async (db) => {
|
|
1182
1182
|
await sql`
|
|
1183
1183
|
insert into jobs (type, payload, max_attempts, idempotency_key)
|
|
1184
1184
|
select ${JOB_TYPE$1}, '{}'::jsonb, 5, ${IDEMPOTENCY_KEY$1}
|
|
@@ -1191,14 +1191,14 @@ const up$18 = async (db) => {
|
|
|
1191
1191
|
`.execute(db);
|
|
1192
1192
|
};
|
|
1193
1193
|
/** The layout job is idempotent; rolling back only forgets it if it has not run yet. */
|
|
1194
|
-
const down$
|
|
1194
|
+
const down$21 = async (db) => {
|
|
1195
1195
|
await sql`delete from jobs where idempotency_key = ${IDEMPOTENCY_KEY$1} and status = 'pending'`.execute(db);
|
|
1196
1196
|
};
|
|
1197
1197
|
//#endregion
|
|
1198
1198
|
//#region ../../apps/api/src/db/migrations/20261003140500_change_set_items_site_and_preview_entry.ts
|
|
1199
1199
|
var _20261003140500_change_set_items_site_and_preview_entry_exports = /* @__PURE__ */ __exportAll({
|
|
1200
|
-
down: () => down$
|
|
1201
|
-
up: () => up$
|
|
1200
|
+
down: () => down$20,
|
|
1201
|
+
up: () => up$20
|
|
1202
1202
|
});
|
|
1203
1203
|
/**
|
|
1204
1204
|
* Sites, publishing (plan agentic-ecosystem §H, package G5).
|
|
@@ -1209,7 +1209,7 @@ var _20261003140500_change_set_items_site_and_preview_entry_exports = /* @__PURE
|
|
|
1209
1209
|
* - `preview_tokens.entry_id` becomes required: a preview token previews one entry of one site. Model-wide
|
|
1210
1210
|
* tokens (short-lived by design) are deleted; whoever needs one opens the entry's preview again.
|
|
1211
1211
|
*/
|
|
1212
|
-
const up$
|
|
1212
|
+
const up$20 = async (db) => {
|
|
1213
1213
|
await sql`alter table change_sets add constraint change_sets_id_site_uq unique (id, site_id)`.execute(db);
|
|
1214
1214
|
await sql`alter table change_set_items add column site_id uuid`.execute(db);
|
|
1215
1215
|
await sql`
|
|
@@ -1225,7 +1225,7 @@ const up$17 = async (db) => {
|
|
|
1225
1225
|
await sql`delete from preview_tokens where entry_id is null`.execute(db);
|
|
1226
1226
|
await sql`alter table preview_tokens alter column entry_id set not null`.execute(db);
|
|
1227
1227
|
};
|
|
1228
|
-
const down$
|
|
1228
|
+
const down$20 = async (db) => {
|
|
1229
1229
|
await sql`alter table preview_tokens alter column entry_id drop not null`.execute(db);
|
|
1230
1230
|
await sql`alter table change_set_items drop constraint change_set_items_entry_site_fk`.execute(db);
|
|
1231
1231
|
await sql`alter table change_set_items drop constraint change_set_items_set_site_fk`.execute(db);
|
|
@@ -1235,8 +1235,8 @@ const down$17 = async (db) => {
|
|
|
1235
1235
|
//#endregion
|
|
1236
1236
|
//#region ../../apps/api/src/db/migrations/20261003150000_widen_deployment_providers.ts
|
|
1237
1237
|
var _20261003150000_widen_deployment_providers_exports = /* @__PURE__ */ __exportAll({
|
|
1238
|
-
down: () => down$
|
|
1239
|
-
up: () => up$
|
|
1238
|
+
down: () => down$19,
|
|
1239
|
+
up: () => up$19
|
|
1240
1240
|
});
|
|
1241
1241
|
/**
|
|
1242
1242
|
* Deploy adapters (plan agentic-ecosystem §B2): deployment connections may use the Vercel and Netlify
|
|
@@ -1251,11 +1251,11 @@ const replaceCheck = async (db, check) => {
|
|
|
1251
1251
|
check (${check}) not valid`.execute(db);
|
|
1252
1252
|
await sql`alter table deployment_connections validate constraint deployment_connections_provider_check`.execute(db);
|
|
1253
1253
|
};
|
|
1254
|
-
const up$
|
|
1254
|
+
const up$19 = async (db) => {
|
|
1255
1255
|
await replaceCheck(db, WIDENED);
|
|
1256
1256
|
};
|
|
1257
1257
|
/** Refuses while Vercel or Netlify connections exist: a down migration never deletes user data. */
|
|
1258
|
-
const down$
|
|
1258
|
+
const down$19 = async (db) => {
|
|
1259
1259
|
const { rows } = await sql`
|
|
1260
1260
|
select count(*)::text as count from deployment_connections where provider in ('vercel', 'netlify')
|
|
1261
1261
|
`.execute(db);
|
|
@@ -1266,8 +1266,8 @@ const down$16 = async (db) => {
|
|
|
1266
1266
|
//#endregion
|
|
1267
1267
|
//#region ../../apps/api/src/db/migrations/20261003160000_create_assist_runs.ts
|
|
1268
1268
|
var _20261003160000_create_assist_runs_exports = /* @__PURE__ */ __exportAll({
|
|
1269
|
-
down: () => down$
|
|
1270
|
-
up: () => up$
|
|
1269
|
+
down: () => down$18,
|
|
1270
|
+
up: () => up$18
|
|
1271
1271
|
});
|
|
1272
1272
|
/**
|
|
1273
1273
|
* Editor assists (plan agentic-ecosystem §A0, §I): one `assist_runs` row per assist request (who, which
|
|
@@ -1283,14 +1283,14 @@ const replaceSourceCheck = async (db, check) => {
|
|
|
1283
1283
|
await sql`alter table change_sets add constraint change_sets_source_check check (${check}) not valid`.execute(db);
|
|
1284
1284
|
await sql`alter table change_sets validate constraint change_sets_source_check`.execute(db);
|
|
1285
1285
|
};
|
|
1286
|
-
const up$
|
|
1286
|
+
const up$18 = async (db) => {
|
|
1287
1287
|
await db.schema.createTable("assist_runs").addColumn("id", "uuid", (col) => col.primaryKey().defaultTo(sql`gen_random_uuid()`)).addColumn("site_id", "uuid", (col) => col.notNull().references("sites.id").onDelete("cascade")).addColumn("actor_type", "text", (col) => col.notNull()).addColumn("actor_id", "text", (col) => col.notNull()).addColumn("action", "text", (col) => col.notNull().check(ACTIONS)).addColumn("rule", "text").addColumn("provider", "text", (col) => col.notNull()).addColumn("model", "text", (col) => col.notNull()).addColumn("input_tokens", "integer", (col) => col.notNull().defaultTo(0)).addColumn("output_tokens", "integer", (col) => col.notNull().defaultTo(0)).addColumn("duration_ms", "integer", (col) => col.notNull().defaultTo(0)).addColumn("status", "text", (col) => col.notNull().check(sql`status in ('queued', 'running', 'succeeded', 'failed')`)).addColumn("error_code", "text").addColumn("job_id", "uuid", (col) => col.references("jobs.id").onDelete("set null")).addColumn("created_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)).addColumn("finished_at", "timestamptz").execute();
|
|
1288
1288
|
await db.schema.createIndex("assist_runs_site_created_idx").on("assist_runs").columns(["site_id", "created_at"]).execute();
|
|
1289
1289
|
await db.schema.createIndex("assist_runs_created_idx").on("assist_runs").column("created_at").execute();
|
|
1290
1290
|
await replaceSourceCheck(db, SOURCES_WIDENED);
|
|
1291
1291
|
};
|
|
1292
1292
|
/** Refuses while change sets opened by assist exist: a down migration never deletes user data. */
|
|
1293
|
-
const down$
|
|
1293
|
+
const down$18 = async (db) => {
|
|
1294
1294
|
const { rows } = await sql`
|
|
1295
1295
|
select count(*)::text as count from change_sets where source = 'assist'
|
|
1296
1296
|
`.execute(db);
|
|
@@ -1302,8 +1302,8 @@ const down$15 = async (db) => {
|
|
|
1302
1302
|
//#endregion
|
|
1303
1303
|
//#region ../../apps/api/src/db/migrations/20261003170000_audit_events_seq.ts
|
|
1304
1304
|
var _20261003170000_audit_events_seq_exports$2 = /* @__PURE__ */ __exportAll({
|
|
1305
|
-
down: () => down$
|
|
1306
|
-
up: () => up$
|
|
1305
|
+
down: () => down$17,
|
|
1306
|
+
up: () => up$17
|
|
1307
1307
|
});
|
|
1308
1308
|
/**
|
|
1309
1309
|
* `audit_events.seq`: a monotonic tiebreaker after `occurred_at`, so events written in the same instant (one
|
|
@@ -1312,17 +1312,17 @@ var _20261003170000_audit_events_seq_exports$2 = /* @__PURE__ */ __exportAll({
|
|
|
1312
1312
|
* are numbered in the order the rewrite reads them. No index: the audit queries filter and sort by
|
|
1313
1313
|
* `occurred_at` first, and `seq` only breaks ties.
|
|
1314
1314
|
*/
|
|
1315
|
-
const up$
|
|
1315
|
+
const up$17 = async (db) => {
|
|
1316
1316
|
await db.schema.alterTable("audit_events").addColumn("seq", "bigint", (col) => col.notNull().generatedAlwaysAsIdentity()).execute();
|
|
1317
1317
|
};
|
|
1318
|
-
const down$
|
|
1318
|
+
const down$17 = async (db) => {
|
|
1319
1319
|
await db.schema.alterTable("audit_events").dropColumn("seq").execute();
|
|
1320
1320
|
};
|
|
1321
1321
|
//#endregion
|
|
1322
1322
|
//#region ../../apps/api/src/db/migrations/20261004120000_models_site_scope.ts
|
|
1323
1323
|
var _20261004120000_models_site_scope_exports$2 = /* @__PURE__ */ __exportAll({
|
|
1324
|
-
down: () => down$
|
|
1325
|
-
up: () => up$
|
|
1324
|
+
down: () => down$16,
|
|
1325
|
+
up: () => up$16
|
|
1326
1326
|
});
|
|
1327
1327
|
/**
|
|
1328
1328
|
* Per-site schema (plan site-schema): a definition belongs to one site (`models.site_id`) or is shared by every
|
|
@@ -1335,7 +1335,7 @@ var _20261004120000_models_site_scope_exports$2 = /* @__PURE__ */ __exportAll({
|
|
|
1335
1335
|
* over `lower(api_key)` cannot hold. Share or delete them first; then `down` is lossless.
|
|
1336
1336
|
*/
|
|
1337
1337
|
const NIL_UUID$1 = "00000000-0000-0000-0000-000000000000";
|
|
1338
|
-
const up$
|
|
1338
|
+
const up$16 = async (db) => {
|
|
1339
1339
|
await sql`alter table models add column site_id uuid references sites (id)`.execute(db);
|
|
1340
1340
|
await sql`create index models_site_idx on models (site_id)`.execute(db);
|
|
1341
1341
|
await sql`drop index models_api_key_uq`.execute(db);
|
|
@@ -1345,7 +1345,7 @@ const up$13 = async (db) => {
|
|
|
1345
1345
|
`.execute(db);
|
|
1346
1346
|
await sql`alter table schema_drafts add column shared boolean not null default false`.execute(db);
|
|
1347
1347
|
};
|
|
1348
|
-
const down$
|
|
1348
|
+
const down$16 = async (db) => {
|
|
1349
1349
|
const { rows } = await sql`select count(*)::text as count from models where site_id is not null`.execute(db);
|
|
1350
1350
|
if (Number(rows[0]?.count ?? 0) > 0) throw new Error("Cannot roll back per-site schema while definitions belong to a site: two sites may share an API ID. Share or delete the site definitions first.");
|
|
1351
1351
|
await sql`alter table schema_drafts drop column shared`.execute(db);
|
|
@@ -1357,8 +1357,8 @@ const down$13 = async (db) => {
|
|
|
1357
1357
|
//#endregion
|
|
1358
1358
|
//#region ../../apps/api/src/db/migrations/20261004130000_site_seo_settings.ts
|
|
1359
1359
|
var _20261004130000_site_seo_settings_exports$2 = /* @__PURE__ */ __exportAll({
|
|
1360
|
-
down: () => down$
|
|
1361
|
-
up: () => up$
|
|
1360
|
+
down: () => down$15,
|
|
1361
|
+
up: () => up$15
|
|
1362
1362
|
});
|
|
1363
1363
|
/**
|
|
1364
1364
|
* SEO defaults per site (plan seo-fields): `sites.seo_defaults` holds the site's default texts per locale, its
|
|
@@ -1369,7 +1369,7 @@ var _20261004130000_site_seo_settings_exports$2 = /* @__PURE__ */ __exportAll({
|
|
|
1369
1369
|
* about what a site publishes) gets it; the built-in owner and admin roles get it from `ensureSystemRoles`.
|
|
1370
1370
|
* The permissions version moves only when grants changed, so running instances reload exactly then.
|
|
1371
1371
|
*/
|
|
1372
|
-
const up$
|
|
1372
|
+
const up$15 = async (db) => {
|
|
1373
1373
|
await sql`alter table sites add column seo_defaults jsonb`.execute(db);
|
|
1374
1374
|
await sql`
|
|
1375
1375
|
with granted as (
|
|
@@ -1384,7 +1384,7 @@ const up$12 = async (db) => {
|
|
|
1384
1384
|
where exists (select 1 from granted)
|
|
1385
1385
|
`.execute(db);
|
|
1386
1386
|
};
|
|
1387
|
-
const down$
|
|
1387
|
+
const down$15 = async (db) => {
|
|
1388
1388
|
await sql`
|
|
1389
1389
|
with revoked as (
|
|
1390
1390
|
delete from admin_role_permissions where action = 'site.settings' returning 1
|
|
@@ -1397,8 +1397,8 @@ const down$12 = async (db) => {
|
|
|
1397
1397
|
//#endregion
|
|
1398
1398
|
//#region ../../apps/api/src/db/migrations/20261005120000_entry_heads_entry_created_at.ts
|
|
1399
1399
|
var _20261005120000_entry_heads_entry_created_at_exports$2 = /* @__PURE__ */ __exportAll({
|
|
1400
|
-
down: () => down$
|
|
1401
|
-
up: () => up$
|
|
1400
|
+
down: () => down$14,
|
|
1401
|
+
up: () => up$14
|
|
1402
1402
|
});
|
|
1403
1403
|
/**
|
|
1404
1404
|
* Delivery perf 2 (ADR 0001 amendment): the entry's `created_at` on each head (`entry_created_at`), so a list
|
|
@@ -1415,7 +1415,7 @@ const INDEX$2 = "entry_heads_entry_order_idx";
|
|
|
1415
1415
|
const JOB_TYPE = "schema.entryOrderIndex";
|
|
1416
1416
|
const IDEMPOTENCY_KEY = "schema.entryOrderIndex:v1";
|
|
1417
1417
|
const BATCH$1 = 5e3;
|
|
1418
|
-
const up$
|
|
1418
|
+
const up$14 = async (db) => {
|
|
1419
1419
|
await sql`alter table entry_heads add column entry_created_at timestamptz`.execute(db);
|
|
1420
1420
|
for (;;) {
|
|
1421
1421
|
const result = await sql`
|
|
@@ -1440,7 +1440,7 @@ const up$11 = async (db) => {
|
|
|
1440
1440
|
create index ${sql.id(INDEX$2)} on entry_heads (site_id, model_id, state, entry_created_at desc, entry_id)
|
|
1441
1441
|
`.execute(db);
|
|
1442
1442
|
};
|
|
1443
|
-
const down$
|
|
1443
|
+
const down$14 = async (db) => {
|
|
1444
1444
|
await sql`delete from jobs where idempotency_key = ${IDEMPOTENCY_KEY} and status = 'pending'`.execute(db);
|
|
1445
1445
|
await sql`drop index if exists ${sql.id(INDEX$2)}`.execute(db);
|
|
1446
1446
|
await sql`alter table entry_heads drop column entry_created_at`.execute(db);
|
|
@@ -1449,20 +1449,58 @@ const down$11 = async (db) => {
|
|
|
1449
1449
|
//#region ../../apps/api/src/db/migrations/20261006120000_system_versions_release.ts
|
|
1450
1450
|
var _20261006120000_system_versions_release_exports = /* @__PURE__ */ __exportAll({
|
|
1451
1451
|
dialectNeutral: () => true,
|
|
1452
|
-
down: () => down$
|
|
1453
|
-
up: () => up$
|
|
1452
|
+
down: () => down$13,
|
|
1453
|
+
up: () => up$13
|
|
1454
1454
|
});
|
|
1455
|
-
const up$
|
|
1455
|
+
const up$13 = async (db) => {
|
|
1456
1456
|
await db.schema.alterTable("system_versions").addColumn("release", "text").execute();
|
|
1457
1457
|
};
|
|
1458
|
-
const down$
|
|
1458
|
+
const down$13 = async (db) => {
|
|
1459
1459
|
await db.schema.alterTable("system_versions").dropColumn("release").execute();
|
|
1460
1460
|
};
|
|
1461
1461
|
//#endregion
|
|
1462
|
+
//#region ../../apps/api/src/db/migrations/20261014120000_canceled_status.ts
|
|
1463
|
+
var _20261014120000_canceled_status_exports$2 = /* @__PURE__ */ __exportAll({
|
|
1464
|
+
down: () => down$12,
|
|
1465
|
+
up: () => up$12
|
|
1466
|
+
});
|
|
1467
|
+
/**
|
|
1468
|
+
* The `cancelled` status of schema change jobs and scheduled publications becomes `canceled`. Rows are
|
|
1469
|
+
* rewritten and the check constraints swapped. MySQL has its own twin; SQLite rebuilds the two tables
|
|
1470
|
+
* (`./sqlite/20261014120000_canceled_status.ts`).
|
|
1471
|
+
*/
|
|
1472
|
+
const TABLES$4 = [{
|
|
1473
|
+
table: "schema_change_jobs",
|
|
1474
|
+
values: [
|
|
1475
|
+
"pending",
|
|
1476
|
+
"running",
|
|
1477
|
+
"activated",
|
|
1478
|
+
"failed"
|
|
1479
|
+
]
|
|
1480
|
+
}, {
|
|
1481
|
+
table: "scheduled_publications",
|
|
1482
|
+
values: [
|
|
1483
|
+
"scheduled",
|
|
1484
|
+
"done",
|
|
1485
|
+
"failed"
|
|
1486
|
+
]
|
|
1487
|
+
}];
|
|
1488
|
+
const swap$1 = async (db, from, to) => {
|
|
1489
|
+
for (const { table, values } of TABLES$4) {
|
|
1490
|
+
const constraint = `${table}_status_check`;
|
|
1491
|
+
await sql`alter table ${sql.table(table)} drop constraint ${sql.id(constraint)}`.execute(db);
|
|
1492
|
+
await sql`update ${sql.table(table)} set status = ${to} where status = ${from}`.execute(db);
|
|
1493
|
+
const allowed = sql.join([...values, to].map((value) => sql.lit(value)));
|
|
1494
|
+
await sql`alter table ${sql.table(table)} add constraint ${sql.id(constraint)} check (status in (${allowed}))`.execute(db);
|
|
1495
|
+
}
|
|
1496
|
+
};
|
|
1497
|
+
const up$12 = (db) => swap$1(db, "cancelled", "canceled");
|
|
1498
|
+
const down$12 = (db) => swap$1(db, "canceled", "cancelled");
|
|
1499
|
+
//#endregion
|
|
1462
1500
|
//#region ../../apps/api/src/db/migrations/mysql/0001_baseline.ts
|
|
1463
1501
|
var _0001_baseline_exports$1 = /* @__PURE__ */ __exportAll({
|
|
1464
|
-
down: () => down$
|
|
1465
|
-
up: () => up$
|
|
1502
|
+
down: () => down$11,
|
|
1503
|
+
up: () => up$11
|
|
1466
1504
|
});
|
|
1467
1505
|
/**
|
|
1468
1506
|
* MySQL baseline: Shapio's whole system schema as of PostgreSQL migration
|
|
@@ -2572,7 +2610,7 @@ const STATEMENTS$1 = [
|
|
|
2572
2610
|
('00000000-0000-4000-b000-000000000001', 'public', '00000000-0000-4000-a000-000000000001'),
|
|
2573
2611
|
('00000000-0000-4000-b000-000000000001', 'authenticated', '00000000-0000-4000-a000-000000000002')`
|
|
2574
2612
|
];
|
|
2575
|
-
const TABLES$
|
|
2613
|
+
const TABLES$3 = [
|
|
2576
2614
|
"system_versions",
|
|
2577
2615
|
"jobs",
|
|
2578
2616
|
"outbox_events",
|
|
@@ -2645,13 +2683,13 @@ const withoutForeignKeyChecks = async (db, statements) => db.connection().execut
|
|
|
2645
2683
|
await sql`set foreign_key_checks = 1`.execute(connection);
|
|
2646
2684
|
}
|
|
2647
2685
|
});
|
|
2648
|
-
const up$
|
|
2649
|
-
const down$
|
|
2686
|
+
const up$11 = async (db) => withoutForeignKeyChecks(db, STATEMENTS$1);
|
|
2687
|
+
const down$11 = async (db) => withoutForeignKeyChecks(db, [...TABLES$3].reverse().map((table) => `drop table if exists \`${table}\``));
|
|
2650
2688
|
//#endregion
|
|
2651
2689
|
//#region ../../apps/api/src/db/migrations/mysql/20261003170000_audit_events_seq.ts
|
|
2652
2690
|
var _20261003170000_audit_events_seq_exports$1 = /* @__PURE__ */ __exportAll({
|
|
2653
|
-
down: () => down$
|
|
2654
|
-
up: () => up$
|
|
2691
|
+
down: () => down$10,
|
|
2692
|
+
up: () => up$10
|
|
2655
2693
|
});
|
|
2656
2694
|
/**
|
|
2657
2695
|
* MySQL twin of `../20261003170000_audit_events_seq.ts`: `seq` is `AUTO_INCREMENT`, which InnoDB only allows
|
|
@@ -2659,26 +2697,26 @@ var _20261003170000_audit_events_seq_exports$1 = /* @__PURE__ */ __exportAll({
|
|
|
2659
2697
|
* tiebreaker). Existing rows are numbered in primary-key order. `db/mysql/tables.ts` lists `seq` as the
|
|
2660
2698
|
* table's identity, so an insert's emulated RETURNING finds its row by `LAST_INSERT_ID()`.
|
|
2661
2699
|
*/
|
|
2662
|
-
const up$
|
|
2700
|
+
const up$10 = async (db) => {
|
|
2663
2701
|
await sql`alter table \`audit_events\`
|
|
2664
2702
|
add column \`seq\` bigint not null auto_increment,
|
|
2665
2703
|
add unique key \`audit_events_seq_key\` (\`seq\`)`.execute(db);
|
|
2666
2704
|
};
|
|
2667
|
-
const down$
|
|
2705
|
+
const down$10 = async (db) => {
|
|
2668
2706
|
await sql`alter table \`audit_events\` drop column \`seq\``.execute(db);
|
|
2669
2707
|
};
|
|
2670
2708
|
//#endregion
|
|
2671
2709
|
//#region ../../apps/api/src/db/migrations/mysql/20261004120000_models_site_scope.ts
|
|
2672
2710
|
var _20261004120000_models_site_scope_exports$1 = /* @__PURE__ */ __exportAll({
|
|
2673
|
-
down: () => down$
|
|
2674
|
-
up: () => up$
|
|
2711
|
+
down: () => down$9,
|
|
2712
|
+
up: () => up$9
|
|
2675
2713
|
});
|
|
2676
2714
|
/**
|
|
2677
2715
|
* MySQL twin of `../20261004120000_models_site_scope.ts`. The per-scope API ID key uses functional key parts,
|
|
2678
2716
|
* like the baseline: `coalesce(site_id, '')` for the scope (MySQL has no `NULLS NOT DISTINCT`) and the
|
|
2679
2717
|
* case-folded API ID of live rows only (a deleted row's part is NULL, and NULLs never collide).
|
|
2680
2718
|
*/
|
|
2681
|
-
const up$
|
|
2719
|
+
const up$9 = async (db) => {
|
|
2682
2720
|
await sql`alter table \`models\` add column \`site_id\` char(36) character set ascii collate ascii_general_ci`.execute(db);
|
|
2683
2721
|
await sql`create index \`models_site_idx\` on \`models\` (\`site_id\`)`.execute(db);
|
|
2684
2722
|
await sql`alter table \`models\` add constraint \`models_site_id_fkey\` foreign key (\`site_id\`) references \`sites\` (\`id\`)`.execute(db);
|
|
@@ -2687,7 +2725,7 @@ const up$7 = async (db) => {
|
|
|
2687
2725
|
((coalesce(\`site_id\`, '')), (case when (\`deleted_at\` IS NULL) then lower(\`api_key\`) end))`.execute(db);
|
|
2688
2726
|
await sql`alter table \`schema_drafts\` add column \`shared\` tinyint(1) not null default 0`.execute(db);
|
|
2689
2727
|
};
|
|
2690
|
-
const down$
|
|
2728
|
+
const down$9 = async (db) => {
|
|
2691
2729
|
const { rows } = await sql`select count(*) as count from \`models\` where \`site_id\` is not null`.execute(db);
|
|
2692
2730
|
if (Number(rows[0]?.count ?? 0) > 0) throw new Error("Cannot roll back per-site schema while definitions belong to a site: two sites may share an API ID. Share or delete the site definitions first.");
|
|
2693
2731
|
await sql`alter table \`schema_drafts\` drop column \`shared\``.execute(db);
|
|
@@ -2701,8 +2739,8 @@ const down$7 = async (db) => {
|
|
|
2701
2739
|
//#endregion
|
|
2702
2740
|
//#region ../../apps/api/src/db/migrations/mysql/20261004130000_site_seo_settings.ts
|
|
2703
2741
|
var _20261004130000_site_seo_settings_exports$1 = /* @__PURE__ */ __exportAll({
|
|
2704
|
-
down: () => down$
|
|
2705
|
-
up: () => up$
|
|
2742
|
+
down: () => down$8,
|
|
2743
|
+
up: () => up$8
|
|
2706
2744
|
});
|
|
2707
2745
|
/**
|
|
2708
2746
|
* MySQL twin of `../20261004130000_site_seo_settings.ts`. `insert ignore` stands in for `on conflict do
|
|
@@ -2710,7 +2748,7 @@ var _20261004130000_site_seo_settings_exports$1 = /* @__PURE__ */ __exportAll({
|
|
|
2710
2748
|
*/
|
|
2711
2749
|
const bumpPermissionsVersion$1 = (db) => sql`update \`system_versions\` set \`permissions_version\` = \`permissions_version\` + 1,
|
|
2712
2750
|
\`updated_at\` = current_timestamp(6)`.execute(db);
|
|
2713
|
-
const up$
|
|
2751
|
+
const up$8 = async (db) => {
|
|
2714
2752
|
await sql`alter table \`sites\` add column \`seo_defaults\` json`.execute(db);
|
|
2715
2753
|
const granted = await sql`
|
|
2716
2754
|
insert ignore into \`admin_role_permissions\` (\`id\`, \`role_id\`, \`action\`, \`model_id\`, \`condition\`, \`field_ids\`)
|
|
@@ -2720,7 +2758,7 @@ const up$6 = async (db) => {
|
|
|
2720
2758
|
`.execute(db);
|
|
2721
2759
|
if (Number(granted.numAffectedRows ?? 0) > 0) await bumpPermissionsVersion$1(db);
|
|
2722
2760
|
};
|
|
2723
|
-
const down$
|
|
2761
|
+
const down$8 = async (db) => {
|
|
2724
2762
|
const revoked = await sql`delete from \`admin_role_permissions\` where \`action\` = 'site.settings'`.execute(db);
|
|
2725
2763
|
if (Number(revoked.numAffectedRows ?? 0) > 0) await bumpPermissionsVersion$1(db);
|
|
2726
2764
|
await sql`alter table \`sites\` drop column \`seo_defaults\``.execute(db);
|
|
@@ -2728,8 +2766,8 @@ const down$6 = async (db) => {
|
|
|
2728
2766
|
//#endregion
|
|
2729
2767
|
//#region ../../apps/api/src/db/migrations/mysql/20261005120000_entry_heads_entry_created_at.ts
|
|
2730
2768
|
var _20261005120000_entry_heads_entry_created_at_exports$1 = /* @__PURE__ */ __exportAll({
|
|
2731
|
-
down: () => down$
|
|
2732
|
-
up: () => up$
|
|
2769
|
+
down: () => down$7,
|
|
2770
|
+
up: () => up$7
|
|
2733
2771
|
});
|
|
2734
2772
|
/**
|
|
2735
2773
|
* MySQL twin of `../20261005120000_entry_heads_entry_created_at.ts`. The column is added `ALGORITHM=INSTANT`
|
|
@@ -2738,7 +2776,7 @@ var _20261005120000_entry_heads_entry_created_at_exports$1 = /* @__PURE__ */ __e
|
|
|
2738
2776
|
*/
|
|
2739
2777
|
const INDEX$1 = "entry_heads_entry_order_idx";
|
|
2740
2778
|
const BATCH = 5e3;
|
|
2741
|
-
const up$
|
|
2779
|
+
const up$7 = async (db) => {
|
|
2742
2780
|
await sql`alter table \`entry_heads\` add column \`entry_created_at\` datetime(6), algorithm=instant`.execute(db);
|
|
2743
2781
|
for (;;) {
|
|
2744
2782
|
const result = await sql`update \`entry_heads\` set \`entry_created_at\` = (
|
|
@@ -2749,11 +2787,48 @@ const up$5 = async (db) => {
|
|
|
2749
2787
|
await sql`create index ${sql.id(INDEX$1)} on \`entry_heads\`
|
|
2750
2788
|
(\`site_id\`, \`model_id\`, \`state\`, \`entry_created_at\` desc, \`entry_id\`) algorithm=inplace lock=none`.execute(db);
|
|
2751
2789
|
};
|
|
2752
|
-
const down$
|
|
2790
|
+
const down$7 = async (db) => {
|
|
2753
2791
|
await sql`drop index ${sql.id(INDEX$1)} on \`entry_heads\``.execute(db);
|
|
2754
2792
|
await sql`alter table \`entry_heads\` drop column \`entry_created_at\``.execute(db);
|
|
2755
2793
|
};
|
|
2756
2794
|
//#endregion
|
|
2795
|
+
//#region ../../apps/api/src/db/migrations/mysql/20261014120000_canceled_status.ts
|
|
2796
|
+
var _20261014120000_canceled_status_exports$1 = /* @__PURE__ */ __exportAll({
|
|
2797
|
+
down: () => down$6,
|
|
2798
|
+
up: () => up$6
|
|
2799
|
+
});
|
|
2800
|
+
/**
|
|
2801
|
+
* MySQL twin of `../20261014120000_canceled_status.ts`: MySQL 8.4 drops a check constraint with
|
|
2802
|
+
* `drop check`, not `drop constraint`.
|
|
2803
|
+
*/
|
|
2804
|
+
const TABLES$2 = [{
|
|
2805
|
+
table: "schema_change_jobs",
|
|
2806
|
+
values: [
|
|
2807
|
+
"pending",
|
|
2808
|
+
"running",
|
|
2809
|
+
"activated",
|
|
2810
|
+
"failed"
|
|
2811
|
+
]
|
|
2812
|
+
}, {
|
|
2813
|
+
table: "scheduled_publications",
|
|
2814
|
+
values: [
|
|
2815
|
+
"scheduled",
|
|
2816
|
+
"done",
|
|
2817
|
+
"failed"
|
|
2818
|
+
]
|
|
2819
|
+
}];
|
|
2820
|
+
const swap = async (db, from, to) => {
|
|
2821
|
+
for (const { table, values } of TABLES$2) {
|
|
2822
|
+
const constraint = `${table}_status_check`;
|
|
2823
|
+
await sql`alter table ${sql.table(table)} drop check ${sql.id(constraint)}`.execute(db);
|
|
2824
|
+
await sql`update ${sql.table(table)} set status = ${to} where status = ${from}`.execute(db);
|
|
2825
|
+
const allowed = sql.join([...values, to].map((value) => sql.lit(value)));
|
|
2826
|
+
await sql`alter table ${sql.table(table)} add constraint ${sql.id(constraint)} check (status in (${allowed}))`.execute(db);
|
|
2827
|
+
}
|
|
2828
|
+
};
|
|
2829
|
+
const up$6 = (db) => swap(db, "cancelled", "canceled");
|
|
2830
|
+
const down$6 = (db) => swap(db, "canceled", "cancelled");
|
|
2831
|
+
//#endregion
|
|
2757
2832
|
//#region ../../apps/api/src/db/migrations/mysql/index.ts
|
|
2758
2833
|
const MYSQL_MIGRATIONS = {
|
|
2759
2834
|
"0001_baseline": _0001_baseline_exports$1,
|
|
@@ -2761,13 +2836,14 @@ const MYSQL_MIGRATIONS = {
|
|
|
2761
2836
|
"20261004120000_models_site_scope": _20261004120000_models_site_scope_exports$1,
|
|
2762
2837
|
"20261004130000_site_seo_settings": _20261004130000_site_seo_settings_exports$1,
|
|
2763
2838
|
"20261005120000_entry_heads_entry_created_at": _20261005120000_entry_heads_entry_created_at_exports$1,
|
|
2764
|
-
"20261006120000_system_versions_release": _20261006120000_system_versions_release_exports
|
|
2839
|
+
"20261006120000_system_versions_release": _20261006120000_system_versions_release_exports,
|
|
2840
|
+
"20261014120000_canceled_status": _20261014120000_canceled_status_exports$1
|
|
2765
2841
|
};
|
|
2766
2842
|
//#endregion
|
|
2767
2843
|
//#region ../../apps/api/src/db/migrations/sqlite/0001_baseline.ts
|
|
2768
2844
|
var _0001_baseline_exports = /* @__PURE__ */ __exportAll({
|
|
2769
|
-
down: () => down$
|
|
2770
|
-
up: () => up$
|
|
2845
|
+
down: () => down$5,
|
|
2846
|
+
up: () => up$5
|
|
2771
2847
|
});
|
|
2772
2848
|
/**
|
|
2773
2849
|
* SQLite baseline: Shapio's whole system schema as of PostgreSQL migration
|
|
@@ -3850,7 +3926,7 @@ const STATEMENTS = [
|
|
|
3850
3926
|
('00000000-0000-4000-b000-000000000001', 'public', '00000000-0000-4000-a000-000000000001'),
|
|
3851
3927
|
('00000000-0000-4000-b000-000000000001', 'authenticated', '00000000-0000-4000-a000-000000000002')`
|
|
3852
3928
|
];
|
|
3853
|
-
const TABLES = [
|
|
3929
|
+
const TABLES$1 = [
|
|
3854
3930
|
"system_versions",
|
|
3855
3931
|
"jobs",
|
|
3856
3932
|
"outbox_events",
|
|
@@ -3912,18 +3988,18 @@ const TABLES = [
|
|
|
3912
3988
|
"assist_runs",
|
|
3913
3989
|
"sequences"
|
|
3914
3990
|
];
|
|
3915
|
-
const up$
|
|
3991
|
+
const up$5 = async (db) => {
|
|
3916
3992
|
for (const statement of STATEMENTS) await sql.raw(statement).execute(db);
|
|
3917
3993
|
};
|
|
3918
|
-
const down$
|
|
3994
|
+
const down$5 = async (db) => {
|
|
3919
3995
|
await sql`pragma defer_foreign_keys = on`.execute(db);
|
|
3920
|
-
for (const table of [...TABLES].reverse()) await sql.raw(`drop table if exists "${table}"`).execute(db);
|
|
3996
|
+
for (const table of [...TABLES$1].reverse()) await sql.raw(`drop table if exists "${table}"`).execute(db);
|
|
3921
3997
|
};
|
|
3922
3998
|
//#endregion
|
|
3923
3999
|
//#region ../../apps/api/src/db/migrations/sqlite/20261003170000_audit_events_seq.ts
|
|
3924
4000
|
var _20261003170000_audit_events_seq_exports = /* @__PURE__ */ __exportAll({
|
|
3925
|
-
down: () => down$
|
|
3926
|
-
up: () => up$
|
|
4001
|
+
down: () => down$4,
|
|
4002
|
+
up: () => up$4
|
|
3927
4003
|
});
|
|
3928
4004
|
/**
|
|
3929
4005
|
* SQLite twin of `../20261003170000_audit_events_seq.ts`. SQLite cannot add a column whose default calls a
|
|
@@ -3950,7 +4026,7 @@ const INDEXES = [
|
|
|
3950
4026
|
`create index "audit_events_occurred_at_idx" on "audit_events" (occurred_at DESC)`,
|
|
3951
4027
|
`create index "audit_events_target_idx" on "audit_events" (target_type, target_id, occurred_at DESC)`
|
|
3952
4028
|
];
|
|
3953
|
-
const up$
|
|
4029
|
+
const up$4 = async (db) => {
|
|
3954
4030
|
await sql`insert into "sequences" (name, value) values ('audit_events_seq', 0)`.execute(db);
|
|
3955
4031
|
await sql`alter table "audit_events" rename to "audit_events_before_seq"`.execute(db);
|
|
3956
4032
|
await sql`create table "audit_events" (
|
|
@@ -3978,15 +4054,15 @@ const up$3 = async (db) => {
|
|
|
3978
4054
|
await sql`drop table "audit_events_before_seq"`.execute(db);
|
|
3979
4055
|
for (const statement of INDEXES) await sql.raw(statement).execute(db);
|
|
3980
4056
|
};
|
|
3981
|
-
const down$
|
|
4057
|
+
const down$4 = async (db) => {
|
|
3982
4058
|
await sql`alter table "audit_events" drop column "seq"`.execute(db);
|
|
3983
4059
|
await sql`delete from "sequences" where name = 'audit_events_seq'`.execute(db);
|
|
3984
4060
|
};
|
|
3985
4061
|
//#endregion
|
|
3986
4062
|
//#region ../../apps/api/src/db/migrations/sqlite/20261004120000_models_site_scope.ts
|
|
3987
4063
|
var _20261004120000_models_site_scope_exports = /* @__PURE__ */ __exportAll({
|
|
3988
|
-
down: () => down$
|
|
3989
|
-
up: () => up$
|
|
4064
|
+
down: () => down$3,
|
|
4065
|
+
up: () => up$3
|
|
3990
4066
|
});
|
|
3991
4067
|
/**
|
|
3992
4068
|
* SQLite twin of `../20261004120000_models_site_scope.ts`. `down` rebuilds `models` without `site_id`
|
|
@@ -3996,7 +4072,7 @@ var _20261004120000_models_site_scope_exports = /* @__PURE__ */ __exportAll({
|
|
|
3996
4072
|
* deletes nothing they reference.
|
|
3997
4073
|
*/
|
|
3998
4074
|
const NIL_UUID = "00000000-0000-0000-0000-000000000000";
|
|
3999
|
-
const up$
|
|
4075
|
+
const up$3 = async (db) => {
|
|
4000
4076
|
await sql`alter table "models" add column "site_id" text_uuid references sites (id)`.execute(db);
|
|
4001
4077
|
await sql`create index "models_site_idx" on "models" (site_id)`.execute(db);
|
|
4002
4078
|
await sql`drop index "models_api_key_uq"`.execute(db);
|
|
@@ -4006,7 +4082,7 @@ const up$2 = async (db) => {
|
|
|
4006
4082
|
`.execute(db);
|
|
4007
4083
|
await sql`alter table "schema_drafts" add column "shared" integer_boolean not null default 0`.execute(db);
|
|
4008
4084
|
};
|
|
4009
|
-
const down$
|
|
4085
|
+
const down$3 = async (db) => {
|
|
4010
4086
|
const { rows } = await sql`select count(*) as count from "models" where site_id is not null`.execute(db);
|
|
4011
4087
|
if (Number(rows[0]?.count ?? 0) > 0) throw new Error("Cannot roll back per-site schema while definitions belong to a site: two sites may share an API ID. Share or delete the site definitions first.");
|
|
4012
4088
|
await sql`alter table "schema_drafts" drop column "shared"`.execute(db);
|
|
@@ -4031,15 +4107,15 @@ const down$2 = async (db) => {
|
|
|
4031
4107
|
//#endregion
|
|
4032
4108
|
//#region ../../apps/api/src/db/migrations/sqlite/20261004130000_site_seo_settings.ts
|
|
4033
4109
|
var _20261004130000_site_seo_settings_exports = /* @__PURE__ */ __exportAll({
|
|
4034
|
-
down: () => down$
|
|
4035
|
-
up: () => up$
|
|
4110
|
+
down: () => down$2,
|
|
4111
|
+
up: () => up$2
|
|
4036
4112
|
});
|
|
4037
4113
|
/**
|
|
4038
4114
|
* SQLite twin of `../20261004130000_site_seo_settings.ts`. `insert or ignore` stands in for `on conflict do
|
|
4039
4115
|
* nothing` (the grant's unique index); the permissions version moves only when a grant was added or removed.
|
|
4040
4116
|
*/
|
|
4041
4117
|
const bumpPermissionsVersion = (db) => sql`update "system_versions" set permissions_version = permissions_version + 1, updated_at = shapio_now()`.execute(db);
|
|
4042
|
-
const up$
|
|
4118
|
+
const up$2 = async (db) => {
|
|
4043
4119
|
await sql`alter table "sites" add column "seo_defaults" text_jsonb`.execute(db);
|
|
4044
4120
|
const granted = await sql`
|
|
4045
4121
|
insert or ignore into "admin_role_permissions" (role_id, action, model_id, condition, field_ids)
|
|
@@ -4049,7 +4125,7 @@ const up$1 = async (db) => {
|
|
|
4049
4125
|
`.execute(db);
|
|
4050
4126
|
if (Number(granted.numAffectedRows ?? 0) > 0) await bumpPermissionsVersion(db);
|
|
4051
4127
|
};
|
|
4052
|
-
const down$
|
|
4128
|
+
const down$2 = async (db) => {
|
|
4053
4129
|
const revoked = await sql`delete from "admin_role_permissions" where action = 'site.settings'`.execute(db);
|
|
4054
4130
|
if (Number(revoked.numAffectedRows ?? 0) > 0) await bumpPermissionsVersion(db);
|
|
4055
4131
|
await sql`alter table "sites" drop column "seo_defaults"`.execute(db);
|
|
@@ -4057,8 +4133,8 @@ const down$1 = async (db) => {
|
|
|
4057
4133
|
//#endregion
|
|
4058
4134
|
//#region ../../apps/api/src/db/migrations/sqlite/20261005120000_entry_heads_entry_created_at.ts
|
|
4059
4135
|
var _20261005120000_entry_heads_entry_created_at_exports = /* @__PURE__ */ __exportAll({
|
|
4060
|
-
down: () => down,
|
|
4061
|
-
up: () => up
|
|
4136
|
+
down: () => down$1,
|
|
4137
|
+
up: () => up$1
|
|
4062
4138
|
});
|
|
4063
4139
|
/**
|
|
4064
4140
|
* SQLite twin of `../20261005120000_entry_heads_entry_created_at.ts`. One process holds the write lock, so
|
|
@@ -4066,18 +4142,61 @@ var _20261005120000_entry_heads_entry_created_at_exports = /* @__PURE__ */ __exp
|
|
|
4066
4142
|
* documented single-process limitation of ADR 0001, "D2: as built").
|
|
4067
4143
|
*/
|
|
4068
4144
|
const INDEX = "entry_heads_entry_order_idx";
|
|
4069
|
-
const up = async (db) => {
|
|
4145
|
+
const up$1 = async (db) => {
|
|
4070
4146
|
await sql`alter table "entry_heads" add column "entry_created_at" text_timestamptz`.execute(db);
|
|
4071
4147
|
await sql`update "entry_heads" set entry_created_at = (
|
|
4072
4148
|
select e.created_at from "entries" e where e.id = "entry_heads".entry_id
|
|
4073
4149
|
) where entry_created_at is null`.execute(db);
|
|
4074
4150
|
await sql`create index ${sql.id(INDEX)} on "entry_heads" (site_id, model_id, state, entry_created_at desc, entry_id)`.execute(db);
|
|
4075
4151
|
};
|
|
4076
|
-
const down = async (db) => {
|
|
4152
|
+
const down$1 = async (db) => {
|
|
4077
4153
|
await sql`drop index if exists ${sql.id(INDEX)}`.execute(db);
|
|
4078
4154
|
await sql`alter table "entry_heads" drop column "entry_created_at"`.execute(db);
|
|
4079
4155
|
};
|
|
4080
4156
|
//#endregion
|
|
4157
|
+
//#region ../../apps/api/src/db/migrations/sqlite/20261014120000_canceled_status.ts
|
|
4158
|
+
var _20261014120000_canceled_status_exports = /* @__PURE__ */ __exportAll({
|
|
4159
|
+
down: () => down,
|
|
4160
|
+
up: () => up
|
|
4161
|
+
});
|
|
4162
|
+
/**
|
|
4163
|
+
* SQLite twin of `../20261014120000_canceled_status.ts`. SQLite cannot change a check constraint, so each
|
|
4164
|
+
* table is rebuilt from its own stored `create table` statement with the one value swapped: renamed aside
|
|
4165
|
+
* (with `legacy_alter_table` on, so references to the name keep pointing at it), recreated, refilled with the
|
|
4166
|
+
* status rewritten, and its indexes recreated from `sqlite_master`. Nothing references either table.
|
|
4167
|
+
*/
|
|
4168
|
+
const TABLES = ["schema_change_jobs", "scheduled_publications"];
|
|
4169
|
+
const rebuild = async (db, table, from, to) => {
|
|
4170
|
+
const { rows: created } = await sql`
|
|
4171
|
+
select sql from sqlite_master where type = 'table' and name = ${table}
|
|
4172
|
+
`.execute(db);
|
|
4173
|
+
const { rows: indexes } = await sql`
|
|
4174
|
+
select sql from sqlite_master where type = 'index' and tbl_name = ${table} and sql is not null
|
|
4175
|
+
`.execute(db);
|
|
4176
|
+
const definition = created[0]?.sql;
|
|
4177
|
+
if (!definition || !definition.includes(`'${from}'`)) throw new Error(`${table}: expected a status check allowing '${from}'`);
|
|
4178
|
+
const repaired = definition.replace(/references\s+("?)(\w+?)_before_\w+\1/gi, (_, quote, base) => `references ${quote}${base}${quote}`);
|
|
4179
|
+
const aside = `${table}_before_${to}`;
|
|
4180
|
+
await sql`pragma legacy_alter_table = on`.execute(db);
|
|
4181
|
+
await sql`alter table ${sql.table(table)} rename to ${sql.table(aside)}`.execute(db);
|
|
4182
|
+
await sql.raw(repaired.replace(`'${from}'`, `'${to}'`)).execute(db);
|
|
4183
|
+
const { rows: columns } = await sql`
|
|
4184
|
+
select name from pragma_table_info(${aside}) order by cid
|
|
4185
|
+
`.execute(db);
|
|
4186
|
+
const names = columns.map(({ name }) => sql.id(name));
|
|
4187
|
+
const values = columns.map(({ name }) => name === "status" ? sql`case when status = ${from} then ${to} else status end` : sql.id(name));
|
|
4188
|
+
await sql`insert into ${sql.table(table)} (${sql.join(names)}) select ${sql.join(values)} from ${sql.table(aside)}`.execute(db);
|
|
4189
|
+
await sql`drop table ${sql.table(aside)}`.execute(db);
|
|
4190
|
+
await sql`pragma legacy_alter_table = off`.execute(db);
|
|
4191
|
+
for (const { sql: index } of indexes) await sql.raw(index).execute(db);
|
|
4192
|
+
};
|
|
4193
|
+
const up = async (db) => {
|
|
4194
|
+
for (const table of TABLES) await rebuild(db, table, "cancelled", "canceled");
|
|
4195
|
+
};
|
|
4196
|
+
const down = async (db) => {
|
|
4197
|
+
for (const table of TABLES) await rebuild(db, table, "canceled", "cancelled");
|
|
4198
|
+
};
|
|
4199
|
+
//#endregion
|
|
4081
4200
|
//#region ../../apps/api/src/db/migrations/sqlite/index.ts
|
|
4082
4201
|
const SQLITE_MIGRATIONS = {
|
|
4083
4202
|
"0001_baseline": _0001_baseline_exports,
|
|
@@ -4085,7 +4204,8 @@ const SQLITE_MIGRATIONS = {
|
|
|
4085
4204
|
"20261004120000_models_site_scope": _20261004120000_models_site_scope_exports,
|
|
4086
4205
|
"20261004130000_site_seo_settings": _20261004130000_site_seo_settings_exports,
|
|
4087
4206
|
"20261005120000_entry_heads_entry_created_at": _20261005120000_entry_heads_entry_created_at_exports,
|
|
4088
|
-
"20261006120000_system_versions_release": _20261006120000_system_versions_release_exports
|
|
4207
|
+
"20261006120000_system_versions_release": _20261006120000_system_versions_release_exports,
|
|
4208
|
+
"20261014120000_canceled_status": _20261014120000_canceled_status_exports
|
|
4089
4209
|
};
|
|
4090
4210
|
//#endregion
|
|
4091
4211
|
//#region ../../apps/api/src/db/migrations/index.ts
|
|
@@ -4119,7 +4239,8 @@ const MIGRATIONS = {
|
|
|
4119
4239
|
"20261004120000_models_site_scope": _20261004120000_models_site_scope_exports$2,
|
|
4120
4240
|
"20261004130000_site_seo_settings": _20261004130000_site_seo_settings_exports$2,
|
|
4121
4241
|
"20261005120000_entry_heads_entry_created_at": _20261005120000_entry_heads_entry_created_at_exports$2,
|
|
4122
|
-
"20261006120000_system_versions_release": _20261006120000_system_versions_release_exports
|
|
4242
|
+
"20261006120000_system_versions_release": _20261006120000_system_versions_release_exports,
|
|
4243
|
+
"20261014120000_canceled_status": _20261014120000_canceled_status_exports$2
|
|
4123
4244
|
};
|
|
4124
4245
|
const PROVIDERS = {
|
|
4125
4246
|
postgres: { getMigrations: () => Promise.resolve({ ...MIGRATIONS }) },
|
|
@@ -4149,4 +4270,4 @@ const getPendingMigrations = async (db) => {
|
|
|
4149
4270
|
//#endregion
|
|
4150
4271
|
export { getPendingMigrations };
|
|
4151
4272
|
|
|
4152
|
-
//# sourceMappingURL=migrator-
|
|
4273
|
+
//# sourceMappingURL=migrator-BfVtncOo.js.map
|