@krantho/persistence-postgres 0.0.0-stage → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/LICENSE +21 -0
  2. package/dist/auth-adapter.d.ts +23 -0
  3. package/dist/auth-adapter.d.ts.map +1 -0
  4. package/dist/auth-adapter.js +159 -0
  5. package/dist/auth-adapter.js.map +1 -0
  6. package/dist/content-migration.d.ts +14 -0
  7. package/dist/content-migration.d.ts.map +1 -0
  8. package/dist/content-migration.js +64 -0
  9. package/dist/content-migration.js.map +1 -0
  10. package/dist/content-query.d.ts +23 -0
  11. package/dist/content-query.d.ts.map +1 -0
  12. package/dist/content-query.js +170 -0
  13. package/dist/content-query.js.map +1 -0
  14. package/dist/index.d.ts +17 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +15 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/migration-runner.d.ts +29 -0
  19. package/dist/migration-runner.d.ts.map +1 -0
  20. package/dist/migration-runner.js +123 -0
  21. package/dist/migration-runner.js.map +1 -0
  22. package/dist/migrations/index.d.ts +4 -0
  23. package/dist/migrations/index.d.ts.map +1 -0
  24. package/dist/migrations/index.js +32 -0
  25. package/dist/migrations/index.js.map +1 -0
  26. package/dist/migrations/v001-initial-schema.d.ts +10 -0
  27. package/dist/migrations/v001-initial-schema.d.ts.map +1 -0
  28. package/dist/migrations/v001-initial-schema.js +94 -0
  29. package/dist/migrations/v001-initial-schema.js.map +1 -0
  30. package/dist/migrations/v002-auth-tables.d.ts +8 -0
  31. package/dist/migrations/v002-auth-tables.d.ts.map +1 -0
  32. package/dist/migrations/v002-auth-tables.js +37 -0
  33. package/dist/migrations/v002-auth-tables.js.map +1 -0
  34. package/dist/migrations/v003-user-permissions.d.ts +6 -0
  35. package/dist/migrations/v003-user-permissions.d.ts.map +1 -0
  36. package/dist/migrations/v003-user-permissions.js +18 -0
  37. package/dist/migrations/v003-user-permissions.js.map +1 -0
  38. package/dist/migrations/v004-media-hotspot.d.ts +14 -0
  39. package/dist/migrations/v004-media-hotspot.d.ts.map +1 -0
  40. package/dist/migrations/v004-media-hotspot.js +25 -0
  41. package/dist/migrations/v004-media-hotspot.js.map +1 -0
  42. package/dist/migrations/v005-content-locks.d.ts +6 -0
  43. package/dist/migrations/v005-content-locks.d.ts.map +1 -0
  44. package/dist/migrations/v005-content-locks.js +21 -0
  45. package/dist/migrations/v005-content-locks.js.map +1 -0
  46. package/dist/migrations/v006-webhook-deliveries.d.ts +6 -0
  47. package/dist/migrations/v006-webhook-deliveries.d.ts.map +1 -0
  48. package/dist/migrations/v006-webhook-deliveries.js +24 -0
  49. package/dist/migrations/v006-webhook-deliveries.js.map +1 -0
  50. package/dist/migrations/v007-media-folders.d.ts +6 -0
  51. package/dist/migrations/v007-media-folders.d.ts.map +1 -0
  52. package/dist/migrations/v007-media-folders.js +19 -0
  53. package/dist/migrations/v007-media-folders.js.map +1 -0
  54. package/dist/migrations/v008-site-settings.d.ts +6 -0
  55. package/dist/migrations/v008-site-settings.d.ts.map +1 -0
  56. package/dist/migrations/v008-site-settings.js +17 -0
  57. package/dist/migrations/v008-site-settings.js.map +1 -0
  58. package/dist/migrations/v009-seo-config.d.ts +12 -0
  59. package/dist/migrations/v009-seo-config.d.ts.map +1 -0
  60. package/dist/migrations/v009-seo-config.js +27 -0
  61. package/dist/migrations/v009-seo-config.js.map +1 -0
  62. package/dist/migrations/v010-content-live-version.d.ts +15 -0
  63. package/dist/migrations/v010-content-live-version.d.ts.map +1 -0
  64. package/dist/migrations/v010-content-live-version.js +40 -0
  65. package/dist/migrations/v010-content-live-version.js.map +1 -0
  66. package/dist/migrations/v011-media.d.ts +12 -0
  67. package/dist/migrations/v011-media.d.ts.map +1 -0
  68. package/dist/migrations/v011-media.js +43 -0
  69. package/dist/migrations/v011-media.js.map +1 -0
  70. package/dist/migrations/v012-page-cache.d.ts +12 -0
  71. package/dist/migrations/v012-page-cache.d.ts.map +1 -0
  72. package/dist/migrations/v012-page-cache.js +31 -0
  73. package/dist/migrations/v012-page-cache.js.map +1 -0
  74. package/dist/migrations/v013-content-contracts.d.ts +17 -0
  75. package/dist/migrations/v013-content-contracts.d.ts.map +1 -0
  76. package/dist/migrations/v013-content-contracts.js +41 -0
  77. package/dist/migrations/v013-content-contracts.js.map +1 -0
  78. package/dist/migrations/v014-content-manifest-commit.d.ts +7 -0
  79. package/dist/migrations/v014-content-manifest-commit.d.ts.map +1 -0
  80. package/dist/migrations/v014-content-manifest-commit.js +12 -0
  81. package/dist/migrations/v014-content-manifest-commit.js.map +1 -0
  82. package/dist/postgres-adapter.d.ts +71 -0
  83. package/dist/postgres-adapter.d.ts.map +1 -0
  84. package/dist/postgres-adapter.js +327 -0
  85. package/dist/postgres-adapter.js.map +1 -0
  86. package/dist/postgres-checkpoints.d.ts +20 -0
  87. package/dist/postgres-checkpoints.d.ts.map +1 -0
  88. package/dist/postgres-checkpoints.js +109 -0
  89. package/dist/postgres-checkpoints.js.map +1 -0
  90. package/dist/postgres-lock-adapter.d.ts +12 -0
  91. package/dist/postgres-lock-adapter.d.ts.map +1 -0
  92. package/dist/postgres-lock-adapter.js +62 -0
  93. package/dist/postgres-lock-adapter.js.map +1 -0
  94. package/dist/postgres-media-adapter.d.ts +28 -0
  95. package/dist/postgres-media-adapter.d.ts.map +1 -0
  96. package/dist/postgres-media-adapter.js +167 -0
  97. package/dist/postgres-media-adapter.js.map +1 -0
  98. package/dist/postgres-media-folder-adapter.d.ts +12 -0
  99. package/dist/postgres-media-folder-adapter.d.ts.map +1 -0
  100. package/dist/postgres-media-folder-adapter.js +60 -0
  101. package/dist/postgres-media-folder-adapter.js.map +1 -0
  102. package/dist/postgres-page-cache-store.d.ts +23 -0
  103. package/dist/postgres-page-cache-store.d.ts.map +1 -0
  104. package/dist/postgres-page-cache-store.js +80 -0
  105. package/dist/postgres-page-cache-store.js.map +1 -0
  106. package/dist/postgres-retention-adapter.d.ts +14 -0
  107. package/dist/postgres-retention-adapter.d.ts.map +1 -0
  108. package/dist/postgres-retention-adapter.js +61 -0
  109. package/dist/postgres-retention-adapter.js.map +1 -0
  110. package/dist/postgres-seo-config-adapter.d.ts +14 -0
  111. package/dist/postgres-seo-config-adapter.d.ts.map +1 -0
  112. package/dist/postgres-seo-config-adapter.js +59 -0
  113. package/dist/postgres-seo-config-adapter.js.map +1 -0
  114. package/dist/postgres-site-settings-adapter.d.ts +11 -0
  115. package/dist/postgres-site-settings-adapter.d.ts.map +1 -0
  116. package/dist/postgres-site-settings-adapter.js +30 -0
  117. package/dist/postgres-site-settings-adapter.js.map +1 -0
  118. package/dist/postgres-webhook-delivery-adapter.d.ts +27 -0
  119. package/dist/postgres-webhook-delivery-adapter.d.ts.map +1 -0
  120. package/dist/postgres-webhook-delivery-adapter.js +99 -0
  121. package/dist/postgres-webhook-delivery-adapter.js.map +1 -0
  122. package/dist/row-mapping.d.ts +40 -0
  123. package/dist/row-mapping.d.ts.map +1 -0
  124. package/dist/row-mapping.js +49 -0
  125. package/dist/row-mapping.js.map +1 -0
  126. package/package.json +39 -3
  127. package/README.md +0 -3
