@byline/db-postgres 3.0.0 → 3.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.
- package/dist/database/schema/index.js +3 -3
- package/dist/index.d.ts +4 -4
- package/dist/modules/storage/storage-commands.d.ts +6 -6
- package/dist/modules/storage/storage-commands.js +7 -7
- package/dist/modules/storage/storage-queries.d.ts +2 -2
- package/dist/modules/storage/storage-queries.js +2 -2
- package/dist/modules/storage/tests/storage-locale-fallback.test.js +0 -20
- package/package.json +4 -4
|
@@ -148,7 +148,7 @@ export const documentPaths = pgTable('byline_document_paths', {
|
|
|
148
148
|
// carries forward across edits and survives restore. Surfaced on reads as
|
|
149
149
|
// `availableLocales`; the public advertised set is the intersection with the
|
|
150
150
|
// ledger's `_availableVersionLocales`. Replaced wholesale on write (the lifecycle
|
|
151
|
-
// deletes then re-inserts the set), never appended. See docs/
|
|
151
|
+
// deletes then re-inserts the set), never appended. See docs/I18N.md.
|
|
152
152
|
export const documentAvailableLocales = pgTable('byline_document_available_locales', {
|
|
153
153
|
document_id: uuid('document_id')
|
|
154
154
|
.notNull()
|
|
@@ -172,7 +172,7 @@ export const documentAvailableLocales = pgTable('byline_document_available_local
|
|
|
172
172
|
// identically in any locale). Computed status-blind at write time and frozen
|
|
173
173
|
// on the immutable version, so restore / point-in-time reads stay consistent.
|
|
174
174
|
// Drives `localeFallback: 'strict'` reads via an indexed EXISTS gate without
|
|
175
|
-
// scanning the store_* tables. See docs/
|
|
175
|
+
// scanning the store_* tables. See docs/I18N.md.
|
|
176
176
|
export const documentVersionLocales = pgTable('byline_document_version_locales', {
|
|
177
177
|
document_version_id: uuid('document_version_id')
|
|
178
178
|
.notNull()
|
|
@@ -248,7 +248,7 @@ export const currentDocumentsView = pgView('byline_current_documents').as((qb) =
|
|
|
248
248
|
// read paths (`buildLocaleChain` / `pathProjection` / field-fallback)
|
|
249
249
|
// re-base onto the per-document source rather than the mutable global
|
|
250
250
|
// default — a primary-key join, already present for `order_key`.
|
|
251
|
-
// See docs/
|
|
251
|
+
// See docs/I18N.md.
|
|
252
252
|
source_locale: documents.source_locale,
|
|
253
253
|
})
|
|
254
254
|
.from(sq)
|
package/dist/index.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export interface PgAdapter extends IDbAdapter {
|
|
|
31
31
|
* existed, so `localeFallback: 'strict'` reads can see pre-existing
|
|
32
32
|
* documents. Idempotent; uses the configured default content locale. Kept
|
|
33
33
|
* off the core `IDbAdapter` contract (no service depends on it) — see
|
|
34
|
-
* docs/
|
|
34
|
+
* docs/I18N.md.
|
|
35
35
|
*/
|
|
36
36
|
backfillVersionLocales(): Promise<{
|
|
37
37
|
rowsInserted: number;
|
|
@@ -42,7 +42,7 @@ export interface PgAdapter extends IDbAdapter {
|
|
|
42
42
|
* default content locale (the anchor they were implicitly authored against).
|
|
43
43
|
* Idempotent; run automatically at boot by `initBylineCore` (also exposed on
|
|
44
44
|
* the core `IDbAdapter` contract as an optional method) — see
|
|
45
|
-
* docs/
|
|
45
|
+
* docs/I18N.md.
|
|
46
46
|
*/
|
|
47
47
|
backfillSourceLocales(): Promise<{
|
|
48
48
|
rowsUpdated: number;
|
|
@@ -53,7 +53,7 @@ export interface PgAdapter extends IDbAdapter {
|
|
|
53
53
|
* unless the document is complete in the target. Writes a new immutable
|
|
54
54
|
* version. `dryRun` reports the would-be outcome without writing. Off the
|
|
55
55
|
* core `IDbAdapter` contract (maintenance/admin operation) — see
|
|
56
|
-
* docs/
|
|
56
|
+
* docs/I18N.md.
|
|
57
57
|
*/
|
|
58
58
|
reAnchorDocument(params: {
|
|
59
59
|
documentId: string;
|
|
@@ -83,7 +83,7 @@ export declare const pgAdapter: ({ connectionString, collections, defaultContent
|
|
|
83
83
|
* for documents whose `source_locale` is not yet backfilled. Per-document
|
|
84
84
|
* reads and writes otherwise re-base onto each document's own `source_locale`
|
|
85
85
|
* (carried on the current-documents views), so changing this value does not
|
|
86
|
-
* re-interpret existing data. See docs/
|
|
86
|
+
* re-interpret existing data. See docs/I18N.md.
|
|
87
87
|
*/
|
|
88
88
|
defaultContentLocale: string;
|
|
89
89
|
/**
|
|
@@ -104,7 +104,7 @@ export declare class DocumentCommands implements IDocumentCommands {
|
|
|
104
104
|
* `undefined` leaves the existing set untouched (sticky across versions,
|
|
105
105
|
* like `path`); an empty array clears it (advertise nothing). The locale
|
|
106
106
|
* values are the advertised content locales themselves, not the default
|
|
107
|
-
* locale. See docs/
|
|
107
|
+
* locale. See docs/I18N.md.
|
|
108
108
|
*/
|
|
109
109
|
availableLocales?: string[];
|
|
110
110
|
locale?: string;
|
|
@@ -139,7 +139,7 @@ export declare class DocumentCommands implements IDocumentCommands {
|
|
|
139
139
|
* so callers must have written them first. Shared by the create write path
|
|
140
140
|
* (step 6) and `reAnchorDocument` (which recomputes against the new source).
|
|
141
141
|
* Assumes the version has no ledger rows yet (a freshly-inserted version).
|
|
142
|
-
* See docs/
|
|
142
|
+
* See docs/I18N.md.
|
|
143
143
|
*/
|
|
144
144
|
private writeVersionLocaleLedger;
|
|
145
145
|
/**
|
|
@@ -167,7 +167,7 @@ export declare class DocumentCommands implements IDocumentCommands {
|
|
|
167
167
|
* identities preserved), and computes that version's ledger against the new
|
|
168
168
|
* source. `dryRun` performs only the eligibility check and reports the
|
|
169
169
|
* outcome that *would* result, writing nothing. See
|
|
170
|
-
* docs/
|
|
170
|
+
* docs/I18N.md.
|
|
171
171
|
*/
|
|
172
172
|
reAnchorDocument(params: {
|
|
173
173
|
documentId: string;
|
|
@@ -185,7 +185,7 @@ export declare class DocumentCommands implements IDocumentCommands {
|
|
|
185
185
|
* "client switched the default content locale, move every fully-translated
|
|
186
186
|
* document onto it" operation; the `skipped-incomplete` results double as the
|
|
187
187
|
* outstanding-translation backlog. `dryRun` reports what would happen without
|
|
188
|
-
* writing. See docs/
|
|
188
|
+
* writing. See docs/I18N.md.
|
|
189
189
|
*/
|
|
190
190
|
reAnchorDocuments(params: {
|
|
191
191
|
targetLocale: string;
|
|
@@ -211,7 +211,7 @@ export declare class DocumentCommands implements IDocumentCommands {
|
|
|
211
211
|
* a version's computed locale set never changes. Returns the number of
|
|
212
212
|
* `(version, locale)` rows inserted.
|
|
213
213
|
*
|
|
214
|
-
* See docs/
|
|
214
|
+
* See docs/I18N.md.
|
|
215
215
|
*/
|
|
216
216
|
backfillVersionLocales(): Promise<{
|
|
217
217
|
rowsInserted: number;
|
|
@@ -230,7 +230,7 @@ export declare class DocumentCommands implements IDocumentCommands {
|
|
|
230
230
|
*
|
|
231
231
|
* Returns the number of document rows stamped.
|
|
232
232
|
*
|
|
233
|
-
* See docs/
|
|
233
|
+
* See docs/I18N.md.
|
|
234
234
|
*/
|
|
235
235
|
backfillSourceLocales(): Promise<{
|
|
236
236
|
rowsUpdated: number;
|
|
@@ -77,7 +77,7 @@ export class DocumentCommands {
|
|
|
77
77
|
// source locale rather than the mutable global default. NULL (a row not
|
|
78
78
|
// yet touched by `backfillSourceLocales`) falls back to the configured
|
|
79
79
|
// default — the value it was implicitly authored against.
|
|
80
|
-
// See docs/
|
|
80
|
+
// See docs/I18N.md.
|
|
81
81
|
let sourceLocale;
|
|
82
82
|
if (documentId == null) {
|
|
83
83
|
documentId = uuidv7();
|
|
@@ -271,7 +271,7 @@ export class DocumentCommands {
|
|
|
271
271
|
// accounts for the per-locale carry-forward in step 5 — not just the
|
|
272
272
|
// freshly-flattened locale. A version with no localized content at all
|
|
273
273
|
// records a single `'all'` sentinel (it renders identically in any
|
|
274
|
-
// locale). Status-blind by design — see docs/
|
|
274
|
+
// locale). Status-blind by design — see docs/I18N.md.
|
|
275
275
|
await this.writeVersionLocaleLedger(tx, documentVersion.id, sourceLocale);
|
|
276
276
|
return {
|
|
277
277
|
document: documentVersion,
|
|
@@ -289,7 +289,7 @@ export class DocumentCommands {
|
|
|
289
289
|
* so callers must have written them first. Shared by the create write path
|
|
290
290
|
* (step 6) and `reAnchorDocument` (which recomputes against the new source).
|
|
291
291
|
* Assumes the version has no ledger rows yet (a freshly-inserted version).
|
|
292
|
-
* See docs/
|
|
292
|
+
* See docs/I18N.md.
|
|
293
293
|
*/
|
|
294
294
|
async writeVersionLocaleLedger(tx, versionId, sourceLocale) {
|
|
295
295
|
await tx.execute(sql `
|
|
@@ -398,7 +398,7 @@ export class DocumentCommands {
|
|
|
398
398
|
* identities preserved), and computes that version's ledger against the new
|
|
399
399
|
* source. `dryRun` performs only the eligibility check and reports the
|
|
400
400
|
* outcome that *would* result, writing nothing. See
|
|
401
|
-
* docs/
|
|
401
|
+
* docs/I18N.md.
|
|
402
402
|
*/
|
|
403
403
|
async reAnchorDocument(params) {
|
|
404
404
|
const { documentId, targetLocale, dryRun = false } = params;
|
|
@@ -479,7 +479,7 @@ export class DocumentCommands {
|
|
|
479
479
|
* "client switched the default content locale, move every fully-translated
|
|
480
480
|
* document onto it" operation; the `skipped-incomplete` results double as the
|
|
481
481
|
* outstanding-translation backlog. `dryRun` reports what would happen without
|
|
482
|
-
* writing. See docs/
|
|
482
|
+
* writing. See docs/I18N.md.
|
|
483
483
|
*/
|
|
484
484
|
async reAnchorDocuments(params) {
|
|
485
485
|
const { targetLocale, collectionId, dryRun = false } = params;
|
|
@@ -540,7 +540,7 @@ export class DocumentCommands {
|
|
|
540
540
|
* a version's computed locale set never changes. Returns the number of
|
|
541
541
|
* `(version, locale)` rows inserted.
|
|
542
542
|
*
|
|
543
|
-
* See docs/
|
|
543
|
+
* See docs/I18N.md.
|
|
544
544
|
*/
|
|
545
545
|
async backfillVersionLocales() {
|
|
546
546
|
const result = await this.db.execute(sql `
|
|
@@ -598,7 +598,7 @@ export class DocumentCommands {
|
|
|
598
598
|
*
|
|
599
599
|
* Returns the number of document rows stamped.
|
|
600
600
|
*
|
|
601
|
-
* See docs/
|
|
601
|
+
* See docs/I18N.md.
|
|
602
602
|
*/
|
|
603
603
|
async backfillSourceLocales() {
|
|
604
604
|
const result = await this.db
|
|
@@ -84,7 +84,7 @@ export declare class DocumentQueries implements IDocumentQueries {
|
|
|
84
84
|
* document, or any document read after the global default is switched, falls
|
|
85
85
|
* back to the locale it was actually authored in) — otherwise the configured
|
|
86
86
|
* global default, which is correct for not-yet-anchored rows and for
|
|
87
|
-
* row-less lookups (findByPath). See docs/
|
|
87
|
+
* row-less lookups (findByPath). See docs/I18N.md.
|
|
88
88
|
*/
|
|
89
89
|
private buildLocaleChain;
|
|
90
90
|
/**
|
|
@@ -113,7 +113,7 @@ export declare class DocumentQueries implements IDocumentQueries {
|
|
|
113
113
|
* advertise. Surfaced on reads as `availableLocales` — the deliberate
|
|
114
114
|
* counterpart to the version-grain `_availableVersionLocales` ledger fact;
|
|
115
115
|
* the public advertised set is their intersection. One indexed query per
|
|
116
|
-
* call. See docs/
|
|
116
|
+
* call. See docs/I18N.md.
|
|
117
117
|
*/
|
|
118
118
|
private getAdvertisedLocalesByDocument;
|
|
119
119
|
/**
|
|
@@ -105,7 +105,7 @@ export class DocumentQueries {
|
|
|
105
105
|
* document, or any document read after the global default is switched, falls
|
|
106
106
|
* back to the locale it was actually authored in) — otherwise the configured
|
|
107
107
|
* global default, which is correct for not-yet-anchored rows and for
|
|
108
|
-
* row-less lookups (findByPath). See docs/
|
|
108
|
+
* row-less lookups (findByPath). See docs/I18N.md.
|
|
109
109
|
*/
|
|
110
110
|
buildLocaleChain(requestedLocale, sourceLocale) {
|
|
111
111
|
const floor = sourceLocale ?? this.defaultContentLocale;
|
|
@@ -171,7 +171,7 @@ export class DocumentQueries {
|
|
|
171
171
|
* advertise. Surfaced on reads as `availableLocales` — the deliberate
|
|
172
172
|
* counterpart to the version-grain `_availableVersionLocales` ledger fact;
|
|
173
173
|
* the public advertised set is their intersection. One indexed query per
|
|
174
|
-
* call. See docs/
|
|
174
|
+
* call. See docs/I18N.md.
|
|
175
175
|
*/
|
|
176
176
|
async getAdvertisedLocalesByDocument(documentIds) {
|
|
177
177
|
const result = new Map();
|
|
@@ -278,26 +278,6 @@ describe('content-locale resolution & fallback', () => {
|
|
|
278
278
|
const second = await commandBuilders.documents.backfillVersionLocales();
|
|
279
279
|
expect(second.rowsInserted).toBe(0);
|
|
280
280
|
});
|
|
281
|
-
it('backfillSourceLocales stamps NULL source_locale rows with the default locale', async () => {
|
|
282
|
-
const id = await createDoc({
|
|
283
|
-
title: { en: 'Hello', de: 'Hallo' },
|
|
284
|
-
body: { en: 'World', de: 'Welt' },
|
|
285
|
-
sku: 'S1',
|
|
286
|
-
});
|
|
287
|
-
// The write path now stamps source_locale on create (Slice 2), so simulate
|
|
288
|
-
// a row written before the column existed by nulling it — exactly the
|
|
289
|
-
// pre-existing-data shape backfill exists to repair.
|
|
290
|
-
await db.execute(sql `UPDATE byline_documents SET source_locale = NULL WHERE id = ${id}::uuid`);
|
|
291
|
-
const before = await db.execute(sql `SELECT source_locale FROM byline_documents WHERE id = ${id}::uuid`);
|
|
292
|
-
expect(before.rows[0].source_locale).toBeNull();
|
|
293
|
-
const result = await commandBuilders.documents.backfillSourceLocales();
|
|
294
|
-
expect(result.rowsUpdated).toBeGreaterThan(0);
|
|
295
|
-
const after = await db.execute(sql `SELECT source_locale FROM byline_documents WHERE id = ${id}::uuid`);
|
|
296
|
-
expect(after.rows[0].source_locale, 'stamped with the adapter default content locale (en)').toBe('en');
|
|
297
|
-
// Idempotent: a second run touches nothing (no NULL rows remain).
|
|
298
|
-
const second = await commandBuilders.documents.backfillSourceLocales();
|
|
299
|
-
expect(second.rowsUpdated).toBe(0);
|
|
300
|
-
});
|
|
301
281
|
// --- source_locale write path (Slice 2) ----------------------------------
|
|
302
282
|
it('records source_locale on create and writes the path row under it', async () => {
|
|
303
283
|
const created = await commandBuilders.documents.createDocumentVersion({
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@byline/db-postgres",
|
|
3
3
|
"private": false,
|
|
4
4
|
"license": "MPL-2.0",
|
|
5
|
-
"version": "3.0.
|
|
5
|
+
"version": "3.0.1",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">=20.9.0"
|
|
8
8
|
},
|
|
@@ -57,9 +57,9 @@
|
|
|
57
57
|
"pg": "^8.21.0",
|
|
58
58
|
"uuid": "^14.0.0",
|
|
59
59
|
"zod": "^4.4.3",
|
|
60
|
-
"@byline/
|
|
61
|
-
"@byline/auth": "3.0.
|
|
62
|
-
"@byline/
|
|
60
|
+
"@byline/core": "3.0.1",
|
|
61
|
+
"@byline/auth": "3.0.1",
|
|
62
|
+
"@byline/admin": "3.0.1"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
65
|
"@biomejs/biome": "2.4.15",
|