@byline/core 1.7.7 → 1.8.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.
|
@@ -207,7 +207,15 @@ export interface IDocumentCommands {
|
|
|
207
207
|
collectionConfig: CollectionDefinition;
|
|
208
208
|
action: string;
|
|
209
209
|
documentData: any;
|
|
210
|
-
|
|
210
|
+
/**
|
|
211
|
+
* Optional. When provided, the adapter upserts a row into
|
|
212
|
+
* `byline_document_paths` keyed by `(document_id, defaultContentLocale)`.
|
|
213
|
+
* When omitted, no path write occurs — the lifecycle uses this to
|
|
214
|
+
* skip path writes during translation (non-default-locale) saves.
|
|
215
|
+
* The unique constraint on `(collection_id, locale, path)` may
|
|
216
|
+
* surface as `ERR_PATH_CONFLICT` from the lifecycle layer.
|
|
217
|
+
*/
|
|
218
|
+
path?: string;
|
|
211
219
|
locale?: string;
|
|
212
220
|
status?: string;
|
|
213
221
|
createdBy?: string;
|
package/dist/lib/errors.d.ts
CHANGED
|
@@ -85,6 +85,7 @@ export declare const ErrorCodes: {
|
|
|
85
85
|
readonly DATABASE: "ERR_DATABASE";
|
|
86
86
|
readonly STORAGE: "ERR_STORAGE";
|
|
87
87
|
readonly READ_BUDGET_EXCEEDED: "ERR_READ_BUDGET_EXCEEDED";
|
|
88
|
+
readonly PATH_CONFLICT: "ERR_PATH_CONFLICT";
|
|
88
89
|
};
|
|
89
90
|
export declare const ERR_UNHANDLED: (opts: BylineErrorOptions, errorConstructor?: any) => BylineError;
|
|
90
91
|
export declare const ERR_NOT_FOUND: (opts: BylineErrorOptions, errorConstructor?: any) => BylineError;
|
|
@@ -95,3 +96,10 @@ export declare const ERR_PATCH_FAILED: (opts: BylineErrorOptions, errorConstruct
|
|
|
95
96
|
export declare const ERR_DATABASE: (opts: BylineErrorOptions, errorConstructor?: any) => BylineError;
|
|
96
97
|
export declare const ERR_STORAGE: (opts: BylineErrorOptions, errorConstructor?: any) => BylineError;
|
|
97
98
|
export declare const ERR_READ_BUDGET_EXCEEDED: (opts: BylineErrorOptions, errorConstructor?: any) => BylineError;
|
|
99
|
+
/**
|
|
100
|
+
* Thrown when a write attempts to set `path` to a value already used by
|
|
101
|
+
* another document in the same `(collection, locale)` scope. Surfaces the
|
|
102
|
+
* underlying Postgres unique-constraint violation on
|
|
103
|
+
* `byline_document_paths(collection_id, locale, path)`.
|
|
104
|
+
*/
|
|
105
|
+
export declare const ERR_PATH_CONFLICT: (opts: BylineErrorOptions, errorConstructor?: any) => BylineError;
|
package/dist/lib/errors.js
CHANGED
|
@@ -118,6 +118,7 @@ export const ErrorCodes = {
|
|
|
118
118
|
DATABASE: 'ERR_DATABASE',
|
|
119
119
|
STORAGE: 'ERR_STORAGE',
|
|
120
120
|
READ_BUDGET_EXCEEDED: 'ERR_READ_BUDGET_EXCEEDED',
|
|
121
|
+
PATH_CONFLICT: 'ERR_PATH_CONFLICT',
|
|
121
122
|
};
|
|
122
123
|
// ---------------------------------------------------------------------------
|
|
123
124
|
// Pre-instantiated factories
|
|
@@ -131,3 +132,10 @@ export const ERR_PATCH_FAILED = createErrorType(ErrorCodes.PATCH_FAILED);
|
|
|
131
132
|
export const ERR_DATABASE = createErrorType(ErrorCodes.DATABASE);
|
|
132
133
|
export const ERR_STORAGE = createErrorType(ErrorCodes.STORAGE);
|
|
133
134
|
export const ERR_READ_BUDGET_EXCEEDED = createErrorType(ErrorCodes.READ_BUDGET_EXCEEDED);
|
|
135
|
+
/**
|
|
136
|
+
* Thrown when a write attempts to set `path` to a value already used by
|
|
137
|
+
* another document in the same `(collection, locale)` scope. Surfaces the
|
|
138
|
+
* underlying Postgres unique-constraint violation on
|
|
139
|
+
* `byline_document_paths(collection_id, locale, path)`.
|
|
140
|
+
*/
|
|
141
|
+
export const ERR_PATH_CONFLICT = createErrorType(ErrorCodes.PATH_CONFLICT, 'warn');
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { normalizeCollectionHook, } from '../@types/index.js';
|
|
9
9
|
import { assertActorCanPerform } from '../auth/assert-actor-can-perform.js';
|
|
10
|
-
import { ERR_CONFLICT, ERR_INVALID_TRANSITION, ERR_NOT_FOUND, ERR_PATCH_FAILED, ERR_VALIDATION, } from '../lib/errors.js';
|
|
10
|
+
import { ERR_CONFLICT, ERR_INVALID_TRANSITION, ERR_NOT_FOUND, ERR_PATCH_FAILED, ERR_PATH_CONFLICT, ERR_VALIDATION, } from '../lib/errors.js';
|
|
11
11
|
import { withLogContext } from '../lib/logger.js';
|
|
12
12
|
import { applyPatches } from '../patches/index.js';
|
|
13
13
|
import { normaliseDateFields } from '../utils/normalise-dates.js';
|
|
@@ -32,6 +32,65 @@ async function invokeHook(hook, ctx) {
|
|
|
32
32
|
function extractVersionId(document) {
|
|
33
33
|
return document?.id ?? document?.document_version_id ?? '';
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Detect a Postgres unique-constraint violation on
|
|
37
|
+
* `byline_document_paths(collection_id, locale, path)` and translate it
|
|
38
|
+
* to `ERR_PATH_CONFLICT`. Any other error is rethrown unchanged.
|
|
39
|
+
*
|
|
40
|
+
* The Postgres SQLSTATE for unique violations is `23505`. Drivers carry
|
|
41
|
+
* the constraint name on the error object (`constraint`); matching by
|
|
42
|
+
* name keeps this targeted to the path constraint and avoids spuriously
|
|
43
|
+
* rebranding unrelated unique violations as path conflicts.
|
|
44
|
+
*
|
|
45
|
+
* Drizzle wraps the underlying pg error in `DrizzleQueryError` with the
|
|
46
|
+
* original attached as `cause`, so we walk a short cause chain to find
|
|
47
|
+
* the carried `code` / `constraint`.
|
|
48
|
+
*/
|
|
49
|
+
function rethrowPathConflict(err, path, locale) {
|
|
50
|
+
let e = err;
|
|
51
|
+
// Walk at most a few `cause` hops — DrizzleQueryError → underlying pg error.
|
|
52
|
+
for (let i = 0; i < 3 && e; i++) {
|
|
53
|
+
if (e.code === '23505' &&
|
|
54
|
+
typeof e.constraint === 'string' &&
|
|
55
|
+
e.constraint.includes('document_paths_collection_locale_path')) {
|
|
56
|
+
throw ERR_PATH_CONFLICT({
|
|
57
|
+
message: `path "${path}" is already in use in this collection (locale: ${locale})`,
|
|
58
|
+
details: { path, locale, constraint: e.constraint },
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
e = e.cause;
|
|
62
|
+
}
|
|
63
|
+
throw err;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Resolve the path argument the storage primitive should receive on an
|
|
67
|
+
* update operation. Phase 1 only writes path rows under the default
|
|
68
|
+
* content locale; on translation saves a supplied path is dropped with
|
|
69
|
+
* a `logger.warn`, leaving the existing default-locale row untouched.
|
|
70
|
+
*
|
|
71
|
+
* Returns `undefined` to signal the storage primitive should skip the
|
|
72
|
+
* path write entirely (no upsert).
|
|
73
|
+
*/
|
|
74
|
+
function resolvePathForUpdate(args) {
|
|
75
|
+
const { explicitPath, currentPath, requestLocale, defaultLocale, documentId, logger } = args;
|
|
76
|
+
if (requestLocale === defaultLocale) {
|
|
77
|
+
// Default-locale write: pass path through when supplied; otherwise
|
|
78
|
+
// skip the write (existing path row stays as-is — sticky).
|
|
79
|
+
return explicitPath ?? undefined;
|
|
80
|
+
}
|
|
81
|
+
// Non-default-locale write: reject any path change with a warn so the
|
|
82
|
+
// operation succeeds but the editor / API caller is informed.
|
|
83
|
+
if (explicitPath !== null && explicitPath !== currentPath) {
|
|
84
|
+
logger?.warn({
|
|
85
|
+
documentId,
|
|
86
|
+
requestedLocale: requestLocale,
|
|
87
|
+
defaultLocale,
|
|
88
|
+
suppliedPath: explicitPath,
|
|
89
|
+
currentPath,
|
|
90
|
+
}, 'path changes apply only on default-locale writes; ignored on translation save');
|
|
91
|
+
}
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
35
94
|
/** Extract the logical document id from the document object returned by `createDocumentVersion`. */
|
|
36
95
|
function extractDocumentId(document) {
|
|
37
96
|
return document?.document_id ?? '';
|
|
@@ -97,7 +156,8 @@ export async function createDocument(ctx, params) {
|
|
|
97
156
|
await invokeHook(hooks?.beforeCreate, { data, collectionPath });
|
|
98
157
|
const explicitPath = typeof params.path === 'string' && params.path.length > 0 ? params.path : null;
|
|
99
158
|
const resolvedPath = explicitPath ?? derivePath(definition, data, defaultLocale, slugifier);
|
|
100
|
-
const result = await db.commands.documents
|
|
159
|
+
const result = await db.commands.documents
|
|
160
|
+
.createDocumentVersion({
|
|
101
161
|
collectionId,
|
|
102
162
|
collectionVersion: ctx.collectionVersion,
|
|
103
163
|
collectionConfig: definition,
|
|
@@ -106,7 +166,8 @@ export async function createDocument(ctx, params) {
|
|
|
106
166
|
path: resolvedPath,
|
|
107
167
|
status: params.status ?? data.status,
|
|
108
168
|
locale: params.locale ?? defaultLocale,
|
|
109
|
-
})
|
|
169
|
+
})
|
|
170
|
+
.catch((err) => rethrowPathConflict(err, resolvedPath, defaultLocale));
|
|
110
171
|
const documentId = extractDocumentId(result.document);
|
|
111
172
|
const documentVersionId = extractVersionId(result.document);
|
|
112
173
|
await invokeHook(hooks?.afterCreate, {
|
|
@@ -150,19 +211,29 @@ export async function updateDocument(ctx, params) {
|
|
|
150
211
|
await invokeHook(hooks?.beforeUpdate, { data, originalData, collectionPath });
|
|
151
212
|
const defaultStatus = getDefaultStatus(definition);
|
|
152
213
|
const explicitPath = typeof params.path === 'string' && params.path.length > 0 ? params.path : null;
|
|
153
|
-
const
|
|
154
|
-
const
|
|
214
|
+
const requestLocale = params.locale ?? defaultLocale;
|
|
215
|
+
const pathForCommand = resolvePathForUpdate({
|
|
216
|
+
explicitPath,
|
|
217
|
+
currentPath: originalData.path,
|
|
218
|
+
requestLocale,
|
|
219
|
+
defaultLocale,
|
|
220
|
+
documentId: params.documentId,
|
|
221
|
+
logger: ctx.logger,
|
|
222
|
+
});
|
|
223
|
+
const result = await db.commands.documents
|
|
224
|
+
.createDocumentVersion({
|
|
155
225
|
documentId: params.documentId,
|
|
156
226
|
collectionId,
|
|
157
227
|
collectionVersion: ctx.collectionVersion,
|
|
158
228
|
collectionConfig: definition,
|
|
159
229
|
action: 'update',
|
|
160
230
|
documentData: data,
|
|
161
|
-
path:
|
|
231
|
+
path: pathForCommand,
|
|
162
232
|
status: defaultStatus,
|
|
163
|
-
locale:
|
|
233
|
+
locale: requestLocale,
|
|
164
234
|
previousVersionId: originalData.document_version_id,
|
|
165
|
-
})
|
|
235
|
+
})
|
|
236
|
+
.catch((err) => rethrowPathConflict(err, pathForCommand ?? '', defaultLocale));
|
|
166
237
|
const documentId = extractDocumentId(result.document) || params.documentId;
|
|
167
238
|
const documentVersionId = extractVersionId(result.document);
|
|
168
239
|
await invokeHook(hooks?.afterUpdate, {
|
|
@@ -236,19 +307,29 @@ export async function updateDocumentWithPatches(ctx, params) {
|
|
|
236
307
|
// 6. Persist.
|
|
237
308
|
const defaultStatus = getDefaultStatus(definition);
|
|
238
309
|
const explicitPath = typeof params.path === 'string' && params.path.length > 0 ? params.path : null;
|
|
239
|
-
const
|
|
240
|
-
const
|
|
310
|
+
const requestLocale = params.locale ?? defaultLocale;
|
|
311
|
+
const pathForCommand = resolvePathForUpdate({
|
|
312
|
+
explicitPath,
|
|
313
|
+
currentPath: originalData.path,
|
|
314
|
+
requestLocale,
|
|
315
|
+
defaultLocale,
|
|
316
|
+
documentId: params.documentId,
|
|
317
|
+
logger: ctx.logger,
|
|
318
|
+
});
|
|
319
|
+
const result = await db.commands.documents
|
|
320
|
+
.createDocumentVersion({
|
|
241
321
|
documentId: params.documentId,
|
|
242
322
|
collectionId,
|
|
243
323
|
collectionVersion: ctx.collectionVersion,
|
|
244
324
|
collectionConfig: definition,
|
|
245
325
|
action: 'update',
|
|
246
326
|
documentData: nextData,
|
|
247
|
-
path:
|
|
327
|
+
path: pathForCommand,
|
|
248
328
|
status: defaultStatus,
|
|
249
|
-
locale:
|
|
329
|
+
locale: requestLocale,
|
|
250
330
|
previousVersionId: originalData.document_version_id,
|
|
251
|
-
})
|
|
331
|
+
})
|
|
332
|
+
.catch((err) => rethrowPathConflict(err, pathForCommand ?? '', defaultLocale));
|
|
252
333
|
const documentId = extractDocumentId(result.document) || params.documentId;
|
|
253
334
|
const documentVersionId = extractVersionId(result.document);
|
|
254
335
|
// 7. afterUpdate hook.
|
|
@@ -493,6 +574,9 @@ export async function restoreDocumentVersion(ctx, params) {
|
|
|
493
574
|
// the source tree forward in a single flatten pass — the
|
|
494
575
|
// cross-locale carry-forward branch in createDocumentVersion does
|
|
495
576
|
// not fire when locale === 'all'.
|
|
577
|
+
//
|
|
578
|
+
// No `path` is passed: restore does not change the document's path
|
|
579
|
+
// (the existing byline_document_paths row stays as-is — sticky).
|
|
496
580
|
const result = await db.commands.documents.createDocumentVersion({
|
|
497
581
|
documentId: params.documentId,
|
|
498
582
|
collectionId,
|
|
@@ -500,7 +584,6 @@ export async function restoreDocumentVersion(ctx, params) {
|
|
|
500
584
|
collectionConfig: definition,
|
|
501
585
|
action: 'restore',
|
|
502
586
|
documentData: sourceFields,
|
|
503
|
-
path: currentMeta.path,
|
|
504
587
|
status: getDefaultStatus(definition),
|
|
505
588
|
locale: 'all',
|
|
506
589
|
previousVersionId: currentMeta.document_version_id,
|
|
@@ -319,7 +319,7 @@ describe('Document lifecycle service', () => {
|
|
|
319
319
|
documentVersionId: 'ver-1',
|
|
320
320
|
}));
|
|
321
321
|
});
|
|
322
|
-
it('
|
|
322
|
+
it('does not pass path to the storage primitive when no explicit path is supplied', async () => {
|
|
323
323
|
const { db, getDocumentById, createDocumentVersion } = createMockDb();
|
|
324
324
|
getDocumentById.mockResolvedValue({
|
|
325
325
|
document_version_id: 'prev-ver',
|
|
@@ -333,8 +333,9 @@ describe('Document lifecycle service', () => {
|
|
|
333
333
|
documentId: 'doc-1',
|
|
334
334
|
data: { title: 'Brand New Title' },
|
|
335
335
|
});
|
|
336
|
-
//
|
|
337
|
-
|
|
336
|
+
// Sticky path semantics: the storage layer is not asked to write the
|
|
337
|
+
// path row; the existing byline_document_paths row stays as-is.
|
|
338
|
+
expect(createDocumentVersion.mock.calls[0]?.[0].path).toBeUndefined();
|
|
338
339
|
});
|
|
339
340
|
it('uses an explicit params.path verbatim on update, overriding the sticky value', async () => {
|
|
340
341
|
const { db, getDocumentById, createDocumentVersion } = createMockDb();
|
|
@@ -365,6 +366,98 @@ describe('Document lifecycle service', () => {
|
|
|
365
366
|
});
|
|
366
367
|
expect(createDocumentVersion.mock.calls[0]?.[0].status).toBe('draft');
|
|
367
368
|
});
|
|
369
|
+
it('drops path changes silently with a logger.warn on non-default-locale (translation) saves', async () => {
|
|
370
|
+
const { db, getDocumentById, createDocumentVersion } = createMockDb();
|
|
371
|
+
getDocumentById.mockResolvedValue({
|
|
372
|
+
document_version_id: 'prev-ver',
|
|
373
|
+
path: 'about',
|
|
374
|
+
status: 'draft',
|
|
375
|
+
fields: { title: 'About' },
|
|
376
|
+
});
|
|
377
|
+
const ctx = buildCtx(db);
|
|
378
|
+
const warn = ctx.logger?.warn;
|
|
379
|
+
warn.mockClear();
|
|
380
|
+
await updateDocument(ctx, {
|
|
381
|
+
documentId: 'doc-1',
|
|
382
|
+
data: { title: 'À propos' },
|
|
383
|
+
locale: 'fr',
|
|
384
|
+
path: 'a-propos',
|
|
385
|
+
});
|
|
386
|
+
// Save still proceeds — the version row is created — but the path
|
|
387
|
+
// row is left untouched (no `path` flows to the storage primitive).
|
|
388
|
+
expect(createDocumentVersion).toHaveBeenCalledOnce();
|
|
389
|
+
expect(createDocumentVersion.mock.calls[0]?.[0].path).toBeUndefined();
|
|
390
|
+
expect(createDocumentVersion.mock.calls[0]?.[0].locale).toBe('fr');
|
|
391
|
+
// The caller is informed via a structured warn.
|
|
392
|
+
expect(warn).toHaveBeenCalledWith(expect.objectContaining({
|
|
393
|
+
documentId: 'doc-1',
|
|
394
|
+
requestedLocale: 'fr',
|
|
395
|
+
defaultLocale: 'en',
|
|
396
|
+
suppliedPath: 'a-propos',
|
|
397
|
+
currentPath: 'about',
|
|
398
|
+
}), expect.stringContaining('path changes apply only on default-locale writes'));
|
|
399
|
+
});
|
|
400
|
+
it('does not warn when a translation save supplies the same path as current', async () => {
|
|
401
|
+
const { db, getDocumentById } = createMockDb();
|
|
402
|
+
getDocumentById.mockResolvedValue({
|
|
403
|
+
document_version_id: 'prev-ver',
|
|
404
|
+
path: 'about',
|
|
405
|
+
status: 'draft',
|
|
406
|
+
fields: { title: 'About' },
|
|
407
|
+
});
|
|
408
|
+
const ctx = buildCtx(db);
|
|
409
|
+
const warn = ctx.logger?.warn;
|
|
410
|
+
warn.mockClear();
|
|
411
|
+
await updateDocument(ctx, {
|
|
412
|
+
documentId: 'doc-1',
|
|
413
|
+
data: { title: 'À propos' },
|
|
414
|
+
locale: 'fr',
|
|
415
|
+
path: 'about', // same as currentPath — idempotent, no warn
|
|
416
|
+
});
|
|
417
|
+
expect(warn).not.toHaveBeenCalled();
|
|
418
|
+
});
|
|
419
|
+
it('translates a Postgres unique-constraint violation on the path index to ERR_PATH_CONFLICT', async () => {
|
|
420
|
+
const { db, getDocumentById, createDocumentVersion } = createMockDb();
|
|
421
|
+
getDocumentById.mockResolvedValue({
|
|
422
|
+
document_version_id: 'prev-ver',
|
|
423
|
+
path: 'about',
|
|
424
|
+
status: 'draft',
|
|
425
|
+
fields: { title: 'About' },
|
|
426
|
+
});
|
|
427
|
+
// Simulate the pg driver throwing a unique-violation on the path
|
|
428
|
+
// constraint when the upsert tries to claim a slug owned by another
|
|
429
|
+
// document in the same (collection, locale).
|
|
430
|
+
createDocumentVersion.mockRejectedValueOnce(Object.assign(new Error('duplicate key value violates unique constraint'), {
|
|
431
|
+
code: '23505',
|
|
432
|
+
constraint: 'idx_document_paths_collection_locale_path',
|
|
433
|
+
}));
|
|
434
|
+
const ctx = buildCtx(db);
|
|
435
|
+
try {
|
|
436
|
+
await updateDocument(ctx, {
|
|
437
|
+
documentId: 'doc-1',
|
|
438
|
+
data: { title: 'About' },
|
|
439
|
+
path: 'home', // collides
|
|
440
|
+
});
|
|
441
|
+
throw new Error('expected ERR_PATH_CONFLICT');
|
|
442
|
+
}
|
|
443
|
+
catch (err) {
|
|
444
|
+
expect(err).toBeInstanceOf(BylineError);
|
|
445
|
+
expect(err.code).toBe(ErrorCodes.PATH_CONFLICT);
|
|
446
|
+
}
|
|
447
|
+
});
|
|
448
|
+
it('rethrows non-23505 errors unchanged', async () => {
|
|
449
|
+
const { db, getDocumentById, createDocumentVersion } = createMockDb();
|
|
450
|
+
getDocumentById.mockResolvedValue({
|
|
451
|
+
document_version_id: 'prev-ver',
|
|
452
|
+
path: 'about',
|
|
453
|
+
status: 'draft',
|
|
454
|
+
fields: { title: 'About' },
|
|
455
|
+
});
|
|
456
|
+
const original = new Error('connection refused');
|
|
457
|
+
createDocumentVersion.mockRejectedValueOnce(original);
|
|
458
|
+
const ctx = buildCtx(db);
|
|
459
|
+
await expect(updateDocument(ctx, { documentId: 'doc-1', data: { title: 'X' }, path: 'home' })).rejects.toBe(original);
|
|
460
|
+
});
|
|
368
461
|
it('supports an array of beforeUpdate and afterUpdate hooks', async () => {
|
|
369
462
|
const callOrder = [];
|
|
370
463
|
const hooks = {
|
|
@@ -719,13 +812,16 @@ describe('Document lifecycle service', () => {
|
|
|
719
812
|
// Source version was 'archived'; default status for minimalCollection is 'draft'.
|
|
720
813
|
expect(createDocumentVersion.mock.calls[0]?.[0].status).toBe('draft');
|
|
721
814
|
});
|
|
722
|
-
it('
|
|
815
|
+
it('does not pass path on restore — the existing path row is sticky', async () => {
|
|
723
816
|
const { db, createDocumentVersion, sourceVersionId } = setupRestore({
|
|
724
817
|
currentPath: 'sticky-path',
|
|
725
818
|
});
|
|
726
819
|
const ctx = buildCtx(db);
|
|
727
820
|
await restoreDocumentVersion(ctx, { documentId: 'doc-1', sourceVersionId });
|
|
728
|
-
|
|
821
|
+
// Restore never changes a document's path: the existing
|
|
822
|
+
// byline_document_paths row carries forward unchanged. The storage
|
|
823
|
+
// primitive only writes to document_paths when `path` is supplied.
|
|
824
|
+
expect(createDocumentVersion.mock.calls[0]?.[0].path).toBeUndefined();
|
|
729
825
|
});
|
|
730
826
|
it('rejects when the source version belongs to a different document', async () => {
|
|
731
827
|
const { db, sourceVersionId, createDocumentVersion } = setupRestore({
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@byline/core",
|
|
3
3
|
"private": false,
|
|
4
4
|
"license": "MPL-2.0",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.8.0",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">=20.9.0"
|
|
8
8
|
},
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"sharp": "^0.34.5",
|
|
80
80
|
"uuid": "^14.0.0",
|
|
81
81
|
"zod": "^4.4.2",
|
|
82
|
-
"@byline/auth": "1.
|
|
82
|
+
"@byline/auth": "1.8.0"
|
|
83
83
|
},
|
|
84
84
|
"devDependencies": {
|
|
85
85
|
"@biomejs/biome": "2.4.14",
|