@@ -0,0 +1,327 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { canonicalJson } from '@krantho/core';
3
+ import { authoredOf, ContentWriteConflict, liveOnWrite, nextAuthored, publicationOfFile, resolveLiveVersion, sameAuthoredValues, storedStatus, } from '@krantho/persistence';
4
+ import { runContentQuery } from './content-query.js';
5
+ import { runMigrations } from './migration-runner.js';
6
+ import { postgresMigrations } from './migrations/index.js';
7
+ import { rowToContentDocument, rowToDocumentMeta } from './row-mapping.js';
8
+ /**
9
+ * Status default used when a file declares none.
10
+ *
11
+ * A deployment sets it through `content.defaultStatus.filesystem` in the
12
+ * krantho configuration tree; the server passes the resolved value down. This
13
+ * literal is the standalone-library fallback and mirrors that tree's default.
14
+ */
15
+ export const DEFAULT_POSTGRES_STATUS = {
16
+ filesystem: 'published',
17
+ };
18
+ export class PostgresAdapter {
19
+ sql;
20
+ defaultStatus;
21
+ defaultLocale;
22
+ initialization = null;
23
+ constructor(sql, options) {
24
+ this.sql = sql;
25
+ this.defaultLocale = options.defaultLocale;
26
+ this.defaultStatus = { ...DEFAULT_POSTGRES_STATUS, ...options.defaultStatus };
27
+ }
28
+ static async create(sql, options) {
29
+ const adapter = new PostgresAdapter(sql, options);
30
+ await adapter.ensureInitialized();
31
+ return adapter;
32
+ }
33
+ /**
34
+ * Run migrations once per instance. Concurrent callers share the in-flight
35
+ * run; a failed run is dropped so the next call retries it.
36
+ */
37
+ ensureInitialized() {
38
+ this.initialization ??= runMigrations(this.sql, postgresMigrations).then(() => undefined, (err) => {
39
+ this.initialization = null;
40
+ throw err;
41
+ });
42
+ return this.initialization;
43
+ }
44
+ // --- IContentLoader methods ---
45
+ async exists(slug) {
46
+ await this.ensureInitialized();
47
+ const rows = await this.sql `
48
+ SELECT COUNT(*) as count FROM content
49
+ WHERE slug = ${slug} AND is_current = TRUE AND deleted_at IS NULL`;
50
+ return parseInt(rows[0]?.count ?? '0', 10) > 0;
51
+ }
52
+ async read(slug) {
53
+ await this.ensureInitialized();
54
+ const rows = await this.sql `
55
+ SELECT * FROM content
56
+ WHERE slug = ${slug} AND is_current = TRUE AND deleted_at IS NULL
57
+ LIMIT 1`;
58
+ const row = rows[0];
59
+ if (!row)
60
+ throw new Error(`Content not found: ${slug}`);
61
+ const yamlLines = Object.entries(row.fields).map(([k, v]) => `${k}: ${JSON.stringify(v)}`);
62
+ return `---\n${yamlLines.join('\n')}\n---\n${row.body}`;
63
+ }
64
+ async getMetadata(slug) {
65
+ await this.ensureInitialized();
66
+ const rows = await this.sql `
67
+ SELECT * FROM content
68
+ WHERE slug = ${slug} AND is_current = TRUE AND deleted_at IS NULL
69
+ LIMIT 1`;
70
+ const row = rows[0];
71
+ if (!row)
72
+ throw new Error(`Content not found: ${slug}`);
73
+ return {
74
+ size: row.body.length + JSON.stringify(row.fields).length,
75
+ lastModified: new Date(row.created_at),
76
+ };
77
+ }
78
+ // --- IPersistenceAdapter methods ---
79
+ async listSlugs() {
80
+ await this.ensureInitialized();
81
+ const rows = await this.sql `
82
+ SELECT DISTINCT slug FROM content WHERE is_current = TRUE AND deleted_at IS NULL`;
83
+ return rows.map((r) => r.slug);
84
+ }
85
+ async writeContent(data, changedBy) {
86
+ await this.ensureInitialized();
87
+ await this.appendVersion(data.collection, data.slug, data.locale ?? this.defaultLocale, {
88
+ authored: authoredOf(data),
89
+ expectedVersion: data.expectedVersion,
90
+ fields: data.fields,
91
+ body: data.body,
92
+ html: data.html ?? '',
93
+ sections: data.sections ?? {},
94
+ source: 'api',
95
+ filePath: null,
96
+ changedBy: changedBy ?? null,
97
+ publication: data.publication,
98
+ });
99
+ }
100
+ async deleteContent(collection, slug, locale, changedBy) {
101
+ await this.ensureInitialized();
102
+ const loc = locale ?? this.defaultLocale;
103
+ const rows = await this.sql `
104
+ SELECT * FROM content
105
+ WHERE collection = ${collection} AND slug = ${slug} AND locale = ${loc}
106
+ AND is_current = TRUE AND deleted_at IS NULL
107
+ LIMIT 1`;
108
+ const row = rows[0];
109
+ if (!row)
110
+ return;
111
+ const maxRows = await this.sql `
112
+ SELECT MAX(version) as max_version FROM content
113
+ WHERE collection = ${collection} AND slug = ${slug} AND locale = ${row.locale}`;
114
+ const nextVersion = (maxRows[0]?.max_version ?? 0) + 1;
115
+ const now = new Date().toISOString();
116
+ await this.sql.begin(async (tx) => {
117
+ await tx.unsafe('UPDATE content SET is_current = FALSE WHERE collection = $1 AND slug = $2 AND locale = $3 AND is_current = TRUE', [collection, slug, row.locale]);
118
+ await tx.unsafe(`INSERT INTO content (id, collection, slug, locale, version, is_current, status, fields, body, html, sections, source, file_path, changed_by, deleted_at, created_at, live_version)
119
+ VALUES ($1, $2, $3, $4, $5, TRUE, 'deleted', '{}'::jsonb, '', '', '{}'::jsonb, 'api', NULL, $6, $7, $7, NULL)`, [randomUUID(), collection, slug, row.locale, nextVersion, changedBy ?? null, now]);
120
+ });
121
+ }
122
+ async getContent(collection, slug, locale) {
123
+ await this.ensureInitialized();
124
+ const loc = locale ?? this.defaultLocale;
125
+ const rows = await this.sql `
126
+ SELECT * FROM content
127
+ WHERE collection = ${collection} AND slug = ${slug} AND locale = ${loc}
128
+ AND is_current = TRUE AND deleted_at IS NULL
129
+ LIMIT 1`;
130
+ const row = rows[0];
131
+ return row ? rowToContentDocument(row) : null;
132
+ }
133
+ async getPublished(collection, slug, locale) {
134
+ await this.ensureInitialized();
135
+ const loc = locale ?? this.defaultLocale;
136
+ const rows = await this.sql `
137
+ SELECT live.* FROM content cur
138
+ JOIN content live ON live.collection = cur.collection AND live.slug = cur.slug
139
+ AND live.locale = cur.locale AND live.version = cur.live_version
140
+ WHERE cur.collection = ${collection} AND cur.slug = ${slug} AND cur.locale = ${loc}
141
+ AND cur.is_current = TRUE AND cur.deleted_at IS NULL
142
+ LIMIT 1`;
143
+ const row = rows[0];
144
+ return row ? rowToContentDocument(row) : null;
145
+ }
146
+ async query(spec) {
147
+ await this.ensureInitialized();
148
+ return runContentQuery(this.sql, spec);
149
+ }
150
+ async listVersions(collection, slug, locale) {
151
+ await this.ensureInitialized();
152
+ const loc = locale ?? this.defaultLocale;
153
+ const rows = await this.sql `
154
+ SELECT id, collection, slug, locale, version, is_current, status, source, file_path,
155
+ changed_by, deleted_at, created_at, live_version
156
+ FROM content
157
+ WHERE collection = ${collection} AND slug = ${slug} AND locale = ${loc}
158
+ ORDER BY version DESC`;
159
+ return rows.map(rowToDocumentMeta);
160
+ }
161
+ async getVersion(collection, slug, version, locale) {
162
+ await this.ensureInitialized();
163
+ const loc = locale ?? this.defaultLocale;
164
+ const rows = await this.sql `
165
+ SELECT * FROM content
166
+ WHERE collection = ${collection} AND slug = ${slug} AND locale = ${loc} AND version = ${version}
167
+ LIMIT 1`;
168
+ const row = rows[0];
169
+ return row ? rowToContentDocument(row) : null;
170
+ }
171
+ /**
172
+ * Import a filesystem content item — creates a new version if content changed.
173
+ * `modifiedAt` (ISO 8601) dates the version when the file last changed, such as
174
+ * its last git commit; without it the version is dated now.
175
+ */
176
+ async upsertFromFile(collection, slug, fields, body, html, sections, filePath, locale, modifiedAt, authored) {
177
+ await this.ensureInitialized();
178
+ const loc = locale ?? this.defaultLocale;
179
+ const status = typeof fields['status'] === 'string' ? fields['status'] : this.defaultStatus.filesystem;
180
+ // Check if content exists and is unchanged
181
+ const existing = await this.sql `
182
+ SELECT * FROM content
183
+ WHERE collection = ${collection} AND slug = ${slug} AND locale = ${loc}
184
+ AND is_current = TRUE AND deleted_at IS NULL
185
+ LIMIT 1`;
186
+ const row = existing[0];
187
+ if (row &&
188
+ canonicalJson(row.fields) === canonicalJson(fields) &&
189
+ row.body === body &&
190
+ sameAuthoredValues(row.authored, authored ?? {})) {
191
+ return; // No change — skip
192
+ }
193
+ await this.appendVersion(collection, slug, loc, {
194
+ fields,
195
+ body,
196
+ html,
197
+ sections,
198
+ source: 'filesystem',
199
+ filePath,
200
+ changedBy: null,
201
+ publication: authored ? authored.publication : publicationOfFile(status),
202
+ authored: authoredOf(authored ?? {}),
203
+ expectedVersion: authored?.expectedVersion,
204
+ createdAt: modifiedAt,
205
+ });
206
+ }
207
+ /** Restore content to a specific version — a save: a new current version from the old one, the live version kept */
208
+ async restoreVersion(collection, slug, version, changedBy, locale) {
209
+ await this.ensureInitialized();
210
+ const loc = locale ?? this.defaultLocale;
211
+ const rows = await this.sql `
212
+ SELECT * FROM content
213
+ WHERE collection = ${collection} AND slug = ${slug} AND locale = ${loc} AND version = ${version}
214
+ LIMIT 1`;
215
+ const target = rows[0];
216
+ if (!target)
217
+ return false;
218
+ await this.appendVersion(collection, slug, target.locale, {
219
+ authored: target.authored,
220
+ fields: target.fields,
221
+ body: target.body,
222
+ html: target.html,
223
+ sections: target.sections,
224
+ source: target.source,
225
+ filePath: target.file_path,
226
+ changedBy: changedBy ?? `restore:v${version}`,
227
+ publication: undefined,
228
+ });
229
+ return true;
230
+ }
231
+ // --- Runtime Schema methods ---
232
+ async getRuntimeSchema(collection) {
233
+ await this.ensureInitialized();
234
+ const rows = await this.sql `SELECT collection, fields, metadata_groups, created_at FROM collection_schemas
235
+ WHERE collection = ${collection} AND is_current = TRUE AND deleted_at IS NULL`;
236
+ const row = rows[0];
237
+ if (!row)
238
+ return null;
239
+ return {
240
+ collection: row.collection,
241
+ fields: row.fields,
242
+ metadata: row.metadata_groups,
243
+ updatedAt: row.created_at instanceof Date ? row.created_at.toISOString() : String(row.created_at),
244
+ };
245
+ }
246
+ async saveRuntimeSchema(collection, schema, changedBy) {
247
+ await this.ensureInitialized();
248
+ const current = await this.sql `
249
+ SELECT version FROM collection_schemas
250
+ WHERE collection = ${collection} AND is_current = TRUE`;
251
+ const nextVersion = current[0] ? current[0].version + 1 : 1;
252
+ const now = new Date().toISOString();
253
+ // See `appendVersion` for the JSONB binding explanation — `sql.json()`
254
+ // wraps the fields array as a JSONB parameter so the driver binds it
255
+ // as an object, not a JSON-text-wrapped-as-string.
256
+ await this.sql.begin(async (tx) => {
257
+ if (current[0]) {
258
+ await tx.unsafe('UPDATE collection_schemas SET is_current = FALSE WHERE collection = $1 AND is_current = TRUE', [collection]);
259
+ }
260
+ await tx.unsafe(`INSERT INTO collection_schemas (row_id, collection, version, is_current, fields, changed_by, created_at, metadata_groups)
261
+ VALUES ($1, $2, $3, TRUE, $4, $5, $6, $7)`, [
262
+ randomUUID(),
263
+ collection,
264
+ nextVersion,
265
+ this.sql.json(schema.fields),
266
+ changedBy ?? null,
267
+ now,
268
+ this.sql.json((schema.metadata ?? [])),
269
+ ]);
270
+ });
271
+ }
272
+ /** Close the database connection */
273
+ async close() {
274
+ await this.sql.end();
275
+ }
276
+ // --- Private helpers ---
277
+ /**
278
+ * Core append-only write: flip current, insert the new version. Its live
279
+ * version follows the write's publication (a save keeps it) and its stored
280
+ * status follows the live version.
281
+ */
282
+ async appendVersion(collection, slug, locale, data) {
283
+ const now = data.createdAt ?? new Date().toISOString();
284
+ // JSONB binding note: the postgres driver's `sql.json(value)` helper
285
+ // wraps an object as a JSONB parameter for `.unsafe()` calls. A previous
286
+ // implementation used `JSON.stringify(fields)` with a `::jsonb` cast,
287
+ // which double-encoded the value — JSONB stored the JSON text as a
288
+ // string literal, so every read returned the stringified text instead of
289
+ // the parsed object. Pass objects through `this.sql.json(...)` to bind
290
+ // correctly as JSONB without the redundant text→jsonb cast.
291
+ await this.sql.begin(async (tx) => {
292
+ await tx `SELECT pg_advisory_xact_lock(hashtextextended(${JSON.stringify([collection, slug, locale])}, 0))`;
293
+ const maxRows = await tx `
294
+ SELECT MAX(version) as max_version FROM content
295
+ WHERE collection = ${collection} AND slug = ${slug} AND locale = ${locale}`;
296
+ const nextVersion = (maxRows[0]?.max_version ?? 0) + 1;
297
+ if (data.expectedVersion !== undefined &&
298
+ data.expectedVersion !== (maxRows[0]?.max_version ?? 0)) {
299
+ throw new ContentWriteConflict(maxRows[0]?.max_version ?? 0, data.expectedVersion);
300
+ }
301
+ const previous = (await tx.unsafe('SELECT live_version, status, authored FROM content WHERE collection = $1 AND slug = $2 AND locale = $3 AND is_current = TRUE', [collection, slug, locale]));
302
+ const liveVersion = resolveLiveVersion(liveOnWrite(data.publication), nextVersion, previous[0]?.live_version ?? null);
303
+ const status = storedStatus(data.publication, liveVersion, previous[0]?.status);
304
+ await tx.unsafe('UPDATE content SET is_current = FALSE WHERE collection = $1 AND slug = $2 AND locale = $3 AND is_current = TRUE', [collection, slug, locale]);
305
+ await tx.unsafe(`INSERT INTO content (id, collection, slug, locale, version, is_current, status, fields, body, html, sections, source, file_path, changed_by, created_at, live_version, authored)
306
+ VALUES ($1, $2, $3, $4, $5, TRUE, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)`, [
307
+ randomUUID(),
308
+ collection,
309
+ slug,
310
+ locale,
311
+ nextVersion,
312
+ status,
313
+ this.sql.json(data.fields),
314
+ data.body,
315
+ data.html,
316
+ this.sql.json(data.sections),
317
+ data.source,
318
+ data.filePath,
319
+ data.changedBy,
320
+ now,
321
+ liveVersion,
322
+ this.sql.json(nextAuthored(previous[0]?.authored ?? null, data.authored ?? {}, nextVersion)),
323
+ ]);
324
+ });
325
+ }
326
+ }
327
+ //# sourceMappingURL=postgres-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres-adapter.js","sourceRoot":"","sources":["../src/postgres-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { CheckpointInfo, CheckpointTrigger, ICheckpointAdapter } from '@krantho/persistence';
2
+ import type { Sql } from 'postgres';
3
+ /**
4
+ * Postgres checkpoint adapter.
5
+ *
6
+ * Checkpoints are lightweight timestamp markers. Creating a checkpoint
7
+ * records the current timestamp. Restoring a checkpoint rewinds all
8
+ * versioned tables to their state at that timestamp by flipping
9
+ * `is_current` flags.
10
+ */
11
+ export declare class PostgresCheckpointAdapter implements ICheckpointAdapter {
12
+ private readonly sql;
13
+ constructor(sql: Sql);
14
+ createCheckpoint(name?: string, trigger?: CheckpointTrigger): Promise<CheckpointInfo>;
15
+ listCheckpoints(): Promise<CheckpointInfo[]>;
16
+ getCheckpoint(version: number): Promise<CheckpointInfo | null>;
17
+ restoreCheckpoint(version: number): Promise<CheckpointInfo>;
18
+ deleteCheckpoint(version: number): Promise<boolean>;
19
+ }
20
+ //# sourceMappingURL=postgres-checkpoints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres-checkpoints.d.ts","sourceRoot":"","sources":["../src/postgres-checkpoints.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AACjG,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAqBnC;;;;;;;GAOG;AACH,qBAAa,yBAA0B,YAAW,kBAAkB;IACtD,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,GAAG;IAE/B,gBAAgB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC;IA4BrF,eAAe,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAM5C,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAO9D,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAmE3D,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAK1D"}
@@ -0,0 +1,109 @@
1
+ function rowToCheckpointInfo(row) {
2
+ return {
3
+ id: row.id,
4
+ version: row.version,
5
+ name: row.name,
6
+ trigger: row.trigger,
7
+ createdAt: row.created_at instanceof Date ? row.created_at.toISOString() : String(row.created_at),
8
+ };
9
+ }
10
+ /**
11
+ * Postgres checkpoint adapter.
12
+ *
13
+ * Checkpoints are lightweight timestamp markers. Creating a checkpoint
14
+ * records the current timestamp. Restoring a checkpoint rewinds all
15
+ * versioned tables to their state at that timestamp by flipping
16
+ * `is_current` flags.
17
+ */
18
+ export class PostgresCheckpointAdapter {
19
+ sql;
20
+ constructor(sql) {
21
+ this.sql = sql;
22
+ }
23
+ async createCheckpoint(name, trigger) {
24
+ const now = new Date().toISOString();
25
+ const triggerValue = trigger ?? 'manual';
26
+ // Allocate next version number and insert checkpoint in a transaction
27
+ const result = await this.sql.begin(async (tx) => {
28
+ const versionRows = (await tx.unsafe('UPDATE checkpoint_counter SET next = next + 1 RETURNING next - 1 as version'));
29
+ const version = versionRows[0].version;
30
+ const insertRows = (await tx.unsafe('INSERT INTO checkpoints (version, name, trigger, created_at) VALUES ($1, $2, $3, $4) RETURNING id', [version, name ?? null, triggerValue, now]));
31
+ return { id: insertRows[0].id, version };
32
+ });
33
+ return {
34
+ id: result.id,
35
+ version: result.version,
36
+ name: name ?? null,
37
+ trigger: triggerValue,
38
+ createdAt: now,
39
+ };
40
+ }
41
+ async listCheckpoints() {
42
+ const rows = await this.sql `
43
+ SELECT * FROM checkpoints ORDER BY version DESC`;
44
+ return rows.map(rowToCheckpointInfo);
45
+ }
46
+ async getCheckpoint(version) {
47
+ const rows = await this.sql `
48
+ SELECT * FROM checkpoints WHERE version = ${version}`;
49
+ const row = rows[0];
50
+ return row ? rowToCheckpointInfo(row) : null;
51
+ }
52
+ async restoreCheckpoint(version) {
53
+ const checkpoint = await this.getCheckpoint(version);
54
+ if (!checkpoint) {
55
+ throw new Error(`Checkpoint version ${version} not found`);
56
+ }
57
+ // Create pre-restore checkpoint first
58
+ await this.createCheckpoint(`pre-restore-v${version}`, 'pre-restore');
59
+ const timestamp = checkpoint.createdAt;
60
+ // Restore all versioned tables to their state at checkpoint time
61
+ await this.sql.begin(async (tx) => {
62
+ // --- Content ---
63
+ // Clear all current flags
64
+ await tx.unsafe('UPDATE content SET is_current = FALSE WHERE is_current = TRUE');
65
+ // Re-activate the latest version of each entity that existed at checkpoint time
66
+ await tx.unsafe(`UPDATE content SET is_current = TRUE
67
+ WHERE id IN (
68
+ SELECT id FROM (
69
+ SELECT id, collection, slug, locale, created_at,
70
+ ROW_NUMBER() OVER (PARTITION BY collection, slug, locale ORDER BY version DESC) as rn
71
+ FROM content
72
+ WHERE created_at <= $1
73
+ AND (deleted_at IS NULL OR deleted_at > $1)
74
+ ) sub WHERE rn = 1
75
+ )`, [timestamp]);
76
+ // --- Collection schemas ---
77
+ await tx.unsafe('UPDATE collection_schemas SET is_current = FALSE WHERE is_current = TRUE');
78
+ await tx.unsafe(`UPDATE collection_schemas SET is_current = TRUE
79
+ WHERE row_id IN (
80
+ SELECT row_id FROM (
81
+ SELECT row_id, collection,
82
+ ROW_NUMBER() OVER (PARTITION BY collection ORDER BY version DESC) as rn
83
+ FROM collection_schemas
84
+ WHERE created_at <= $1
85
+ AND (deleted_at IS NULL OR deleted_at > $1)
86
+ ) sub WHERE rn = 1
87
+ )`, [timestamp]);
88
+ // --- Media ---
89
+ await tx.unsafe('UPDATE media SET is_current = FALSE WHERE is_current = TRUE');
90
+ await tx.unsafe(`UPDATE media SET is_current = TRUE
91
+ WHERE row_id IN (
92
+ SELECT row_id FROM (
93
+ SELECT row_id, id,
94
+ ROW_NUMBER() OVER (PARTITION BY id ORDER BY version DESC) as rn
95
+ FROM media
96
+ WHERE created_at <= $1
97
+ AND (deleted_at IS NULL OR deleted_at > $1)
98
+ ) sub WHERE rn = 1
99
+ )`, [timestamp]);
100
+ });
101
+ return checkpoint;
102
+ }
103
+ async deleteCheckpoint(version) {
104
+ const result = await this.sql `
105
+ DELETE FROM checkpoints WHERE version = ${version}`;
106
+ return result.count > 0;
107
+ }
108
+ }
109
+ //# sourceMappingURL=postgres-checkpoints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres-checkpoints.js","sourceRoot":"","sources":["../src/postgres-checkpoints.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { ContentLock, ILockAdapter } from '@krantho/persistence';
2
+ import type { Sql } from 'postgres';
3
+ /** Postgres implementation of advisory content locking */
4
+ export declare class PostgresLockAdapter implements ILockAdapter {
5
+ private readonly sql;
6
+ constructor(sql: Sql);
7
+ getLock(collection: string, slug: string, locale: string): Promise<ContentLock | null>;
8
+ acquireLock(collection: string, slug: string, locale: string, lockedBy: string, expiresAt: string): Promise<void>;
9
+ releaseLock(collection: string, slug: string, locale: string): Promise<void>;
10
+ listLocks(): Promise<ContentLock[]>;
11
+ }
12
+ //# sourceMappingURL=postgres-lock-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres-lock-adapter.d.ts","sourceRoot":"","sources":["../src/postgres-lock-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACrE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAWnC,0DAA0D;AAC1D,qBAAa,mBAAoB,YAAW,YAAY;IAC1C,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,GAAG;IAE/B,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IA6BtF,WAAW,CACf,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC;IAWV,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM5E,SAAS,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;CAe1C"}
@@ -0,0 +1,62 @@
1
+ /** Postgres implementation of advisory content locking */
2
+ export class PostgresLockAdapter {
3
+ sql;
4
+ constructor(sql) {
5
+ this.sql = sql;
6
+ }
7
+ async getLock(collection, slug, locale) {
8
+ const rows = await this.sql `
9
+ SELECT * FROM content_locks
10
+ WHERE collection = ${collection} AND slug = ${slug} AND locale = ${locale}`;
11
+ const row = rows[0];
12
+ if (!row)
13
+ return null;
14
+ // Clean up expired locks
15
+ const expiresAt = row.expires_at instanceof Date ? row.expires_at : new Date(String(row.expires_at));
16
+ if (expiresAt <= new Date()) {
17
+ await this.sql `
18
+ DELETE FROM content_locks
19
+ WHERE collection = ${collection} AND slug = ${slug} AND locale = ${locale}`;
20
+ return null;
21
+ }
22
+ const lockedAt = row.locked_at instanceof Date ? row.locked_at : new Date(String(row.locked_at));
23
+ return {
24
+ collection: row.collection,
25
+ slug: row.slug,
26
+ locale: row.locale,
27
+ lockedBy: row.locked_by,
28
+ lockedAt: lockedAt.toISOString(),
29
+ expiresAt: expiresAt.toISOString(),
30
+ };
31
+ }
32
+ async acquireLock(collection, slug, locale, lockedBy, expiresAt) {
33
+ const now = new Date().toISOString();
34
+ await this.sql `
35
+ INSERT INTO content_locks (collection, slug, locale, locked_by, locked_at, expires_at)
36
+ VALUES (${collection}, ${slug}, ${locale}, ${lockedBy}, ${now}, ${expiresAt})
37
+ ON CONFLICT (collection, slug, locale) DO UPDATE SET
38
+ locked_by = EXCLUDED.locked_by,
39
+ locked_at = EXCLUDED.locked_at,
40
+ expires_at = EXCLUDED.expires_at`;
41
+ }
42
+ async releaseLock(collection, slug, locale) {
43
+ await this.sql `
44
+ DELETE FROM content_locks
45
+ WHERE collection = ${collection} AND slug = ${slug} AND locale = ${locale}`;
46
+ }
47
+ async listLocks() {
48
+ await this.sql `DELETE FROM content_locks WHERE expires_at <= now()`;
49
+ const rows = await this.sql `
50
+ SELECT * FROM content_locks ORDER BY collection, slug, locale`;
51
+ const iso = (value) => (value instanceof Date ? value : new Date(String(value))).toISOString();
52
+ return rows.map((row) => ({
53
+ collection: row.collection,
54
+ slug: row.slug,
55
+ locale: row.locale,
56
+ lockedBy: row.locked_by,
57
+ lockedAt: iso(row.locked_at),
58
+ expiresAt: iso(row.expires_at),
59
+ }));
60
+ }
61
+ }
62
+ //# sourceMappingURL=postgres-lock-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres-lock-adapter.js","sourceRoot":"","sources":["../src/postgres-lock-adapter.ts"],"names":[],"mappings":"AAYA,0DAA0D;AAC1D,MAAM,OAAO,mBAAmB;IACD;IAA7B,YAA6B,GAAQ;QAAR,QAAG,GAAH,GAAG,CAAK;IAAG,CAAC;IAEzC,KAAK,CAAC,OAAO,CAAC,UAAkB,EAAE,IAAY,EAAE,MAAc;QAC5D,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAW;;2BAEf,UAAU,eAAe,IAAI,iBAAiB,MAAM,EAAE,CAAA;QAE7E,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;QACnB,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAA;QAErB,yBAAyB;QACzB,MAAM,SAAS,GACb,GAAG,CAAC,UAAU,YAAY,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAA;QACpF,IAAI,SAAS,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC;YAC5B,MAAM,IAAI,CAAC,GAAG,CAAA;;6BAES,UAAU,eAAe,IAAI,iBAAiB,MAAM,EAAE,CAAA;YAC7E,OAAO,IAAI,CAAA;QACb,CAAC;QAED,MAAM,QAAQ,GAAG,GAAG,CAAC,SAAS,YAAY,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAA;QAChG,OAAO;YACL,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,QAAQ,EAAE,GAAG,CAAC,SAAS;YACvB,QAAQ,EAAE,QAAQ,CAAC,WAAW,EAAE;YAChC,SAAS,EAAE,SAAS,CAAC,WAAW,EAAE;SACnC,CAAA;IACH,CAAC;IAED,KAAK,CAAC,WAAW,CACf,UAAkB,EAClB,IAAY,EACZ,MAAc,EACd,QAAgB,EAChB,SAAiB;QAEjB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;QACpC,MAAM,IAAI,CAAC,GAAG,CAAA;;gBAEF,UAAU,KAAK,IAAI,KAAK,MAAM,KAAK,QAAQ,KAAK,GAAG,KAAK,SAAS;;;;yCAIxC,CAAA;IACvC,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,UAAkB,EAAE,IAAY,EAAE,MAAc;QAChE,MAAM,IAAI,CAAC,GAAG,CAAA;;2BAES,UAAU,eAAe,IAAI,iBAAiB,MAAM,EAAE,CAAA;IAC/E,CAAC;IAED,KAAK,CAAC,SAAS;QACb,MAAM,IAAI,CAAC,GAAG,CAAA,qDAAqD,CAAA;QACnE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAW;oEAC0B,CAAA;QAChE,MAAM,GAAG,GAAG,CAAC,KAAW,EAAU,EAAE,CAClC,CAAC,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAA;QACzE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACxB,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,QAAQ,EAAE,GAAG,CAAC,SAAS;YACvB,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC;YAC5B,SAAS,EAAE,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC;SAC/B,CAAC,CAAC,CAAA;IACL,CAAC;CACF"}
@@ -0,0 +1,28 @@
1
+ import type { IMediaMetadataAdapter, MediaListOptions, MediaRecord, MediaRecordChanges, MediaStats, NewMediaRecord } from '@krantho/persistence';
2
+ import type { Sql } from 'postgres';
3
+ /**
4
+ * Postgres implementation of IMediaMetadataAdapter.
5
+ *
6
+ * Append-only: every change inserts a new version row and flips
7
+ * `is_current` inside one transaction; `UNIQUE (id, version)` rejects a
8
+ * concurrent duplicate. A delete appends a tombstone with `deleted_at` set.
9
+ */
10
+ export declare class PostgresMediaAdapter implements IMediaMetadataAdapter {
11
+ private readonly sql;
12
+ constructor(sql: Sql);
13
+ insert(record: NewMediaRecord): Promise<MediaRecord>;
14
+ get(id: string): Promise<MediaRecord | null>;
15
+ list(options?: MediaListOptions | undefined): Promise<{
16
+ items: MediaRecord[];
17
+ total: number;
18
+ }>;
19
+ appendVersion(id: string, changes: MediaRecordChanges): Promise<MediaRecord | null>;
20
+ markDeleted(id: string): Promise<MediaRecord | null>;
21
+ stats(): Promise<MediaStats>;
22
+ listTags(): Promise<string[]>;
23
+ /** Insert the next version of `id` and make it current, inside `tx` */
24
+ private writeVersion;
25
+ /** WHERE clause for current records matching search, folder, and tag filters */
26
+ private buildFilter;
27
+ }
28
+ //# sourceMappingURL=postgres-media-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres-media-adapter.d.ts","sourceRoot":"","sources":["../src/postgres-media-adapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,qBAAqB,EAGrB,gBAAgB,EAChB,WAAW,EACX,kBAAkB,EAClB,UAAU,EACV,cAAc,EACf,MAAM,sBAAsB,CAAA;AAE7B,OAAO,KAAK,EAAE,GAAG,EAAkB,MAAM,UAAU,CAAA;AA8BnD;;;;;;GAMG;AACH,qBAAa,oBAAqB,YAAW,qBAAqB;IACpD,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,GAAG;IAE/B,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IAQpD,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAK5C,IAAI,CACR,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,GACrC,OAAO,CAAC;QAAE,KAAK,EAAE,WAAW,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAe7C,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAUnF,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAUpD,KAAK,IAAI,OAAO,CAAC,UAAU,CAAC;IAW5B,QAAQ,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAOnC,uEAAuE;YACzD,YAAY;IAoC1B,gFAAgF;IAChF,OAAO,CAAC,WAAW;CA0BpB"}