@beechcms/core 0.9.4 → 0.9.6
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/content/content-lock.repository.d.ts +63 -0
- package/dist/content/content-lock.repository.d.ts.map +1 -0
- package/dist/content/content-lock.repository.js +15 -0
- package/dist/content/content.repository.d.ts +22 -22
- package/dist/content/content.repository.d.ts.map +1 -1
- package/dist/content/retention.d.ts +13 -0
- package/dist/content/retention.d.ts.map +1 -0
- package/dist/content/retention.js +20 -0
- package/dist/content/slug-utils.d.ts +7 -0
- package/dist/content/slug-utils.d.ts.map +1 -1
- package/dist/content/slug-utils.js +12 -0
- package/dist/dashboard-layout/content-view.d.ts +4 -4
- package/dist/dashboard-layout/dashboard-layout.d.ts +2 -2
- package/dist/dashboard-layout/dashboard-layout.d.ts.map +1 -1
- package/dist/dashboard-layout/dashboard-layout.js +3 -3
- package/dist/dashboard-layout/kanban/kanban-position.repository.d.ts +19 -0
- package/dist/dashboard-layout/kanban/kanban-position.repository.d.ts.map +1 -0
- package/dist/dashboard-layout/kanban/kanban-position.repository.js +3 -0
- package/dist/dashboard-layout/seed-layout.d.ts.map +1 -1
- package/dist/dashboard-layout/seed-layout.js +17 -1
- package/dist/engine/ddl/ddl.d.ts +4 -6
- package/dist/engine/ddl/ddl.d.ts.map +1 -1
- package/dist/engine/ddl/ddl.js +13 -27
- package/dist/engine/ddl/seed-ddl-destructive.d.ts +40 -0
- package/dist/engine/ddl/seed-ddl-destructive.d.ts.map +1 -0
- package/dist/engine/ddl/seed-ddl-destructive.js +149 -0
- package/dist/engine/ddl/seed-ddl.d.ts.map +1 -1
- package/dist/engine/ddl/seed-ddl.js +10 -2
- package/dist/engine/ddl.d.ts +216 -0
- package/dist/engine/ddl.d.ts.map +1 -0
- package/dist/engine/ddl.js +574 -0
- package/dist/engine/define-seed.d.ts +3 -0
- package/dist/engine/define-seed.d.ts.map +1 -0
- package/dist/engine/define-seed.js +5 -0
- package/dist/engine/introspection.d.ts +101 -0
- package/dist/engine/introspection.d.ts.map +1 -0
- package/dist/engine/introspection.js +127 -0
- package/dist/engine/policies.d.ts +58 -0
- package/dist/engine/policies.d.ts.map +1 -0
- package/dist/engine/policies.js +168 -0
- package/dist/engine/privacy.service.d.ts +65 -0
- package/dist/engine/privacy.service.d.ts.map +1 -0
- package/dist/engine/privacy.service.js +114 -0
- package/dist/engine/query/active-clause.d.ts +2 -3
- package/dist/engine/query/active-clause.d.ts.map +1 -1
- package/dist/engine/query/active-clause.js +3 -4
- package/dist/engine/query/query.js +8 -8
- package/dist/engine/query/relations.d.ts +15 -0
- package/dist/engine/query/relations.d.ts.map +1 -1
- package/dist/engine/query.d.ts +23 -0
- package/dist/engine/query.d.ts.map +1 -0
- package/dist/engine/query.js +248 -0
- package/dist/engine/relations.d.ts +28 -0
- package/dist/engine/relations.d.ts.map +1 -0
- package/dist/engine/relations.js +25 -0
- package/dist/engine/schema-fingerprint.d.ts +71 -0
- package/dist/engine/schema-fingerprint.d.ts.map +1 -0
- package/dist/engine/schema-fingerprint.js +95 -0
- package/dist/engine/schema-mutator.d.ts +26 -0
- package/dist/engine/schema-mutator.d.ts.map +1 -0
- package/dist/engine/schema-mutator.js +3 -0
- package/dist/engine/seed-ddl-destructive.d.ts +40 -0
- package/dist/engine/seed-ddl-destructive.d.ts.map +1 -0
- package/dist/engine/seed-ddl-destructive.js +149 -0
- package/dist/engine/seed-ddl.d.ts +43 -0
- package/dist/engine/seed-ddl.d.ts.map +1 -0
- package/dist/engine/seed-ddl.js +115 -0
- package/dist/engine/seed-registry.d.ts +71 -0
- package/dist/engine/seed-registry.d.ts.map +1 -0
- package/dist/engine/seed-registry.js +167 -0
- package/dist/engine/seed-types-generator.d.ts +25 -0
- package/dist/engine/seed-types-generator.d.ts.map +1 -0
- package/dist/engine/seed-types-generator.js +117 -0
- package/dist/engine/seed-validation.d.ts +30 -0
- package/dist/engine/seed-validation.d.ts.map +1 -0
- package/dist/engine/seed-validation.js +329 -0
- package/dist/engine/seeds/seed-definition-diff.d.ts +1 -1
- package/dist/engine/seeds/seed-definition-diff.d.ts.map +1 -1
- package/dist/engine/seeds/seed-definition-diff.js +2 -2
- package/dist/engine/seeds/seed-validation.d.ts.map +1 -1
- package/dist/engine/seeds/seed-validation.js +3 -12
- package/dist/engine/seeds.d.ts +20 -0
- package/dist/engine/seeds.d.ts.map +1 -0
- package/dist/engine/seeds.js +21 -0
- package/dist/engine/serialize.d.ts +20 -0
- package/dist/engine/serialize.d.ts.map +1 -0
- package/dist/engine/serialize.js +160 -0
- package/dist/engine/types.d.ts +7 -7
- package/dist/engine/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/notifications/notification-service.d.ts +2 -2
- package/dist/notifications/notification.repository.d.ts +6 -3
- package/dist/notifications/notification.repository.d.ts.map +1 -1
- package/dist/security/time-trap.d.ts +3 -2
- package/dist/security/time-trap.d.ts.map +1 -1
- package/dist/security/time-trap.js +5 -4
- package/dist/seed-types-generator.d.ts +10 -0
- package/dist/seed-types-generator.d.ts.map +1 -0
- package/dist/seed-types-generator.js +86 -0
- package/dist/settings/site-settings.repository.d.ts +2 -0
- package/dist/settings/site-settings.repository.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Seed, BranchType } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Ordered DROP TABLE statements for a full hard-delete of a seed's tables.
|
|
4
|
+
* Order: junction drafts → junctions → FTS triggers → FTS table → drafts → main table.
|
|
5
|
+
* All statements use IF EXISTS (idempotent).
|
|
6
|
+
*/
|
|
7
|
+
export declare function generateDropTable(seed: Seed): string[];
|
|
8
|
+
/**
|
|
9
|
+
* DROP COLUMN statements for a single branch (by alias).
|
|
10
|
+
* For multi-relation branches: drops the junction tables (no column on parent).
|
|
11
|
+
* For regular branches: drops from main table + drafts table (if allowDrafts).
|
|
12
|
+
* Does NOT include FTS handling — callers must prepend ftsTriggerDrops() and
|
|
13
|
+
* append planFtsRebuild() when the branch is searchable.
|
|
14
|
+
*/
|
|
15
|
+
export declare function generateDropColumn(seed: Seed, alias: string): string[];
|
|
16
|
+
/**
|
|
17
|
+
* RENAME COLUMN statements for a branch alias change.
|
|
18
|
+
* Updates main table + drafts (if allowDrafts).
|
|
19
|
+
* Does NOT handle FTS — callers must rebuild FTS separately (SQLite auto-updates
|
|
20
|
+
* trigger bodies on RENAME but the FTS virtual-table columns keep the old name).
|
|
21
|
+
*/
|
|
22
|
+
export declare function generateRenameColumn(seed: Seed, fromAlias: string, toAlias: string): string[];
|
|
23
|
+
/**
|
|
24
|
+
* Full FTS rebuild: drop triggers + FTS table, then recreate them, then backfill.
|
|
25
|
+
* Returns an empty array if the seed has no searchable branches.
|
|
26
|
+
* The drop steps use IF EXISTS so this is safe to call even if FTS was already dropped.
|
|
27
|
+
*/
|
|
28
|
+
export declare function planFtsRebuild(seed: Seed): string[];
|
|
29
|
+
export interface RetypeColumnPlan {
|
|
30
|
+
statements: string[];
|
|
31
|
+
ftsRebuildNeeded: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Generates statements to change a branch's SQL storage type using the
|
|
35
|
+
* add-new-column / copy / drop-old / rename approach.
|
|
36
|
+
* Includes FTS rebuild statements when the branch is (or becomes) searchable.
|
|
37
|
+
* `updatedSeed` must already reflect the new type on the renamed branch.
|
|
38
|
+
*/
|
|
39
|
+
export declare function planRetypeColumn(seed: Seed, alias: string, newType: BranchType, updatedSeed: Seed): RetypeColumnPlan;
|
|
40
|
+
//# sourceMappingURL=seed-ddl-destructive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seed-ddl-destructive.d.ts","sourceRoot":"","sources":["../../../src/engine/ddl/seed-ddl-destructive.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAU,UAAU,EAAE,MAAM,aAAa,CAAA;AAkC3D;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAgBtD;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAgBtE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ7F;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAiBnD;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,gBAAgB,EAAE,OAAO,CAAA;CAC1B;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,UAAU,EACnB,WAAW,EAAE,IAAI,GAChB,gBAAgB,CAyClB"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Copyright (c) 2024–2026 Flavio De Musso
|
|
3
|
+
import { junctionTableName, generateFtsTable, generateFtsTriggers } from './ddl.js';
|
|
4
|
+
const BRANCH_SQL_TYPE = {
|
|
5
|
+
text: 'TEXT',
|
|
6
|
+
number: 'REAL',
|
|
7
|
+
boolean: 'INTEGER',
|
|
8
|
+
date: 'INTEGER',
|
|
9
|
+
json: 'TEXT',
|
|
10
|
+
richtext: 'TEXT',
|
|
11
|
+
file: 'TEXT',
|
|
12
|
+
tags: 'TEXT',
|
|
13
|
+
relation: 'TEXT',
|
|
14
|
+
repeater: 'TEXT',
|
|
15
|
+
};
|
|
16
|
+
/** Branch types that receive a B-tree index in generateIndexes (used by retype to drop/recreate). */
|
|
17
|
+
const INDEXABLE_TYPES = new Set(['text', 'number', 'date', 'boolean', 'relation']);
|
|
18
|
+
function searchBranches(seed) {
|
|
19
|
+
return seed.branches.filter(b => (b.type === 'text' || b.type === 'richtext') && b.policies?.search !== false);
|
|
20
|
+
}
|
|
21
|
+
function ftsTriggerDrops(slug) {
|
|
22
|
+
return [
|
|
23
|
+
`DROP TRIGGER IF EXISTS fts_${slug}_insert;`,
|
|
24
|
+
`DROP TRIGGER IF EXISTS fts_${slug}_update;`,
|
|
25
|
+
`DROP TRIGGER IF EXISTS fts_${slug}_delete;`,
|
|
26
|
+
`DROP TABLE IF EXISTS fts_${slug};`,
|
|
27
|
+
];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Ordered DROP TABLE statements for a full hard-delete of a seed's tables.
|
|
31
|
+
* Order: junction drafts → junctions → FTS triggers → FTS table → drafts → main table.
|
|
32
|
+
* All statements use IF EXISTS (idempotent).
|
|
33
|
+
*/
|
|
34
|
+
export function generateDropTable(seed) {
|
|
35
|
+
const stmts = [];
|
|
36
|
+
const { slug } = seed;
|
|
37
|
+
for (const branch of seed.branches) {
|
|
38
|
+
if (branch.type !== 'relation' || branch.multiple !== true)
|
|
39
|
+
continue;
|
|
40
|
+
const jt = junctionTableName(slug, branch.alias);
|
|
41
|
+
stmts.push(`DROP TABLE IF EXISTS ${jt}_drafts;`);
|
|
42
|
+
stmts.push(`DROP TABLE IF EXISTS ${jt};`);
|
|
43
|
+
}
|
|
44
|
+
stmts.push(...ftsTriggerDrops(slug));
|
|
45
|
+
stmts.push(`DROP TABLE IF EXISTS content_${slug}_drafts;`);
|
|
46
|
+
stmts.push(`DROP TABLE IF EXISTS content_${slug};`);
|
|
47
|
+
return stmts;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* DROP COLUMN statements for a single branch (by alias).
|
|
51
|
+
* For multi-relation branches: drops the junction tables (no column on parent).
|
|
52
|
+
* For regular branches: drops from main table + drafts table (if allowDrafts).
|
|
53
|
+
* Does NOT include FTS handling — callers must prepend ftsTriggerDrops() and
|
|
54
|
+
* append planFtsRebuild() when the branch is searchable.
|
|
55
|
+
*/
|
|
56
|
+
export function generateDropColumn(seed, alias) {
|
|
57
|
+
const stmts = [];
|
|
58
|
+
const { slug } = seed;
|
|
59
|
+
const branch = seed.branches.find(b => b.alias === alias);
|
|
60
|
+
if (!branch)
|
|
61
|
+
throw new Error(`Branch '${alias}' not found in seed '${slug}'`);
|
|
62
|
+
if (branch.type === 'relation' && branch.multiple === true) {
|
|
63
|
+
const jt = junctionTableName(slug, alias);
|
|
64
|
+
if (seed.allowDrafts)
|
|
65
|
+
stmts.push(`DROP TABLE IF EXISTS ${jt}_drafts;`);
|
|
66
|
+
stmts.push(`DROP TABLE IF EXISTS ${jt};`);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
stmts.push(`ALTER TABLE content_${slug} DROP COLUMN ${alias};`);
|
|
70
|
+
if (seed.allowDrafts)
|
|
71
|
+
stmts.push(`ALTER TABLE content_${slug}_drafts DROP COLUMN ${alias};`);
|
|
72
|
+
}
|
|
73
|
+
return stmts;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* RENAME COLUMN statements for a branch alias change.
|
|
77
|
+
* Updates main table + drafts (if allowDrafts).
|
|
78
|
+
* Does NOT handle FTS — callers must rebuild FTS separately (SQLite auto-updates
|
|
79
|
+
* trigger bodies on RENAME but the FTS virtual-table columns keep the old name).
|
|
80
|
+
*/
|
|
81
|
+
export function generateRenameColumn(seed, fromAlias, toAlias) {
|
|
82
|
+
const stmts = [];
|
|
83
|
+
const { slug } = seed;
|
|
84
|
+
stmts.push(`ALTER TABLE content_${slug} RENAME COLUMN ${fromAlias} TO ${toAlias};`);
|
|
85
|
+
if (seed.allowDrafts) {
|
|
86
|
+
stmts.push(`ALTER TABLE content_${slug}_drafts RENAME COLUMN ${fromAlias} TO ${toAlias};`);
|
|
87
|
+
}
|
|
88
|
+
return stmts;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Full FTS rebuild: drop triggers + FTS table, then recreate them, then backfill.
|
|
92
|
+
* Returns an empty array if the seed has no searchable branches.
|
|
93
|
+
* The drop steps use IF EXISTS so this is safe to call even if FTS was already dropped.
|
|
94
|
+
*/
|
|
95
|
+
export function planFtsRebuild(seed) {
|
|
96
|
+
const rtBranches = searchBranches(seed);
|
|
97
|
+
if (rtBranches.length === 0)
|
|
98
|
+
return [];
|
|
99
|
+
const { slug } = seed;
|
|
100
|
+
const stmts = [...ftsTriggerDrops(slug)];
|
|
101
|
+
const ftsTable = generateFtsTable(seed);
|
|
102
|
+
if (ftsTable)
|
|
103
|
+
stmts.push(ftsTable);
|
|
104
|
+
stmts.push(...generateFtsTriggers(seed));
|
|
105
|
+
const cols = rtBranches.map(b => b.alias);
|
|
106
|
+
stmts.push(`INSERT INTO fts_${slug}(entry_id, ${cols.join(', ')}) SELECT id, ${cols.join(', ')} FROM content_${slug};`);
|
|
107
|
+
return stmts;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Generates statements to change a branch's SQL storage type using the
|
|
111
|
+
* add-new-column / copy / drop-old / rename approach.
|
|
112
|
+
* Includes FTS rebuild statements when the branch is (or becomes) searchable.
|
|
113
|
+
* `updatedSeed` must already reflect the new type on the renamed branch.
|
|
114
|
+
*/
|
|
115
|
+
export function planRetypeColumn(seed, alias, newType, updatedSeed) {
|
|
116
|
+
const branch = seed.branches.find(b => b.alias === alias);
|
|
117
|
+
if (!branch)
|
|
118
|
+
throw new Error(`Branch '${alias}' not found in seed '${seed.slug}'`);
|
|
119
|
+
const { slug } = seed;
|
|
120
|
+
const newSqlType = BRANCH_SQL_TYPE[newType];
|
|
121
|
+
const tmpAlias = `${alias}_migrate`;
|
|
122
|
+
const stmts = [];
|
|
123
|
+
// Always drop FTS first to avoid "column referenced in trigger" errors on DROP COLUMN.
|
|
124
|
+
stmts.push(...ftsTriggerDrops(slug));
|
|
125
|
+
// Drop the branch index if it exists on the old column (required before DROP COLUMN).
|
|
126
|
+
if (INDEXABLE_TYPES.has(branch.type) && branch.policies?.filter !== false) {
|
|
127
|
+
stmts.push(`DROP INDEX IF EXISTS idx_${slug}_${alias};`);
|
|
128
|
+
}
|
|
129
|
+
// Main table: add migration column, copy data, drop old, rename.
|
|
130
|
+
stmts.push(`ALTER TABLE content_${slug} ADD COLUMN ${tmpAlias} ${newSqlType};`);
|
|
131
|
+
stmts.push(`UPDATE content_${slug} SET ${tmpAlias} = CAST(${alias} AS ${newSqlType});`);
|
|
132
|
+
stmts.push(`ALTER TABLE content_${slug} DROP COLUMN ${alias};`);
|
|
133
|
+
stmts.push(`ALTER TABLE content_${slug} RENAME COLUMN ${tmpAlias} TO ${alias};`);
|
|
134
|
+
// Recreate index for the renamed column if the new type warrants it.
|
|
135
|
+
if (INDEXABLE_TYPES.has(newType) && branch.policies?.filter !== false) {
|
|
136
|
+
stmts.push(`CREATE INDEX IF NOT EXISTS idx_${slug}_${alias} ON content_${slug}(${alias});`);
|
|
137
|
+
}
|
|
138
|
+
// Drafts table (no indexes to worry about).
|
|
139
|
+
if (seed.allowDrafts) {
|
|
140
|
+
stmts.push(`ALTER TABLE content_${slug}_drafts ADD COLUMN ${tmpAlias} ${newSqlType};`);
|
|
141
|
+
stmts.push(`UPDATE content_${slug}_drafts SET ${tmpAlias} = CAST(${alias} AS ${newSqlType});`);
|
|
142
|
+
stmts.push(`ALTER TABLE content_${slug}_drafts DROP COLUMN ${alias};`);
|
|
143
|
+
stmts.push(`ALTER TABLE content_${slug}_drafts RENAME COLUMN ${tmpAlias} TO ${alias};`);
|
|
144
|
+
}
|
|
145
|
+
// Rebuild FTS if the seed has searchable branches in the updated definition.
|
|
146
|
+
const rebuild = planFtsRebuild(updatedSeed);
|
|
147
|
+
stmts.push(...rebuild);
|
|
148
|
+
return { statements: stmts, ftsRebuildNeeded: rebuild.length > 0 };
|
|
149
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"seed-ddl.d.ts","sourceRoot":"","sources":["../../../src/engine/ddl/seed-ddl.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"seed-ddl.d.ts","sourceRoot":"","sources":["../../../src/engine/ddl/seed-ddl.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAiBvC;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAenD;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,gBAAgB,EAAE,OAAO,CAAA;CAC1B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,IAAI,EACV,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,EAC5B,oBAAoB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,GACxC,UAAU,CAwCZ;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CA0BnD"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
2
|
// Copyright (c) 2024–2026 Flavio De Musso
|
|
3
|
-
import { generateCreateTable, generateDraftTable, generateIndexes, generateFtsTable, generateFtsTriggers, generateAddColumn, generateAddDraftSnapshotColumn, generateJunctionTable, generateJunctionIndexes, generateJunctionDraftTable, generateEnableSoftDelete, indexableSearchBranches, } from './ddl.js';
|
|
3
|
+
import { generateCreateTable, generateDraftTable, generateIndexes, generateFtsTable, generateFtsTriggers, generateVectorTable, generateAddColumn, generateAddDraftSnapshotColumn, generateJunctionTable, generateJunctionIndexes, generateJunctionDraftTable, generateEnableSoftDelete, indexableSearchBranches, } from './ddl.js';
|
|
4
4
|
/**
|
|
5
5
|
* Full create-from-scratch statement set for a seed. Mirrors the CLI's buildStatements.
|
|
6
6
|
* Order: parent table → indexes → draft table → FTS table → FTS triggers →
|
|
@@ -16,6 +16,9 @@ export function planCreateSeed(seed) {
|
|
|
16
16
|
const fts = generateFtsTable(seed);
|
|
17
17
|
if (fts)
|
|
18
18
|
stmts.push(fts, ...generateFtsTriggers(seed));
|
|
19
|
+
const vector = generateVectorTable(seed);
|
|
20
|
+
if (vector)
|
|
21
|
+
stmts.push(vector);
|
|
19
22
|
for (const branch of seed.branches) {
|
|
20
23
|
if (branch.type !== 'relation' || branch.multiple !== true)
|
|
21
24
|
continue;
|
|
@@ -59,7 +62,7 @@ export function planExtendSeed(seed, existingColumns, existingDraftColumns) {
|
|
|
59
62
|
}
|
|
60
63
|
}
|
|
61
64
|
// System column, not a branch: the branch loop above can never emit it.
|
|
62
|
-
if (
|
|
65
|
+
if (!existingColumns.has('deleted_at')) {
|
|
63
66
|
statements.push(...generateEnableSoftDelete(seed));
|
|
64
67
|
}
|
|
65
68
|
// Draft-table system column. Emitted only when the caller actually introspected
|
|
@@ -70,6 +73,11 @@ export function planExtendSeed(seed, existingColumns, existingDraftColumns) {
|
|
|
70
73
|
!existingDraftColumns.has('live_snapshot_at')) {
|
|
71
74
|
statements.push(generateAddDraftSnapshotColumn(seed));
|
|
72
75
|
}
|
|
76
|
+
// Vector table is CREATE TABLE IF NOT EXISTS — safe and idempotent to emit if seed has indexable branches
|
|
77
|
+
const vector = generateVectorTable(seed);
|
|
78
|
+
if (vector) {
|
|
79
|
+
statements.push(vector);
|
|
80
|
+
}
|
|
73
81
|
// CREATE INDEX IF NOT EXISTS — idempotent, safe to re-run
|
|
74
82
|
statements.push(...generateIndexes(seed));
|
|
75
83
|
return { statements, ftsRebuildNeeded };
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import type { Seed, Branch } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Helper function to determine if a branch requires a blind index column.
|
|
4
|
+
* Returns true if storage classification is 'encrypt' and filtering is not explicitly disabled.
|
|
5
|
+
*/
|
|
6
|
+
export declare function hasBlindIndex(branch: Branch): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* System-defined columns that exist on all content tables.
|
|
9
|
+
*/
|
|
10
|
+
export declare const SYSTEM_COLUMNS: Set<string>;
|
|
11
|
+
/**
|
|
12
|
+
* Returns the SQL table name for a given Seed.
|
|
13
|
+
*
|
|
14
|
+
* @param seed The seed definition.
|
|
15
|
+
* @returns The table name.
|
|
16
|
+
*/
|
|
17
|
+
export declare function tableName(seed: Seed): string;
|
|
18
|
+
/**
|
|
19
|
+
* Returns the FTS (Full-Text Search) virtual table name for a given Seed.
|
|
20
|
+
*
|
|
21
|
+
* @param seed The seed definition.
|
|
22
|
+
* @returns The FTS table name.
|
|
23
|
+
*/
|
|
24
|
+
export declare function ftsTableName(seed: Seed): string;
|
|
25
|
+
/**
|
|
26
|
+
* Returns the vector table name for a given Seed.
|
|
27
|
+
*
|
|
28
|
+
* @param seed The seed definition.
|
|
29
|
+
* @returns The vector table name.
|
|
30
|
+
*/
|
|
31
|
+
export declare function vectorTableName(seed: Seed): string;
|
|
32
|
+
/**
|
|
33
|
+
* Determines whether a column is valid for a given Seed (either system column or branch alias).
|
|
34
|
+
*
|
|
35
|
+
* @param seed The seed definition.
|
|
36
|
+
* @param col The column name to check.
|
|
37
|
+
* @returns True if the column is valid, false otherwise.
|
|
38
|
+
*/
|
|
39
|
+
export declare function isValidColumn(seed: Seed, col: string): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Filters the branches of a Seed to return only the ones that are indexable for full-text search.
|
|
42
|
+
*
|
|
43
|
+
* @param seed The seed definition.
|
|
44
|
+
* @returns An array of indexable branches.
|
|
45
|
+
*/
|
|
46
|
+
export declare function indexableSearchBranches(seed: Seed): Branch[];
|
|
47
|
+
/**
|
|
48
|
+
* Generates the SQL `CREATE TABLE IF NOT EXISTS content_{slug}` statement
|
|
49
|
+
* with system columns and one column per branch.
|
|
50
|
+
*
|
|
51
|
+
* @param seed The seed definition.
|
|
52
|
+
* @returns The CREATE TABLE SQL statement.
|
|
53
|
+
*/
|
|
54
|
+
export declare function generateCreateTable(seed: Seed): string;
|
|
55
|
+
/**
|
|
56
|
+
* Generates the SQL `CREATE TABLE IF NOT EXISTS content_{slug}_drafts` statement
|
|
57
|
+
* for seeds that allow drafts.
|
|
58
|
+
*
|
|
59
|
+
* @param seed The seed definition.
|
|
60
|
+
* @returns The draft table CREATE TABLE SQL statement, or null if drafts are disabled.
|
|
61
|
+
*/
|
|
62
|
+
export declare function generateDraftTable(seed: Seed): string | null;
|
|
63
|
+
/**
|
|
64
|
+
* Generates the SQL `ALTER TABLE content_{slug} ADD COLUMN {alias} {type}` statement.
|
|
65
|
+
*
|
|
66
|
+
* @param seed The seed definition.
|
|
67
|
+
* @param branch The branch definition for the new column.
|
|
68
|
+
* @returns The ALTER TABLE SQL statement.
|
|
69
|
+
*/
|
|
70
|
+
export declare function generateAddColumn(seed: Seed, branch: Branch): string;
|
|
71
|
+
/**
|
|
72
|
+
* Generates the `ALTER TABLE content_{slug}_drafts ADD COLUMN live_snapshot_at INTEGER` statement
|
|
73
|
+
* for a draft table provisioned before the column existed.
|
|
74
|
+
*
|
|
75
|
+
* System column, not a branch — `generateAddColumn` iterates `seed.branches` and can never emit it.
|
|
76
|
+
* NOT idempotent: `ADD COLUMN` fails when the column is already present and `ISchemaMutator.execDdl`
|
|
77
|
+
* aborts the whole batch on the first failing statement, so the caller MUST check the physical
|
|
78
|
+
* columns first (see `planExtendSeed`).
|
|
79
|
+
*
|
|
80
|
+
* @param seed The seed definition. Caller must have verified `seed.allowDrafts`.
|
|
81
|
+
* @returns The ALTER TABLE statement.
|
|
82
|
+
*/
|
|
83
|
+
export declare function generateAddDraftSnapshotColumn(seed: Seed): string;
|
|
84
|
+
/**
|
|
85
|
+
* Generates SQL index statements for system fields (status, created_at)
|
|
86
|
+
* and indexable branch columns.
|
|
87
|
+
*
|
|
88
|
+
* @param seed The seed definition.
|
|
89
|
+
* @returns An array of CREATE INDEX SQL statements.
|
|
90
|
+
*/
|
|
91
|
+
export declare function generateIndexes(seed: Seed): string[];
|
|
92
|
+
/**
|
|
93
|
+
* Generates the FTS5 virtual table definition for indexable text/richtext branches.
|
|
94
|
+
*
|
|
95
|
+
* @param seed The seed definition.
|
|
96
|
+
* @returns The CREATE VIRTUAL TABLE SQL statement, or null if no branches are indexable.
|
|
97
|
+
*/
|
|
98
|
+
export declare function generateFtsTable(seed: Seed): string | null;
|
|
99
|
+
/**
|
|
100
|
+
* Generates FTS5 triggers (insert, update, delete) to keep the FTS virtual table synchronized.
|
|
101
|
+
*
|
|
102
|
+
* @param seed The seed definition.
|
|
103
|
+
* @returns An array of CREATE TRIGGER SQL statements.
|
|
104
|
+
*/
|
|
105
|
+
export declare function generateFtsTriggers(seed: Seed): string[];
|
|
106
|
+
/**
|
|
107
|
+
* Generates the SQL `CREATE TABLE IF NOT EXISTS vector_{slug}` statement
|
|
108
|
+
* for indexable text/richtext branches.
|
|
109
|
+
*
|
|
110
|
+
* @param seed The seed definition.
|
|
111
|
+
* @returns The CREATE TABLE SQL statement, or null if no branches are indexable.
|
|
112
|
+
*/
|
|
113
|
+
export declare function generateVectorTable(seed: Seed): string | null;
|
|
114
|
+
/**
|
|
115
|
+
* Expected database schema column interface.
|
|
116
|
+
*/
|
|
117
|
+
export interface SchemaColumn {
|
|
118
|
+
/** Column name. */
|
|
119
|
+
name: string;
|
|
120
|
+
/** SQLite storage type. */
|
|
121
|
+
sqlType: 'TEXT' | 'REAL' | 'INTEGER';
|
|
122
|
+
/** Whether the column is NOT NULL. */
|
|
123
|
+
notNull: boolean;
|
|
124
|
+
/** Whether the column is the PRIMARY KEY. */
|
|
125
|
+
isPk: boolean;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Returns the list of expected columns for a Seed's table.
|
|
129
|
+
* Used to compare current vs expected schema (diffing).
|
|
130
|
+
*
|
|
131
|
+
* @param seed The seed definition.
|
|
132
|
+
* @returns The array of expected schema columns.
|
|
133
|
+
*/
|
|
134
|
+
export declare function getExpectedColumns(seed: Seed): SchemaColumn[];
|
|
135
|
+
/**
|
|
136
|
+
* Returns the junction table name for a many-to-many relation branch.
|
|
137
|
+
* Format: `rel_<seedSlug>_<branchAlias>`.
|
|
138
|
+
*
|
|
139
|
+
* @param seedSlug The slug of the parent Seed.
|
|
140
|
+
* @param branchAlias The alias of the relation branch.
|
|
141
|
+
* @returns The junction table name.
|
|
142
|
+
*/
|
|
143
|
+
export declare function junctionTableName(seedSlug: string, branchAlias: string): string;
|
|
144
|
+
/**
|
|
145
|
+
* Generates `CREATE TABLE IF NOT EXISTS rel_<seed>_<alias>` statement for a multi-relation branch.
|
|
146
|
+
*
|
|
147
|
+
* @param seed The parent seed definition.
|
|
148
|
+
* @param branch The multi-relation branch definition.
|
|
149
|
+
* @throws {Error} If called on a non-multi-relation branch or if `targetSeed` is missing.
|
|
150
|
+
* @returns The CREATE TABLE SQL statement.
|
|
151
|
+
*/
|
|
152
|
+
export declare function generateJunctionTable(seed: Seed, branch: Branch): string;
|
|
153
|
+
/**
|
|
154
|
+
* Generates the two B-tree indexes for a junction table:
|
|
155
|
+
* one on `parent_id` (listing entries by parent) and one on `target_id` (handling cascade checks from target side).
|
|
156
|
+
*
|
|
157
|
+
* @param seed The parent seed definition.
|
|
158
|
+
* @param branch The multi-relation branch definition.
|
|
159
|
+
* @returns An array of CREATE INDEX SQL statements.
|
|
160
|
+
*/
|
|
161
|
+
export declare function generateJunctionIndexes(seed: Seed, branch: Branch): string[];
|
|
162
|
+
/**
|
|
163
|
+
* Generates the drafts junction table `rel_<seed>_<alias>_drafts` for a many-to-many relation branch.
|
|
164
|
+
*
|
|
165
|
+
* @param seed The parent seed definition.
|
|
166
|
+
* @param branch The multi-relation branch definition.
|
|
167
|
+
* @returns The CREATE TABLE SQL statement, or null if drafts are disabled.
|
|
168
|
+
*/
|
|
169
|
+
export declare function generateJunctionDraftTable(seed: Seed, branch: Branch): string | null;
|
|
170
|
+
/**
|
|
171
|
+
* Returns every `DROP TABLE IF EXISTS` needed to fully remove a content type:
|
|
172
|
+
* the main table, the drafts table (if drafts enabled), full-text search table/triggers, and junction tables.
|
|
173
|
+
*
|
|
174
|
+
* @param seed The seed definition.
|
|
175
|
+
* @returns An array of DROP TABLE / DROP TRIGGER SQL statements.
|
|
176
|
+
*/
|
|
177
|
+
export declare function generateDropTable(seed: Seed): string[];
|
|
178
|
+
/**
|
|
179
|
+
* Returns the `DROP COLUMN` SQL statements for removing a single field.
|
|
180
|
+
* Drops the junction table for multi-relations, or alters the tables to drop the column.
|
|
181
|
+
*
|
|
182
|
+
* @param seed The seed definition.
|
|
183
|
+
* @param alias The alias of the branch to drop.
|
|
184
|
+
* @returns An array of SQL statements.
|
|
185
|
+
*/
|
|
186
|
+
export declare function generateDropColumn(seed: Seed, alias: string): string[];
|
|
187
|
+
/**
|
|
188
|
+
* Returns the `RENAME COLUMN` SQL statements for renaming a field's alias.
|
|
189
|
+
* For a multi-relation branch, renames the junction table (+ drafts junction table) instead.
|
|
190
|
+
*
|
|
191
|
+
* @param seed The seed definition.
|
|
192
|
+
* @param from The old alias.
|
|
193
|
+
* @param to The new alias.
|
|
194
|
+
* @returns An array of SQL statements.
|
|
195
|
+
*/
|
|
196
|
+
export declare function generateRenameColumn(seed: Seed, from: string, to: string): string[];
|
|
197
|
+
/**
|
|
198
|
+
* Returns the statements that change a column's SQL type in place using CAST, bypassing SQLite rebuild limitations.
|
|
199
|
+
*
|
|
200
|
+
* @param seed The seed definition.
|
|
201
|
+
* @param branch The target branch definition (carrying the new type).
|
|
202
|
+
* @throws {Error} If called on a multi-relation branch.
|
|
203
|
+
* @returns An array of SQL statements.
|
|
204
|
+
*/
|
|
205
|
+
export declare function generateRetypeColumn(seed: Seed, branch: Branch): string[];
|
|
206
|
+
/**
|
|
207
|
+
* Additive statements that turn soft delete on for a table that already exists.
|
|
208
|
+
*
|
|
209
|
+
* The partial unique index is emitted for correctness on tables that were CREATED with
|
|
210
|
+
* `softDelete: true`. On a pre-existing table the inline `slug … UNIQUE` survives as a
|
|
211
|
+
* sqlite_autoindex that SQLite cannot drop via ALTER; there the partial index is redundant
|
|
212
|
+
* and a trashed slug stays reserved until the table is rebuilt (see ROADMAP deferral).
|
|
213
|
+
* Returns [] when the seed does not opt in.
|
|
214
|
+
*/
|
|
215
|
+
export declare function generateEnableSoftDelete(seed: Seed): string[];
|
|
216
|
+
//# sourceMappingURL=ddl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ddl.d.ts","sourceRoot":"","sources":["../../src/engine/ddl.ts"],"names":[],"mappings":"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"}
|