@krantho/persistence-sqlite 0.0.0-stage → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/auth-adapter.d.ts +23 -0
- package/dist/auth-adapter.d.ts.map +1 -0
- package/dist/auth-adapter.js +159 -0
- package/dist/auth-adapter.js.map +1 -0
- package/dist/checkpoints.d.ts +20 -0
- package/dist/checkpoints.d.ts.map +1 -0
- package/dist/checkpoints.js +119 -0
- package/dist/checkpoints.js.map +1 -0
- package/dist/connection.d.ts +29 -0
- package/dist/connection.d.ts.map +1 -0
- package/dist/connection.js +77 -0
- package/dist/connection.js.map +1 -0
- package/dist/content-migration.d.ts +18 -0
- package/dist/content-migration.d.ts.map +1 -0
- package/dist/content-migration.js +68 -0
- package/dist/content-migration.js.map +1 -0
- package/dist/content-query.d.ts +16 -0
- package/dist/content-query.d.ts.map +1 -0
- package/dist/content-query.js +155 -0
- package/dist/content-query.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/lock-adapter.d.ts +11 -0
- package/dist/lock-adapter.d.ts.map +1 -0
- package/dist/lock-adapter.js +63 -0
- package/dist/lock-adapter.js.map +1 -0
- package/dist/media-adapter.d.ts +27 -0
- package/dist/media-adapter.d.ts.map +1 -0
- package/dist/media-adapter.js +175 -0
- package/dist/media-adapter.js.map +1 -0
- package/dist/media-folder-adapter.d.ts +13 -0
- package/dist/media-folder-adapter.d.ts.map +1 -0
- package/dist/media-folder-adapter.js +58 -0
- package/dist/media-folder-adapter.js.map +1 -0
- package/dist/migration-runner.d.ts +28 -0
- package/dist/migration-runner.d.ts.map +1 -0
- package/dist/migration-runner.js +109 -0
- package/dist/migration-runner.js.map +1 -0
- package/dist/migrations/index.d.ts +4 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +32 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/migrations/v001-initial-schema.d.ts +10 -0
- package/dist/migrations/v001-initial-schema.d.ts.map +1 -0
- package/dist/migrations/v001-initial-schema.js +94 -0
- package/dist/migrations/v001-initial-schema.js.map +1 -0
- package/dist/migrations/v002-auth-tables.d.ts +9 -0
- package/dist/migrations/v002-auth-tables.d.ts.map +1 -0
- package/dist/migrations/v002-auth-tables.js +38 -0
- package/dist/migrations/v002-auth-tables.js.map +1 -0
- package/dist/migrations/v003-user-permissions.d.ts +9 -0
- package/dist/migrations/v003-user-permissions.d.ts.map +1 -0
- package/dist/migrations/v003-user-permissions.js +21 -0
- package/dist/migrations/v003-user-permissions.js.map +1 -0
- package/dist/migrations/v004-media-hotspot.d.ts +14 -0
- package/dist/migrations/v004-media-hotspot.d.ts.map +1 -0
- package/dist/migrations/v004-media-hotspot.js +24 -0
- package/dist/migrations/v004-media-hotspot.js.map +1 -0
- package/dist/migrations/v005-content-locks.d.ts +9 -0
- package/dist/migrations/v005-content-locks.d.ts.map +1 -0
- package/dist/migrations/v005-content-locks.js +24 -0
- package/dist/migrations/v005-content-locks.js.map +1 -0
- package/dist/migrations/v006-webhook-deliveries.d.ts +6 -0
- package/dist/migrations/v006-webhook-deliveries.d.ts.map +1 -0
- package/dist/migrations/v006-webhook-deliveries.js +24 -0
- package/dist/migrations/v006-webhook-deliveries.js.map +1 -0
- package/dist/migrations/v007-media-folders.d.ts +10 -0
- package/dist/migrations/v007-media-folders.d.ts.map +1 -0
- package/dist/migrations/v007-media-folders.js +23 -0
- package/dist/migrations/v007-media-folders.js.map +1 -0
- package/dist/migrations/v008-site-settings.d.ts +9 -0
- package/dist/migrations/v008-site-settings.d.ts.map +1 -0
- package/dist/migrations/v008-site-settings.js +20 -0
- package/dist/migrations/v008-site-settings.js.map +1 -0
- package/dist/migrations/v009-seo-config.d.ts +15 -0
- package/dist/migrations/v009-seo-config.d.ts.map +1 -0
- package/dist/migrations/v009-seo-config.js +29 -0
- package/dist/migrations/v009-seo-config.js.map +1 -0
- package/dist/migrations/v010-content-live-version.d.ts +15 -0
- package/dist/migrations/v010-content-live-version.d.ts.map +1 -0
- package/dist/migrations/v010-content-live-version.js +40 -0
- package/dist/migrations/v010-content-live-version.js.map +1 -0
- package/dist/migrations/v011-media.d.ts +12 -0
- package/dist/migrations/v011-media.d.ts.map +1 -0
- package/dist/migrations/v011-media.js +43 -0
- package/dist/migrations/v011-media.js.map +1 -0
- package/dist/migrations/v012-page-cache.d.ts +12 -0
- package/dist/migrations/v012-page-cache.d.ts.map +1 -0
- package/dist/migrations/v012-page-cache.js +31 -0
- package/dist/migrations/v012-page-cache.js.map +1 -0
- package/dist/migrations/v013-content-contracts.d.ts +17 -0
- package/dist/migrations/v013-content-contracts.d.ts.map +1 -0
- package/dist/migrations/v013-content-contracts.js +46 -0
- package/dist/migrations/v013-content-contracts.js.map +1 -0
- package/dist/migrations/v014-content-manifest-commit.d.ts +7 -0
- package/dist/migrations/v014-content-manifest-commit.d.ts.map +1 -0
- package/dist/migrations/v014-content-manifest-commit.js +12 -0
- package/dist/migrations/v014-content-manifest-commit.js.map +1 -0
- package/dist/page-cache-store.d.ts +17 -0
- package/dist/page-cache-store.d.ts.map +1 -0
- package/dist/page-cache-store.js +76 -0
- package/dist/page-cache-store.js.map +1 -0
- package/dist/queries.d.ts +82 -0
- package/dist/queries.d.ts.map +1 -0
- package/dist/queries.js +25 -0
- package/dist/queries.js.map +1 -0
- package/dist/retention-adapter.d.ts +13 -0
- package/dist/retention-adapter.d.ts.map +1 -0
- package/dist/retention-adapter.js +62 -0
- package/dist/retention-adapter.js.map +1 -0
- package/dist/row-mapping.d.ts +14 -0
- package/dist/row-mapping.d.ts.map +1 -0
- package/dist/row-mapping.js +71 -0
- package/dist/row-mapping.js.map +1 -0
- package/dist/seo-config-adapter.d.ts +14 -0
- package/dist/seo-config-adapter.d.ts.map +1 -0
- package/dist/seo-config-adapter.js +57 -0
- package/dist/seo-config-adapter.js.map +1 -0
- package/dist/site-settings-adapter.d.ts +10 -0
- package/dist/site-settings-adapter.d.ts.map +1 -0
- package/dist/site-settings-adapter.js +27 -0
- package/dist/site-settings-adapter.js.map +1 -0
- package/dist/sqlite-adapter.d.ts +69 -0
- package/dist/sqlite-adapter.d.ts.map +1 -0
- package/dist/sqlite-adapter.js +242 -0
- package/dist/sqlite-adapter.js.map +1 -0
- package/dist/webhook-delivery-adapter.d.ts +27 -0
- package/dist/webhook-delivery-adapter.d.ts.map +1 -0
- package/dist/webhook-delivery-adapter.js +93 -0
- package/dist/webhook-delivery-adapter.js.map +1 -0
- package/package.json +37 -3
- package/README.md +0 -3
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { migrationFailedMessage, resolveCurrentVersion, validateChecksums, } from '@krantho/persistence';
|
|
3
|
+
/** Compute SHA-256 checksum of a migration's identity */
|
|
4
|
+
function computeChecksum(migration) {
|
|
5
|
+
const content = `v${migration.version}:${migration.name}`;
|
|
6
|
+
return createHash('sha256').update(content).digest('hex');
|
|
7
|
+
}
|
|
8
|
+
const CREATE_SCHEMA_MIGRATIONS = `
|
|
9
|
+
CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
10
|
+
version INTEGER PRIMARY KEY,
|
|
11
|
+
name TEXT NOT NULL,
|
|
12
|
+
checksum TEXT NOT NULL,
|
|
13
|
+
applied_at TEXT NOT NULL
|
|
14
|
+
)`;
|
|
15
|
+
/** Read the applied-migration ledger, or null when it has not been created yet */
|
|
16
|
+
function readLedger(db) {
|
|
17
|
+
const tableExists = db
|
|
18
|
+
.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='schema_migrations'")
|
|
19
|
+
.get();
|
|
20
|
+
if (!tableExists)
|
|
21
|
+
return null;
|
|
22
|
+
const rows = db
|
|
23
|
+
.prepare('SELECT version, name, checksum, applied_at FROM schema_migrations ORDER BY version')
|
|
24
|
+
.all();
|
|
25
|
+
return new Map(rows.map((m) => [m.version, m]));
|
|
26
|
+
}
|
|
27
|
+
/** Apply one migration and record it, rolling back that migration alone on failure */
|
|
28
|
+
function applyMigration(db, migration, checksum, appliedAt) {
|
|
29
|
+
const run = db.transaction(() => {
|
|
30
|
+
migration.apply(db);
|
|
31
|
+
db.prepare('INSERT INTO schema_migrations (version, name, checksum, applied_at) VALUES (?, ?, ?, ?)').run(migration.version, migration.name, checksum, appliedAt);
|
|
32
|
+
});
|
|
33
|
+
try {
|
|
34
|
+
run();
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
throw new Error(migrationFailedMessage(migration.version, migration.name, err));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** Apply every pending migration. Must run while holding the database write lock. */
|
|
41
|
+
function applyPending(db, migrations) {
|
|
42
|
+
db.exec(CREATE_SCHEMA_MIGRATIONS);
|
|
43
|
+
const ledger = readLedger(db) ?? new Map();
|
|
44
|
+
validateChecksums(migrations, ledger, computeChecksum);
|
|
45
|
+
const newlyApplied = [];
|
|
46
|
+
for (const migration of [...migrations].sort((a, b) => a.version - b.version)) {
|
|
47
|
+
if (ledger.has(migration.version))
|
|
48
|
+
continue;
|
|
49
|
+
const checksum = computeChecksum(migration);
|
|
50
|
+
const appliedAt = new Date().toISOString();
|
|
51
|
+
applyMigration(db, migration, checksum, appliedAt);
|
|
52
|
+
newlyApplied.push({ version: migration.version, name: migration.name, checksum, appliedAt });
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
applied: newlyApplied,
|
|
56
|
+
currentVersion: resolveCurrentVersion(ledger.keys(), newlyApplied),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Run pending migrations on a SQLite database.
|
|
61
|
+
*
|
|
62
|
+
* Self-bootstrapping: creates the schema_migrations table if it doesn't exist.
|
|
63
|
+
* Each migration runs inside a transaction. Halts on first failure.
|
|
64
|
+
*
|
|
65
|
+
* Deciding what is pending and applying it is a check-then-act, so it runs inside
|
|
66
|
+
* a BEGIN IMMEDIATE transaction: the write lock is taken before the ledger is read
|
|
67
|
+
* and held until the last migration is recorded. Several processes may open the
|
|
68
|
+
* same database file at once — a server, a CLI, a framework spawning one build
|
|
69
|
+
* worker per core — and without the lock they all read an empty ledger and race to
|
|
70
|
+
* create the same tables. The loser waits on the connection's busy timeout and then
|
|
71
|
+
* re-reads the ledger inside the lock, finding the work already done.
|
|
72
|
+
*/
|
|
73
|
+
export function runMigrations(db, migrations) {
|
|
74
|
+
// Fast path — an already-migrated database is the common case, and reading the
|
|
75
|
+
// ledger without the write lock is safe because "every migration is applied" is
|
|
76
|
+
// a state no concurrent migration run can take away.
|
|
77
|
+
const ledger = readLedger(db);
|
|
78
|
+
if (ledger) {
|
|
79
|
+
validateChecksums(migrations, ledger, computeChecksum);
|
|
80
|
+
if (migrations.every((m) => ledger.has(m.version))) {
|
|
81
|
+
return { applied: [], currentVersion: resolveCurrentVersion(ledger.keys(), []) };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return db.transaction(() => applyPending(db, migrations)).immediate();
|
|
85
|
+
}
|
|
86
|
+
/** Get the current schema version from the database */
|
|
87
|
+
export function getSchemaVersion(db) {
|
|
88
|
+
// Check if schema_migrations table exists
|
|
89
|
+
const tableExists = db
|
|
90
|
+
.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='schema_migrations'")
|
|
91
|
+
.get();
|
|
92
|
+
if (!tableExists)
|
|
93
|
+
return 0;
|
|
94
|
+
const row = db.prepare('SELECT MAX(version) as max_version FROM schema_migrations').get();
|
|
95
|
+
return row?.max_version ?? 0;
|
|
96
|
+
}
|
|
97
|
+
/** Get all applied migrations */
|
|
98
|
+
export function getAppliedMigrations(db) {
|
|
99
|
+
const ledger = readLedger(db);
|
|
100
|
+
if (!ledger)
|
|
101
|
+
return [];
|
|
102
|
+
return [...ledger.values()].map((r) => ({
|
|
103
|
+
version: r.version,
|
|
104
|
+
name: r.name,
|
|
105
|
+
checksum: r.checksum,
|
|
106
|
+
appliedAt: r.applied_at,
|
|
107
|
+
}));
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=migration-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration-runner.js","sourceRoot":"","sources":["../src/migration-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAgB7D,yDAAyD;AACzD,eAAO,MAAM,gBAAgB,EAAE,SAAS,eAAe,EAetD,CAAA"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { v001InitialSchema } from './v001-initial-schema.js';
|
|
2
|
+
import { v002AuthTables } from './v002-auth-tables.js';
|
|
3
|
+
import { v003UserPermissions } from './v003-user-permissions.js';
|
|
4
|
+
import { v004MediaHotspot } from './v004-media-hotspot.js';
|
|
5
|
+
import { v005ContentLocks } from './v005-content-locks.js';
|
|
6
|
+
import { v006WebhookDeliveries } from './v006-webhook-deliveries.js';
|
|
7
|
+
import { v007MediaFolders } from './v007-media-folders.js';
|
|
8
|
+
import { v008SiteSettings } from './v008-site-settings.js';
|
|
9
|
+
import { v009SeoConfig } from './v009-seo-config.js';
|
|
10
|
+
import { v010ContentLiveVersion } from './v010-content-live-version.js';
|
|
11
|
+
import { v011Media } from './v011-media.js';
|
|
12
|
+
import { v012PageCache } from './v012-page-cache.js';
|
|
13
|
+
import { v013ContentContracts } from './v013-content-contracts.js';
|
|
14
|
+
import { v014ContentManifestCommit } from './v014-content-manifest-commit.js';
|
|
15
|
+
/** All registered SQLite migrations, in version order */
|
|
16
|
+
export const sqliteMigrations = [
|
|
17
|
+
v001InitialSchema,
|
|
18
|
+
v002AuthTables,
|
|
19
|
+
v003UserPermissions,
|
|
20
|
+
v004MediaHotspot,
|
|
21
|
+
v005ContentLocks,
|
|
22
|
+
v006WebhookDeliveries,
|
|
23
|
+
v007MediaFolders,
|
|
24
|
+
v008SiteSettings,
|
|
25
|
+
v009SeoConfig,
|
|
26
|
+
v010ContentLiveVersion,
|
|
27
|
+
v011Media,
|
|
28
|
+
v012PageCache,
|
|
29
|
+
v013ContentContracts,
|
|
30
|
+
v014ContentManifestCommit,
|
|
31
|
+
];
|
|
32
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAA;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAA;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AAClE,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAA;AAE7E,yDAAyD;AACzD,MAAM,CAAC,MAAM,gBAAgB,GAA+B;IAC1D,iBAAiB;IACjB,cAAc;IACd,mBAAmB;IACnB,gBAAgB;IAChB,gBAAgB;IAChB,qBAAqB;IACrB,gBAAgB;IAChB,gBAAgB;IAChB,aAAa;IACb,sBAAsB;IACtB,SAAS;IACT,aAAa;IACb,oBAAoB;IACpB,yBAAyB;CAC1B,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SqliteMigration } from '../migration-runner.js';
|
|
2
|
+
/**
|
|
3
|
+
* V001: Initial schema — all core tables for content, schemas, manifests,
|
|
4
|
+
* and checkpoints using the append-only versioning model.
|
|
5
|
+
*
|
|
6
|
+
* Content and collection_schemas use append-only rows with `is_current`
|
|
7
|
+
* flags and `version` columns. Every write creates a new row.
|
|
8
|
+
*/
|
|
9
|
+
export declare const v001InitialSchema: SqliteMigration;
|
|
10
|
+
//# sourceMappingURL=v001-initial-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v001-initial-schema.d.ts","sourceRoot":"","sources":["../../src/migrations/v001-initial-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAE7D;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,EAAE,eA0G/B,CAAA"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V001: Initial schema — all core tables for content, schemas, manifests,
|
|
3
|
+
* and checkpoints using the append-only versioning model.
|
|
4
|
+
*
|
|
5
|
+
* Content and collection_schemas use append-only rows with `is_current`
|
|
6
|
+
* flags and `version` columns. Every write creates a new row.
|
|
7
|
+
*/
|
|
8
|
+
export const v001InitialSchema = {
|
|
9
|
+
version: 1,
|
|
10
|
+
name: 'initial_schema',
|
|
11
|
+
apply: (db) => {
|
|
12
|
+
// --- Content (append-only) ---
|
|
13
|
+
db.exec(`
|
|
14
|
+
CREATE TABLE content (
|
|
15
|
+
id TEXT PRIMARY KEY,
|
|
16
|
+
collection TEXT NOT NULL,
|
|
17
|
+
slug TEXT NOT NULL,
|
|
18
|
+
locale TEXT NOT NULL DEFAULT 'en',
|
|
19
|
+
version INTEGER NOT NULL,
|
|
20
|
+
is_current INTEGER NOT NULL DEFAULT 1,
|
|
21
|
+
status TEXT NOT NULL DEFAULT 'draft',
|
|
22
|
+
fields TEXT NOT NULL,
|
|
23
|
+
body TEXT NOT NULL,
|
|
24
|
+
html TEXT NOT NULL DEFAULT '',
|
|
25
|
+
sections TEXT NOT NULL DEFAULT '{}',
|
|
26
|
+
source TEXT NOT NULL DEFAULT 'api',
|
|
27
|
+
file_path TEXT,
|
|
28
|
+
changed_by TEXT,
|
|
29
|
+
deleted_at TEXT,
|
|
30
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
31
|
+
UNIQUE(collection, slug, locale, version)
|
|
32
|
+
)
|
|
33
|
+
`);
|
|
34
|
+
db.exec('CREATE INDEX idx_content_current ON content(collection, slug, locale) WHERE is_current = 1');
|
|
35
|
+
db.exec('CREATE INDEX idx_content_collection_status ON content(collection, status) WHERE is_current = 1');
|
|
36
|
+
db.exec('CREATE INDEX idx_content_slug ON content(slug) WHERE is_current = 1');
|
|
37
|
+
// --- Collection schemas (append-only) ---
|
|
38
|
+
db.exec(`
|
|
39
|
+
CREATE TABLE collection_schemas (
|
|
40
|
+
row_id TEXT PRIMARY KEY,
|
|
41
|
+
collection TEXT NOT NULL,
|
|
42
|
+
version INTEGER NOT NULL,
|
|
43
|
+
is_current INTEGER NOT NULL DEFAULT 1,
|
|
44
|
+
fields TEXT NOT NULL,
|
|
45
|
+
changed_by TEXT,
|
|
46
|
+
deleted_at TEXT,
|
|
47
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
48
|
+
UNIQUE(collection, version)
|
|
49
|
+
)
|
|
50
|
+
`);
|
|
51
|
+
db.exec('CREATE INDEX idx_schemas_current ON collection_schemas(collection) WHERE is_current = 1');
|
|
52
|
+
// --- Content manifest ---
|
|
53
|
+
db.exec(`
|
|
54
|
+
CREATE TABLE content_manifest (
|
|
55
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
56
|
+
repo_version INTEGER NOT NULL,
|
|
57
|
+
imported_at TEXT NOT NULL,
|
|
58
|
+
file_checksums TEXT NOT NULL
|
|
59
|
+
)
|
|
60
|
+
`);
|
|
61
|
+
db.exec(`
|
|
62
|
+
CREATE TABLE content_migration_conflicts (
|
|
63
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
64
|
+
migration_id INTEGER NOT NULL,
|
|
65
|
+
collection TEXT NOT NULL,
|
|
66
|
+
slug TEXT NOT NULL,
|
|
67
|
+
repo_checksum TEXT NOT NULL,
|
|
68
|
+
db_checksum TEXT NOT NULL,
|
|
69
|
+
resolved INTEGER DEFAULT 0,
|
|
70
|
+
resolved_at TEXT,
|
|
71
|
+
resolution TEXT
|
|
72
|
+
)
|
|
73
|
+
`);
|
|
74
|
+
db.exec('CREATE INDEX idx_content_conflicts_unresolved ON content_migration_conflicts(resolved) WHERE resolved = 0');
|
|
75
|
+
// --- Checkpoints ---
|
|
76
|
+
db.exec(`
|
|
77
|
+
CREATE TABLE checkpoints (
|
|
78
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
79
|
+
version INTEGER NOT NULL UNIQUE,
|
|
80
|
+
name TEXT,
|
|
81
|
+
trigger TEXT NOT NULL,
|
|
82
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
83
|
+
)
|
|
84
|
+
`);
|
|
85
|
+
db.exec(`
|
|
86
|
+
CREATE TABLE checkpoint_counter (
|
|
87
|
+
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
88
|
+
next INTEGER NOT NULL DEFAULT 1
|
|
89
|
+
)
|
|
90
|
+
`);
|
|
91
|
+
db.exec('INSERT INTO checkpoint_counter (id, next) VALUES (1, 1)');
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
//# sourceMappingURL=v001-initial-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v001-initial-schema.js","sourceRoot":"","sources":["../../src/migrations/v001-initial-schema.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAoB;IAChD,OAAO,EAAE,CAAC;IACV,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE;QACZ,gCAAgC;QAEhC,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;KAoBP,CAAC,CAAA;QAEF,EAAE,CAAC,IAAI,CACL,4FAA4F,CAC7F,CAAA;QACD,EAAE,CAAC,IAAI,CACL,gGAAgG,CACjG,CAAA;QACD,EAAE,CAAC,IAAI,CAAC,qEAAqE,CAAC,CAAA;QAE9E,2CAA2C;QAE3C,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;KAYP,CAAC,CAAA;QAEF,EAAE,CAAC,IAAI,CACL,yFAAyF,CAC1F,CAAA;QAED,2BAA2B;QAE3B,EAAE,CAAC,IAAI,CAAC;;;;;;;KAOP,CAAC,CAAA;QAEF,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;KAYP,CAAC,CAAA;QAEF,EAAE,CAAC,IAAI,CACL,2GAA2G,CAC5G,CAAA;QAED,sBAAsB;QAEtB,EAAE,CAAC,IAAI,CAAC;;;;;;;;KAQP,CAAC,CAAA;QAEF,EAAE,CAAC,IAAI,CAAC;;;;;KAKP,CAAC,CAAA;QAEF,EAAE,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAA;IACpE,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SqliteMigration } from '../migration-runner.js';
|
|
2
|
+
/**
|
|
3
|
+
* V002: Auth tables — users and refresh tokens.
|
|
4
|
+
*
|
|
5
|
+
* Users store identity, roles, and OIDC provider linkage.
|
|
6
|
+
* Refresh tokens are stored as SHA-256 hashes with expiry.
|
|
7
|
+
*/
|
|
8
|
+
export declare const v002AuthTables: SqliteMigration;
|
|
9
|
+
//# sourceMappingURL=v002-auth-tables.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v002-auth-tables.d.ts","sourceRoot":"","sources":["../../src/migrations/v002-auth-tables.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAE7D;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAE,eAiC5B,CAAA"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V002: Auth tables — users and refresh tokens.
|
|
3
|
+
*
|
|
4
|
+
* Users store identity, roles, and OIDC provider linkage.
|
|
5
|
+
* Refresh tokens are stored as SHA-256 hashes with expiry.
|
|
6
|
+
*/
|
|
7
|
+
export const v002AuthTables = {
|
|
8
|
+
version: 2,
|
|
9
|
+
name: 'auth_tables',
|
|
10
|
+
apply: (db) => {
|
|
11
|
+
db.exec(`
|
|
12
|
+
CREATE TABLE users (
|
|
13
|
+
id TEXT PRIMARY KEY,
|
|
14
|
+
email TEXT UNIQUE,
|
|
15
|
+
name TEXT,
|
|
16
|
+
roles TEXT NOT NULL DEFAULT '["viewer"]',
|
|
17
|
+
oidc_subject TEXT,
|
|
18
|
+
oidc_issuer TEXT,
|
|
19
|
+
is_active INTEGER NOT NULL DEFAULT 1,
|
|
20
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
21
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
22
|
+
)
|
|
23
|
+
`);
|
|
24
|
+
db.exec('CREATE UNIQUE INDEX idx_users_oidc ON users(oidc_issuer, oidc_subject)');
|
|
25
|
+
db.exec(`
|
|
26
|
+
CREATE TABLE refresh_tokens (
|
|
27
|
+
id TEXT PRIMARY KEY,
|
|
28
|
+
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
29
|
+
token_hash TEXT NOT NULL UNIQUE,
|
|
30
|
+
expires_at TEXT NOT NULL,
|
|
31
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
32
|
+
)
|
|
33
|
+
`);
|
|
34
|
+
db.exec('CREATE INDEX idx_refresh_user ON refresh_tokens(user_id)');
|
|
35
|
+
db.exec('CREATE INDEX idx_refresh_expires ON refresh_tokens(expires_at)');
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=v002-auth-tables.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v002-auth-tables.js","sourceRoot":"","sources":["../../src/migrations/v002-auth-tables.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAoB;IAC7C,OAAO,EAAE,CAAC;IACV,IAAI,EAAE,aAAa;IACnB,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE;QACZ,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;KAYP,CAAC,CAAA;QAEF,EAAE,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAA;QAEjF,EAAE,CAAC,IAAI,CAAC;;;;;;;;KAQP,CAAC,CAAA;QAEF,EAAE,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAA;QACnE,EAAE,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAA;IAC3E,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SqliteMigration } from '../migration-runner.js';
|
|
2
|
+
/**
|
|
3
|
+
* V003: Per-collection permission overrides.
|
|
4
|
+
*
|
|
5
|
+
* Allows a user to have a different role for specific collections.
|
|
6
|
+
* E.g., viewer globally but editor for the 'blog' collection.
|
|
7
|
+
*/
|
|
8
|
+
export declare const v003UserPermissions: SqliteMigration;
|
|
9
|
+
//# sourceMappingURL=v003-user-permissions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v003-user-permissions.d.ts","sourceRoot":"","sources":["../../src/migrations/v003-user-permissions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAE7D;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,EAAE,eAajC,CAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V003: Per-collection permission overrides.
|
|
3
|
+
*
|
|
4
|
+
* Allows a user to have a different role for specific collections.
|
|
5
|
+
* E.g., viewer globally but editor for the 'blog' collection.
|
|
6
|
+
*/
|
|
7
|
+
export const v003UserPermissions = {
|
|
8
|
+
version: 3,
|
|
9
|
+
name: 'user_permissions',
|
|
10
|
+
apply: (db) => {
|
|
11
|
+
db.exec(`
|
|
12
|
+
CREATE TABLE user_permissions (
|
|
13
|
+
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
14
|
+
collection TEXT NOT NULL,
|
|
15
|
+
role TEXT NOT NULL,
|
|
16
|
+
PRIMARY KEY (user_id, collection)
|
|
17
|
+
)
|
|
18
|
+
`);
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=v003-user-permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v003-user-permissions.js","sourceRoot":"","sources":["../../src/migrations/v003-user-permissions.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAoB;IAClD,OAAO,EAAE,CAAC;IACV,IAAI,EAAE,kBAAkB;IACxB,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE;QACZ,EAAE,CAAC,IAAI,CAAC;;;;;;;KAOP,CAAC,CAAA;IACJ,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SqliteMigration } from '../migration-runner.js';
|
|
2
|
+
/**
|
|
3
|
+
* V004: Add hotspot column to media table.
|
|
4
|
+
*
|
|
5
|
+
* Stores a JSON-encoded hotspot (center + ellipse) for adaptive
|
|
6
|
+
* aspect-ratio cropping. NULL means no hotspot defined.
|
|
7
|
+
*
|
|
8
|
+
* It ran before the `media` table was part of the migrated schema, so it is a
|
|
9
|
+
* no-op when the table is missing. It stays because applied migrations form
|
|
10
|
+
* the numbered ledger (the checksum covers only `version:name`); v011 creates
|
|
11
|
+
* `media` with the hotspot column.
|
|
12
|
+
*/
|
|
13
|
+
export declare const v004MediaHotspot: SqliteMigration;
|
|
14
|
+
//# sourceMappingURL=v004-media-hotspot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v004-media-hotspot.d.ts","sourceRoot":"","sources":["../../src/migrations/v004-media-hotspot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAE7D;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,EAAE,eAS9B,CAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V004: Add hotspot column to media table.
|
|
3
|
+
*
|
|
4
|
+
* Stores a JSON-encoded hotspot (center + ellipse) for adaptive
|
|
5
|
+
* aspect-ratio cropping. NULL means no hotspot defined.
|
|
6
|
+
*
|
|
7
|
+
* It ran before the `media` table was part of the migrated schema, so it is a
|
|
8
|
+
* no-op when the table is missing. It stays because applied migrations form
|
|
9
|
+
* the numbered ledger (the checksum covers only `version:name`); v011 creates
|
|
10
|
+
* `media` with the hotspot column.
|
|
11
|
+
*/
|
|
12
|
+
export const v004MediaHotspot = {
|
|
13
|
+
version: 4,
|
|
14
|
+
name: 'media_hotspot',
|
|
15
|
+
apply: (db) => {
|
|
16
|
+
const columns = db.pragma('table_info(media)');
|
|
17
|
+
if (columns.length === 0)
|
|
18
|
+
return;
|
|
19
|
+
if (columns.some((c) => c.name === 'hotspot'))
|
|
20
|
+
return;
|
|
21
|
+
db.exec('ALTER TABLE media ADD COLUMN hotspot TEXT DEFAULT NULL');
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=v004-media-hotspot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v004-media-hotspot.js","sourceRoot":"","sources":["../../src/migrations/v004-media-hotspot.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAoB;IAC/C,OAAO,EAAE,CAAC;IACV,IAAI,EAAE,eAAe;IACrB,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE;QACZ,MAAM,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAA4B,CAAA;QACzE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAM;QAChC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC;YAAE,OAAM;QACrD,EAAE,CAAC,IAAI,CAAC,wDAAwD,CAAC,CAAA;IACnE,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SqliteMigration } from '../migration-runner.js';
|
|
2
|
+
/**
|
|
3
|
+
* V005: Advisory content locks.
|
|
4
|
+
*
|
|
5
|
+
* Ephemeral locks for preventing concurrent editing.
|
|
6
|
+
* 5-minute lease, renewed by Studio heartbeat.
|
|
7
|
+
*/
|
|
8
|
+
export declare const v005ContentLocks: SqliteMigration;
|
|
9
|
+
//# sourceMappingURL=v005-content-locks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v005-content-locks.d.ts","sourceRoot":"","sources":["../../src/migrations/v005-content-locks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAE7D;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,EAAE,eAgB9B,CAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V005: Advisory content locks.
|
|
3
|
+
*
|
|
4
|
+
* Ephemeral locks for preventing concurrent editing.
|
|
5
|
+
* 5-minute lease, renewed by Studio heartbeat.
|
|
6
|
+
*/
|
|
7
|
+
export const v005ContentLocks = {
|
|
8
|
+
version: 5,
|
|
9
|
+
name: 'content_locks',
|
|
10
|
+
apply: (db) => {
|
|
11
|
+
db.exec(`
|
|
12
|
+
CREATE TABLE content_locks (
|
|
13
|
+
collection TEXT NOT NULL,
|
|
14
|
+
slug TEXT NOT NULL,
|
|
15
|
+
locale TEXT NOT NULL DEFAULT 'en',
|
|
16
|
+
locked_by TEXT NOT NULL,
|
|
17
|
+
locked_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
18
|
+
expires_at TEXT NOT NULL,
|
|
19
|
+
PRIMARY KEY (collection, slug, locale)
|
|
20
|
+
)
|
|
21
|
+
`);
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=v005-content-locks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v005-content-locks.js","sourceRoot":"","sources":["../../src/migrations/v005-content-locks.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAoB;IAC/C,OAAO,EAAE,CAAC;IACV,IAAI,EAAE,eAAe;IACrB,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE;QACZ,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;KAUP,CAAC,CAAA;IACJ,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v006-webhook-deliveries.d.ts","sourceRoot":"","sources":["../../src/migrations/v006-webhook-deliveries.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAE7D;;GAEG;AACH,eAAO,MAAM,qBAAqB,EAAE,eAqBnC,CAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V006: Webhook delivery log with retry support.
|
|
3
|
+
*/
|
|
4
|
+
export const v006WebhookDeliveries = {
|
|
5
|
+
version: 6,
|
|
6
|
+
name: 'webhook_deliveries',
|
|
7
|
+
apply: (db) => {
|
|
8
|
+
db.exec(`
|
|
9
|
+
CREATE TABLE webhook_deliveries (
|
|
10
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
11
|
+
webhook_url TEXT NOT NULL,
|
|
12
|
+
event TEXT NOT NULL,
|
|
13
|
+
payload TEXT NOT NULL,
|
|
14
|
+
status INTEGER,
|
|
15
|
+
attempts INTEGER NOT NULL DEFAULT 0,
|
|
16
|
+
next_retry_at TEXT,
|
|
17
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
18
|
+
delivered_at TEXT
|
|
19
|
+
)
|
|
20
|
+
`);
|
|
21
|
+
db.exec('CREATE INDEX idx_webhook_pending ON webhook_deliveries(next_retry_at) WHERE delivered_at IS NULL AND attempts < 5');
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=v006-webhook-deliveries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v006-webhook-deliveries.js","sourceRoot":"","sources":["../../src/migrations/v006-webhook-deliveries.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAoB;IACpD,OAAO,EAAE,CAAC;IACV,IAAI,EAAE,oBAAoB;IAC1B,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE;QACZ,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;KAYP,CAAC,CAAA;QACF,EAAE,CAAC,IAAI,CACL,mHAAmH,CACpH,CAAA;IACH,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SqliteMigration } from '../migration-runner.js';
|
|
2
|
+
/**
|
|
3
|
+
* V007: Media folders — hierarchical folder structure for media organization.
|
|
4
|
+
*
|
|
5
|
+
* Replaces the flat `folder` TEXT column on media with a proper
|
|
6
|
+
* `media_folders` table supporting parent-child nesting.
|
|
7
|
+
* The media table's `folder` column now stores a folder ID (FK).
|
|
8
|
+
*/
|
|
9
|
+
export declare const v007MediaFolders: SqliteMigration;
|
|
10
|
+
//# sourceMappingURL=v007-media-folders.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v007-media-folders.d.ts","sourceRoot":"","sources":["../../src/migrations/v007-media-folders.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAE7D;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,EAAE,eAc9B,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V007: Media folders — hierarchical folder structure for media organization.
|
|
3
|
+
*
|
|
4
|
+
* Replaces the flat `folder` TEXT column on media with a proper
|
|
5
|
+
* `media_folders` table supporting parent-child nesting.
|
|
6
|
+
* The media table's `folder` column now stores a folder ID (FK).
|
|
7
|
+
*/
|
|
8
|
+
export const v007MediaFolders = {
|
|
9
|
+
version: 7,
|
|
10
|
+
name: 'media_folders',
|
|
11
|
+
apply: (db) => {
|
|
12
|
+
db.exec(`
|
|
13
|
+
CREATE TABLE media_folders (
|
|
14
|
+
id TEXT PRIMARY KEY,
|
|
15
|
+
name TEXT NOT NULL,
|
|
16
|
+
parent_id TEXT REFERENCES media_folders(id),
|
|
17
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
18
|
+
)
|
|
19
|
+
`);
|
|
20
|
+
db.exec('CREATE INDEX idx_media_folders_parent ON media_folders(parent_id)');
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=v007-media-folders.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v007-media-folders.js","sourceRoot":"","sources":["../../src/migrations/v007-media-folders.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAoB;IAC/C,OAAO,EAAE,CAAC;IACV,IAAI,EAAE,eAAe;IACrB,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE;QACZ,EAAE,CAAC,IAAI,CAAC;;;;;;;KAOP,CAAC,CAAA;QACF,EAAE,CAAC,IAAI,CAAC,mEAAmE,CAAC,CAAA;IAC9E,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SqliteMigration } from '../migration-runner.js';
|
|
2
|
+
/**
|
|
3
|
+
* V008: Site settings — runtime-configurable key-value settings.
|
|
4
|
+
*
|
|
5
|
+
* Used for locale configuration and other admin-editable site settings
|
|
6
|
+
* that shouldn't require a code deploy to change.
|
|
7
|
+
*/
|
|
8
|
+
export declare const v008SiteSettings: SqliteMigration;
|
|
9
|
+
//# sourceMappingURL=v008-site-settings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v008-site-settings.d.ts","sourceRoot":"","sources":["../../src/migrations/v008-site-settings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAE7D;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,EAAE,eAY9B,CAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V008: Site settings — runtime-configurable key-value settings.
|
|
3
|
+
*
|
|
4
|
+
* Used for locale configuration and other admin-editable site settings
|
|
5
|
+
* that shouldn't require a code deploy to change.
|
|
6
|
+
*/
|
|
7
|
+
export const v008SiteSettings = {
|
|
8
|
+
version: 8,
|
|
9
|
+
name: 'site_settings',
|
|
10
|
+
apply: (db) => {
|
|
11
|
+
db.exec(`
|
|
12
|
+
CREATE TABLE site_settings (
|
|
13
|
+
key TEXT PRIMARY KEY,
|
|
14
|
+
value TEXT NOT NULL,
|
|
15
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
16
|
+
)
|
|
17
|
+
`);
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=v008-site-settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v008-site-settings.js","sourceRoot":"","sources":["../../src/migrations/v008-site-settings.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAoB;IAC/C,OAAO,EAAE,CAAC;IACV,IAAI,EAAE,eAAe;IACrB,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE;QACZ,EAAE,CAAC,IAAI,CAAC;;;;;;KAMP,CAAC,CAAA;IACJ,CAAC;CACF,CAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { SqliteMigration } from '../migration-runner.js';
|
|
2
|
+
/**
|
|
3
|
+
* V009: SEO configuration — structured entity graph per site, collection,
|
|
4
|
+
* document, or route.
|
|
5
|
+
*
|
|
6
|
+
* Stores a single `config` JSON column holding a `SeoConfigData` object
|
|
7
|
+
* with an ordered entity array and optional field-mapping overrides.
|
|
8
|
+
* Four scopes:
|
|
9
|
+
* - site: global business identity and site-level entities
|
|
10
|
+
* - collection: default archetype per content collection (primary)
|
|
11
|
+
* - route: URL-pattern override (optional, advanced)
|
|
12
|
+
* - document: per-page override
|
|
13
|
+
*/
|
|
14
|
+
export declare const v009SeoConfig: SqliteMigration;
|
|
15
|
+
//# sourceMappingURL=v009-seo-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v009-seo-config.d.ts","sourceRoot":"","sources":["../../src/migrations/v009-seo-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAE7D;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,EAAE,eAe3B,CAAA"}
|