@byline/db-postgres 3.0.2 → 3.1.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.
|
@@ -216,6 +216,20 @@ export declare class DocumentQueries implements IDocumentQueries {
|
|
|
216
216
|
created_at: Date;
|
|
217
217
|
updated_at: Date;
|
|
218
218
|
} | null>;
|
|
219
|
+
/**
|
|
220
|
+
* getCurrentPath — resolve a document's canonical (source-locale) path.
|
|
221
|
+
*
|
|
222
|
+
* Reuses `pathProjection` against `current_documents`, passing
|
|
223
|
+
* `requestedLocale: undefined` so the projection's fallback floor — the
|
|
224
|
+
* document's own `source_locale` (COALESCE-guarded to the default content
|
|
225
|
+
* locale for not-yet-anchored rows) — supplies the canonical path. Used by
|
|
226
|
+
* the lifecycle to populate `path` on the status-change / unpublish hook
|
|
227
|
+
* contexts. Returns `null` when no path row (or document) exists.
|
|
228
|
+
*/
|
|
229
|
+
getCurrentPath({ collection_id, document_id, }: {
|
|
230
|
+
collection_id: string;
|
|
231
|
+
document_id: string;
|
|
232
|
+
}): Promise<string | null>;
|
|
219
233
|
/**
|
|
220
234
|
* getDocumentById — gets the current version of a document by its logical document ID.
|
|
221
235
|
*
|
|
@@ -439,6 +439,26 @@ export class DocumentQueries {
|
|
|
439
439
|
updated_at: row.updated_at ?? new Date(),
|
|
440
440
|
};
|
|
441
441
|
}
|
|
442
|
+
/**
|
|
443
|
+
* getCurrentPath — resolve a document's canonical (source-locale) path.
|
|
444
|
+
*
|
|
445
|
+
* Reuses `pathProjection` against `current_documents`, passing
|
|
446
|
+
* `requestedLocale: undefined` so the projection's fallback floor — the
|
|
447
|
+
* document's own `source_locale` (COALESCE-guarded to the default content
|
|
448
|
+
* locale for not-yet-anchored rows) — supplies the canonical path. Used by
|
|
449
|
+
* the lifecycle to populate `path` on the status-change / unpublish hook
|
|
450
|
+
* contexts. Returns `null` when no path row (or document) exists.
|
|
451
|
+
*/
|
|
452
|
+
async getCurrentPath({ collection_id, document_id, }) {
|
|
453
|
+
const [row] = await this.db
|
|
454
|
+
.select({
|
|
455
|
+
path: this.pathProjection(sql `${currentDocumentsView.document_id}`, undefined, sql `${currentDocumentsView.source_locale}`),
|
|
456
|
+
})
|
|
457
|
+
.from(currentDocumentsView)
|
|
458
|
+
.where(and(eq(currentDocumentsView.collection_id, collection_id), eq(currentDocumentsView.document_id, document_id)))
|
|
459
|
+
.limit(1);
|
|
460
|
+
return row?.path ?? null;
|
|
461
|
+
}
|
|
442
462
|
/**
|
|
443
463
|
* getDocumentById — gets the current version of a document by its logical document ID.
|
|
444
464
|
*
|
|
@@ -181,4 +181,81 @@ describe('byline_document_paths integration', () => {
|
|
|
181
181
|
});
|
|
182
182
|
expect(result).toBe(null);
|
|
183
183
|
});
|
|
184
|
+
describe('getCurrentPath', () => {
|
|
185
|
+
it('resolves a document’s canonical path under its default source locale', async () => {
|
|
186
|
+
const canonicalPath = `current-path-${Date.now()}`;
|
|
187
|
+
const created = await commandBuilders.documents.createDocumentVersion({
|
|
188
|
+
collectionId: testCollection.id,
|
|
189
|
+
collectionVersion: 1,
|
|
190
|
+
collectionConfig: PathsCollectionConfig,
|
|
191
|
+
action: 'create',
|
|
192
|
+
documentData: { title: 'Has Path' },
|
|
193
|
+
path: canonicalPath,
|
|
194
|
+
locale: 'all',
|
|
195
|
+
status: 'draft',
|
|
196
|
+
});
|
|
197
|
+
const documentId = created.document.document_id;
|
|
198
|
+
const path = await queryBuilders.documents.getCurrentPath({
|
|
199
|
+
collection_id: testCollection.id,
|
|
200
|
+
document_id: documentId,
|
|
201
|
+
});
|
|
202
|
+
expect(path).toBe(canonicalPath);
|
|
203
|
+
});
|
|
204
|
+
it('follows the source-locale anchor after a document is re-anchored', async () => {
|
|
205
|
+
const canonicalPath = `reanchor-path-${Date.now()}`;
|
|
206
|
+
// Create locale-agnostic content (ledger carries the 'all' sentinel) so
|
|
207
|
+
// the document is "complete" in any target and re-anchoring is eligible.
|
|
208
|
+
const created = await commandBuilders.documents.createDocumentVersion({
|
|
209
|
+
collectionId: testCollection.id,
|
|
210
|
+
collectionVersion: 1,
|
|
211
|
+
collectionConfig: PathsCollectionConfig,
|
|
212
|
+
action: 'create',
|
|
213
|
+
documentData: { title: 'Re-anchor me' },
|
|
214
|
+
path: canonicalPath,
|
|
215
|
+
locale: 'all',
|
|
216
|
+
status: 'draft',
|
|
217
|
+
});
|
|
218
|
+
const documentId = created.document.document_id;
|
|
219
|
+
// Flip the document's source locale from the default ('en') to 'fr'.
|
|
220
|
+
// reAnchorDocument moves the path row onto the new source locale,
|
|
221
|
+
// keeping the slug. getCurrentPath passes requestedLocale: undefined, so
|
|
222
|
+
// its fallback floor is COALESCE(source_locale, default) — it must now
|
|
223
|
+
// resolve via the 'fr' anchor, not the global default 'en'.
|
|
224
|
+
const result = await commandBuilders.documents.reAnchorDocument({
|
|
225
|
+
documentId,
|
|
226
|
+
targetLocale: 'fr',
|
|
227
|
+
});
|
|
228
|
+
expect(result.status).toBe('reanchored');
|
|
229
|
+
const path = await queryBuilders.documents.getCurrentPath({
|
|
230
|
+
collection_id: testCollection.id,
|
|
231
|
+
document_id: documentId,
|
|
232
|
+
});
|
|
233
|
+
expect(path).toBe(canonicalPath);
|
|
234
|
+
});
|
|
235
|
+
it('returns null when the document has no path row', async () => {
|
|
236
|
+
// Create a version without a `path` — no document_paths row is written.
|
|
237
|
+
const created = await commandBuilders.documents.createDocumentVersion({
|
|
238
|
+
collectionId: testCollection.id,
|
|
239
|
+
collectionVersion: 1,
|
|
240
|
+
collectionConfig: PathsCollectionConfig,
|
|
241
|
+
action: 'create',
|
|
242
|
+
documentData: { title: 'No Path' },
|
|
243
|
+
locale: 'all',
|
|
244
|
+
status: 'draft',
|
|
245
|
+
});
|
|
246
|
+
const documentId = created.document.document_id;
|
|
247
|
+
const path = await queryBuilders.documents.getCurrentPath({
|
|
248
|
+
collection_id: testCollection.id,
|
|
249
|
+
document_id: documentId,
|
|
250
|
+
});
|
|
251
|
+
expect(path).toBe(null);
|
|
252
|
+
});
|
|
253
|
+
it('returns null for a non-existent document', async () => {
|
|
254
|
+
const path = await queryBuilders.documents.getCurrentPath({
|
|
255
|
+
collection_id: testCollection.id,
|
|
256
|
+
document_id: crypto.randomUUID(),
|
|
257
|
+
});
|
|
258
|
+
expect(path).toBe(null);
|
|
259
|
+
});
|
|
260
|
+
});
|
|
184
261
|
});
|
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.1.0",
|
|
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.1.0",
|
|
61
|
+
"@byline/auth": "3.1.0",
|
|
62
|
+
"@byline/admin": "3.1.0"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
65
|
"@biomejs/biome": "2.4.15",
|