@byline/db-postgres 1.10.3 → 1.11.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.d.ts +53 -0
- package/dist/database/schema/index.js +45 -2
- package/dist/modules/storage/storage-commands.d.ts +11 -1
- package/dist/modules/storage/storage-commands.js +15 -0
- package/dist/modules/storage/storage-queries.d.ts +44 -2
- package/dist/modules/storage/storage-queries.js +73 -2
- package/package.json +4 -4
|
@@ -207,6 +207,25 @@ export declare const documents: import("drizzle-orm/pg-core").PgTableWithColumns
|
|
|
207
207
|
identity: undefined;
|
|
208
208
|
generated: undefined;
|
|
209
209
|
}, {}, {}>;
|
|
210
|
+
order_key: import("drizzle-orm/pg-core").PgColumn<{
|
|
211
|
+
name: "order_key";
|
|
212
|
+
tableName: "byline_documents";
|
|
213
|
+
dataType: "custom";
|
|
214
|
+
columnType: "PgCustomColumn";
|
|
215
|
+
data: string;
|
|
216
|
+
driverParam: string;
|
|
217
|
+
notNull: false;
|
|
218
|
+
hasDefault: false;
|
|
219
|
+
isPrimaryKey: false;
|
|
220
|
+
isAutoincrement: false;
|
|
221
|
+
hasRuntimeDefault: false;
|
|
222
|
+
enumValues: undefined;
|
|
223
|
+
baseColumn: never;
|
|
224
|
+
identity: undefined;
|
|
225
|
+
generated: undefined;
|
|
226
|
+
}, {}, {
|
|
227
|
+
pgColumnBuilderBrand: "PgCustomColumnBuilderBrand";
|
|
228
|
+
}>;
|
|
210
229
|
created_at: import("drizzle-orm/pg-core").PgColumn<{
|
|
211
230
|
name: "created_at";
|
|
212
231
|
tableName: "byline_documents";
|
|
@@ -818,6 +837,23 @@ export declare const currentDocumentsView: import("drizzle-orm/pg-core").PgViewW
|
|
|
818
837
|
identity: undefined;
|
|
819
838
|
generated: undefined;
|
|
820
839
|
}, {}, {}>;
|
|
840
|
+
order_key: import("drizzle-orm/pg-core").PgColumn<{
|
|
841
|
+
name: "order_key";
|
|
842
|
+
tableName: "byline_current_documents";
|
|
843
|
+
dataType: "custom";
|
|
844
|
+
columnType: "PgCustomColumn";
|
|
845
|
+
data: string;
|
|
846
|
+
driverParam: string;
|
|
847
|
+
notNull: false;
|
|
848
|
+
hasDefault: false;
|
|
849
|
+
isPrimaryKey: false;
|
|
850
|
+
isAutoincrement: false;
|
|
851
|
+
hasRuntimeDefault: false;
|
|
852
|
+
enumValues: undefined;
|
|
853
|
+
baseColumn: never;
|
|
854
|
+
identity: undefined;
|
|
855
|
+
generated: undefined;
|
|
856
|
+
}, {}, {}>;
|
|
821
857
|
}>;
|
|
822
858
|
export declare const currentPublishedDocumentsView: import("drizzle-orm/pg-core").PgViewWithSelection<"byline_current_published_documents", false, {
|
|
823
859
|
id: import("drizzle-orm/pg-core").PgColumn<{
|
|
@@ -1007,6 +1043,23 @@ export declare const currentPublishedDocumentsView: import("drizzle-orm/pg-core"
|
|
|
1007
1043
|
identity: undefined;
|
|
1008
1044
|
generated: undefined;
|
|
1009
1045
|
}, {}, {}>;
|
|
1046
|
+
order_key: import("drizzle-orm/pg-core").PgColumn<{
|
|
1047
|
+
name: "order_key";
|
|
1048
|
+
tableName: "byline_current_published_documents";
|
|
1049
|
+
dataType: "custom";
|
|
1050
|
+
columnType: "PgCustomColumn";
|
|
1051
|
+
data: string;
|
|
1052
|
+
driverParam: string;
|
|
1053
|
+
notNull: false;
|
|
1054
|
+
hasDefault: false;
|
|
1055
|
+
isPrimaryKey: false;
|
|
1056
|
+
isAutoincrement: false;
|
|
1057
|
+
hasRuntimeDefault: false;
|
|
1058
|
+
enumValues: undefined;
|
|
1059
|
+
baseColumn: never;
|
|
1060
|
+
identity: undefined;
|
|
1061
|
+
generated: undefined;
|
|
1062
|
+
}, {}, {}>;
|
|
1010
1063
|
}>;
|
|
1011
1064
|
export declare const textStore: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
1012
1065
|
name: "byline_store_text";
|
|
@@ -6,7 +6,28 @@
|
|
|
6
6
|
* Copyright (c) Infonomic Company Limited
|
|
7
7
|
*/
|
|
8
8
|
import { eq, relations, sql } from 'drizzle-orm';
|
|
9
|
-
import { bigint, boolean, date, decimal, index, integer, jsonb, pgTable, pgView, real, text, time, timestamp, unique, uuid, varchar, } from 'drizzle-orm/pg-core';
|
|
9
|
+
import { bigint, boolean, customType, date, decimal, index, integer, jsonb, pgTable, pgView, real, text, time, timestamp, unique, uuid, varchar, } from 'drizzle-orm/pg-core';
|
|
10
|
+
/**
|
|
11
|
+
* `varchar(...)` with explicit byte-wise (C) collation.
|
|
12
|
+
*
|
|
13
|
+
* Used for `byline_documents.order_key` so the column sorts the same way
|
|
14
|
+
* JavaScript string comparison does. The fractional-index algorithm in
|
|
15
|
+
* `@byline/core` (`generateKeyBetween`, `generateNKeysBetween`) is designed
|
|
16
|
+
* against byte-wise ordering; the database default collation (e.g.
|
|
17
|
+
* `en_US.utf8` on most modern installs) is locale-aware and disagrees with
|
|
18
|
+
* JS on cases like `'Zz' vs 'a0'` — which causes a refetch after a drag-
|
|
19
|
+
* reorder to "snap" the moved row back to its original position.
|
|
20
|
+
*
|
|
21
|
+
* Captured here (rather than only in a hand-written migration) so future
|
|
22
|
+
* regenerations from this schema reproduce the COLLATE clause cleanly.
|
|
23
|
+
* See migration `0003_order_key_byte_collation.sql` and `docs/ORDERABLE.md`.
|
|
24
|
+
*/
|
|
25
|
+
const varcharByteSorted = customType({
|
|
26
|
+
dataType(config) {
|
|
27
|
+
const len = config?.length ?? 255;
|
|
28
|
+
return `varchar(${len}) COLLATE "C"`;
|
|
29
|
+
},
|
|
30
|
+
});
|
|
10
31
|
// Collections table
|
|
11
32
|
export const collections = pgTable('byline_collections', {
|
|
12
33
|
id: uuid('id').primaryKey(),
|
|
@@ -32,9 +53,22 @@ export const documents = pgTable('byline_documents', {
|
|
|
32
53
|
collection_id: uuid('collection_id')
|
|
33
54
|
.notNull()
|
|
34
55
|
.references(() => collections.id, { onDelete: 'cascade' }),
|
|
56
|
+
// Fractional-index sort key for collections with `orderable: true` in
|
|
57
|
+
// their admin config. Null on collections that haven't opted in, and on
|
|
58
|
+
// pre-existing rows in newly-`orderable` collections (sort NULLS LAST).
|
|
59
|
+
// Admin metadata — never per-version, never EAV; updated by the reorder
|
|
60
|
+
// server fn without bumping documentVersions.
|
|
61
|
+
//
|
|
62
|
+
// Uses `varcharByteSorted` (COLLATE "C") so DB ordering matches JS string
|
|
63
|
+
// comparison — the fractional-index algorithm requires this. See
|
|
64
|
+
// `varcharByteSorted` above and docs/ORDERABLE.md.
|
|
65
|
+
order_key: varcharByteSorted('order_key', { length: 128 }),
|
|
35
66
|
created_at: timestamp('created_at').defaultNow(),
|
|
36
67
|
updated_at: timestamp('updated_at').defaultNow(),
|
|
37
|
-
}, (table) => [
|
|
68
|
+
}, (table) => [
|
|
69
|
+
index('idx_documents_collection').on(table.collection_id),
|
|
70
|
+
index('idx_documents_collection_order').on(table.collection_id, table.order_key),
|
|
71
|
+
]);
|
|
38
72
|
// Document versions table
|
|
39
73
|
export const documentVersions = pgTable('byline_document_versions', {
|
|
40
74
|
id: uuid('id').primaryKey(), // UUIDv7 versioning by default
|
|
@@ -143,6 +177,11 @@ export const currentDocumentsView = pgView('byline_current_documents').as((qb) =
|
|
|
143
177
|
})
|
|
144
178
|
.from(documentVersions)
|
|
145
179
|
.where(eq(documentVersions.is_deleted, false)));
|
|
180
|
+
// `order_key` is sourced from `byline_documents` (the logical-document
|
|
181
|
+
// row, not the version row). Joining it through the view keeps
|
|
182
|
+
// `d.order_key` addressable in findDocuments' ORDER BY without an
|
|
183
|
+
// ad-hoc join per query. Always nullable; null sorts last for
|
|
184
|
+
// collections that haven't opted in to `orderable: true`.
|
|
146
185
|
return qb
|
|
147
186
|
.with(sq)
|
|
148
187
|
.select({
|
|
@@ -157,8 +196,10 @@ export const currentDocumentsView = pgView('byline_current_documents').as((qb) =
|
|
|
157
196
|
updated_at: sq.updated_at,
|
|
158
197
|
created_by: sq.created_by,
|
|
159
198
|
change_summary: sq.change_summary,
|
|
199
|
+
order_key: documents.order_key,
|
|
160
200
|
})
|
|
161
201
|
.from(sq)
|
|
202
|
+
.innerJoin(documents, eq(documents.id, sq.document_id))
|
|
162
203
|
.where(eq(sq.rn, 1));
|
|
163
204
|
});
|
|
164
205
|
// Current Published Documents View - gets the latest version of each logical
|
|
@@ -198,8 +239,10 @@ export const currentPublishedDocumentsView = pgView('byline_current_published_do
|
|
|
198
239
|
updated_at: sq.updated_at,
|
|
199
240
|
created_by: sq.created_by,
|
|
200
241
|
change_summary: sq.change_summary,
|
|
242
|
+
order_key: documents.order_key,
|
|
201
243
|
})
|
|
202
244
|
.from(sq)
|
|
245
|
+
.innerJoin(documents, eq(documents.id, sq.document_id))
|
|
203
246
|
.where(eq(sq.rn, 1));
|
|
204
247
|
});
|
|
205
248
|
// Base field values structure
|
|
@@ -22,10 +22,10 @@ export declare class CollectionCommands implements ICollectionCommands {
|
|
|
22
22
|
id: string;
|
|
23
23
|
created_at: Date | null;
|
|
24
24
|
updated_at: Date | null;
|
|
25
|
+
config: unknown;
|
|
25
26
|
path: string;
|
|
26
27
|
singular: string;
|
|
27
28
|
plural: string;
|
|
28
|
-
config: unknown;
|
|
29
29
|
version: number;
|
|
30
30
|
schema_hash: string | null;
|
|
31
31
|
}[]>;
|
|
@@ -79,6 +79,7 @@ export declare class DocumentCommands implements IDocumentCommands {
|
|
|
79
79
|
status?: string;
|
|
80
80
|
createdBy?: string;
|
|
81
81
|
previousVersionId?: string;
|
|
82
|
+
orderKey?: string;
|
|
82
83
|
}): Promise<{
|
|
83
84
|
document: {
|
|
84
85
|
id: string;
|
|
@@ -133,6 +134,15 @@ export declare class DocumentCommands implements IDocumentCommands {
|
|
|
133
134
|
softDeleteDocument(params: {
|
|
134
135
|
document_id: string;
|
|
135
136
|
}): Promise<number>;
|
|
137
|
+
/**
|
|
138
|
+
* Write `order_key` on a single `byline_documents` row. Single-column
|
|
139
|
+
* metadata update — no new version row, no `documentVersions` touch.
|
|
140
|
+
* `updated_at` on the document row is bumped so list caches invalidate.
|
|
141
|
+
*/
|
|
142
|
+
setOrderKey(params: {
|
|
143
|
+
document_id: string;
|
|
144
|
+
order_key: string;
|
|
145
|
+
}): Promise<void>;
|
|
136
146
|
}
|
|
137
147
|
export declare function createCommandBuilders(db: DatabaseConnection, defaultContentLocale: string): {
|
|
138
148
|
collections: CollectionCommands;
|
|
@@ -76,6 +76,7 @@ export class DocumentCommands {
|
|
|
76
76
|
.values({
|
|
77
77
|
id: documentId,
|
|
78
78
|
collection_id: params.collectionId,
|
|
79
|
+
order_key: params.orderKey ?? null,
|
|
79
80
|
})
|
|
80
81
|
.returning()
|
|
81
82
|
.then(getFirstOrThrow('Failed to create document'));
|
|
@@ -287,6 +288,20 @@ export class DocumentCommands {
|
|
|
287
288
|
.where(eq(documentVersions.document_id, params.document_id));
|
|
288
289
|
return result.rowCount ?? 0;
|
|
289
290
|
}
|
|
291
|
+
/**
|
|
292
|
+
* Write `order_key` on a single `byline_documents` row. Single-column
|
|
293
|
+
* metadata update — no new version row, no `documentVersions` touch.
|
|
294
|
+
* `updated_at` on the document row is bumped so list caches invalidate.
|
|
295
|
+
*/
|
|
296
|
+
async setOrderKey(params) {
|
|
297
|
+
await this.db
|
|
298
|
+
.update(documents)
|
|
299
|
+
.set({
|
|
300
|
+
order_key: params.order_key,
|
|
301
|
+
updated_at: new Date(),
|
|
302
|
+
})
|
|
303
|
+
.where(eq(documents.id, params.document_id));
|
|
304
|
+
}
|
|
290
305
|
}
|
|
291
306
|
export function createCommandBuilders(db, defaultContentLocale) {
|
|
292
307
|
return {
|
|
@@ -30,10 +30,10 @@ export declare class CollectionQueries implements ICollectionQueries {
|
|
|
30
30
|
id: string;
|
|
31
31
|
created_at: Date | null;
|
|
32
32
|
updated_at: Date | null;
|
|
33
|
+
config: unknown;
|
|
33
34
|
path: string;
|
|
34
35
|
singular: string;
|
|
35
36
|
plural: string;
|
|
36
|
-
config: unknown;
|
|
37
37
|
version: number;
|
|
38
38
|
schema_hash: string | null;
|
|
39
39
|
} | undefined>;
|
|
@@ -41,10 +41,10 @@ export declare class CollectionQueries implements ICollectionQueries {
|
|
|
41
41
|
id: string;
|
|
42
42
|
created_at: Date | null;
|
|
43
43
|
updated_at: Date | null;
|
|
44
|
+
config: unknown;
|
|
44
45
|
path: string;
|
|
45
46
|
singular: string;
|
|
46
47
|
plural: string;
|
|
47
|
-
config: unknown;
|
|
48
48
|
version: number;
|
|
49
49
|
schema_hash: string | null;
|
|
50
50
|
} | undefined>;
|
|
@@ -306,6 +306,48 @@ export declare class DocumentQueries implements IDocumentQueries {
|
|
|
306
306
|
document_ids: string[];
|
|
307
307
|
status?: string;
|
|
308
308
|
}): Promise<Set<string>>;
|
|
309
|
+
/**
|
|
310
|
+
* getLastOrderKey
|
|
311
|
+
*
|
|
312
|
+
* Largest `order_key` currently in use for the given collection. Used
|
|
313
|
+
* at create-time on `orderable: true` collections to append the new
|
|
314
|
+
* row at the end. Returns `null` when no keyed rows exist yet.
|
|
315
|
+
*/
|
|
316
|
+
getLastOrderKey({ collection_id }: {
|
|
317
|
+
collection_id: string;
|
|
318
|
+
}): Promise<string | null>;
|
|
319
|
+
/**
|
|
320
|
+
* getNeighborOrderKeys
|
|
321
|
+
*
|
|
322
|
+
* Resolve the `order_key` values bracketing a target gap in one query.
|
|
323
|
+
* `before_document_id` is the doc the moved row should land *after*;
|
|
324
|
+
* `after_document_id` is the doc it should land *before*. Either or
|
|
325
|
+
* both may be null (append / prepend / empty collection).
|
|
326
|
+
*
|
|
327
|
+
* Resolves both keys in a single round trip to keep the read consistent
|
|
328
|
+
* with the next-key computation that follows in the caller.
|
|
329
|
+
*/
|
|
330
|
+
getNeighborOrderKeys({ collection_id, before_document_id, after_document_id, }: {
|
|
331
|
+
collection_id: string;
|
|
332
|
+
before_document_id: string | null;
|
|
333
|
+
after_document_id: string | null;
|
|
334
|
+
}): Promise<{
|
|
335
|
+
left: string | null;
|
|
336
|
+
right: string | null;
|
|
337
|
+
}>;
|
|
338
|
+
/**
|
|
339
|
+
* getCanonicalDocumentOrder
|
|
340
|
+
*
|
|
341
|
+
* Returns every document in the collection in its canonical list-view
|
|
342
|
+
* order: `order_key ASC NULLS LAST, created_at DESC`. Used by the reorder
|
|
343
|
+
* server fn for backfill and recovery from key corruption.
|
|
344
|
+
*/
|
|
345
|
+
getCanonicalDocumentOrder({ collection_id, }: {
|
|
346
|
+
collection_id: string;
|
|
347
|
+
}): Promise<Array<{
|
|
348
|
+
id: string;
|
|
349
|
+
order_key: string | null;
|
|
350
|
+
}>>;
|
|
309
351
|
/**
|
|
310
352
|
* getDocumentCountsByStatus
|
|
311
353
|
*
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
// logger. A future refactor could inject the logger at construction time by
|
|
11
11
|
// either deferring adapter construction or accepting a lazy logger parameter.
|
|
12
12
|
import { ERR_DATABASE, ERR_NOT_FOUND, getLogger } from '@byline/core';
|
|
13
|
-
import { and, eq, inArray, sql } from 'drizzle-orm';
|
|
14
|
-
import { collections, currentDocumentsView, currentPublishedDocumentsView, documentPaths, documentVersions, metaStore, } from '../../database/schema/index.js';
|
|
13
|
+
import { and, desc, eq, inArray, isNotNull, sql } from 'drizzle-orm';
|
|
14
|
+
import { collections, currentDocumentsView, currentPublishedDocumentsView, documentPaths, documents, documentVersions, metaStore, } from '../../database/schema/index.js';
|
|
15
15
|
import { extractFlattenedFieldValue, restoreFieldSetData } from './storage-restore.js';
|
|
16
16
|
import { allStoreTypes, storeSelectList, storeTableNames, } from './storage-store-manifest.js';
|
|
17
17
|
import { resolveStoreTypes } from './storage-utils.js';
|
|
@@ -601,6 +601,67 @@ export class DocumentQueries {
|
|
|
601
601
|
.groupBy(documentVersions.document_id);
|
|
602
602
|
return new Set(rows.map((r) => r.document_id));
|
|
603
603
|
}
|
|
604
|
+
/**
|
|
605
|
+
* getLastOrderKey
|
|
606
|
+
*
|
|
607
|
+
* Largest `order_key` currently in use for the given collection. Used
|
|
608
|
+
* at create-time on `orderable: true` collections to append the new
|
|
609
|
+
* row at the end. Returns `null` when no keyed rows exist yet.
|
|
610
|
+
*/
|
|
611
|
+
async getLastOrderKey({ collection_id }) {
|
|
612
|
+
const rows = await this.db
|
|
613
|
+
.select({ order_key: documents.order_key })
|
|
614
|
+
.from(documents)
|
|
615
|
+
.where(and(eq(documents.collection_id, collection_id), isNotNull(documents.order_key)))
|
|
616
|
+
.orderBy(desc(documents.order_key))
|
|
617
|
+
.limit(1);
|
|
618
|
+
return rows[0]?.order_key ?? null;
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* getNeighborOrderKeys
|
|
622
|
+
*
|
|
623
|
+
* Resolve the `order_key` values bracketing a target gap in one query.
|
|
624
|
+
* `before_document_id` is the doc the moved row should land *after*;
|
|
625
|
+
* `after_document_id` is the doc it should land *before*. Either or
|
|
626
|
+
* both may be null (append / prepend / empty collection).
|
|
627
|
+
*
|
|
628
|
+
* Resolves both keys in a single round trip to keep the read consistent
|
|
629
|
+
* with the next-key computation that follows in the caller.
|
|
630
|
+
*/
|
|
631
|
+
async getNeighborOrderKeys({ collection_id, before_document_id, after_document_id, }) {
|
|
632
|
+
const ids = [];
|
|
633
|
+
if (before_document_id)
|
|
634
|
+
ids.push(before_document_id);
|
|
635
|
+
if (after_document_id)
|
|
636
|
+
ids.push(after_document_id);
|
|
637
|
+
if (ids.length === 0) {
|
|
638
|
+
return { left: null, right: null };
|
|
639
|
+
}
|
|
640
|
+
const rows = await this.db
|
|
641
|
+
.select({ id: documents.id, order_key: documents.order_key })
|
|
642
|
+
.from(documents)
|
|
643
|
+
.where(and(eq(documents.collection_id, collection_id), inArray(documents.id, ids)));
|
|
644
|
+
const byId = new Map(rows.map((r) => [r.id, r.order_key]));
|
|
645
|
+
return {
|
|
646
|
+
left: before_document_id ? (byId.get(before_document_id) ?? null) : null,
|
|
647
|
+
right: after_document_id ? (byId.get(after_document_id) ?? null) : null,
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* getCanonicalDocumentOrder
|
|
652
|
+
*
|
|
653
|
+
* Returns every document in the collection in its canonical list-view
|
|
654
|
+
* order: `order_key ASC NULLS LAST, created_at DESC`. Used by the reorder
|
|
655
|
+
* server fn for backfill and recovery from key corruption.
|
|
656
|
+
*/
|
|
657
|
+
async getCanonicalDocumentOrder({ collection_id, }) {
|
|
658
|
+
const rows = await this.db
|
|
659
|
+
.select({ id: documents.id, order_key: documents.order_key })
|
|
660
|
+
.from(documents)
|
|
661
|
+
.where(eq(documents.collection_id, collection_id))
|
|
662
|
+
.orderBy(sql `${documents.order_key} ASC NULLS LAST`, desc(documents.created_at));
|
|
663
|
+
return rows;
|
|
664
|
+
}
|
|
604
665
|
/**
|
|
605
666
|
* getDocumentCountsByStatus
|
|
606
667
|
*
|
|
@@ -1037,6 +1098,16 @@ export class DocumentQueries {
|
|
|
1037
1098
|
* arrives.
|
|
1038
1099
|
*/
|
|
1039
1100
|
buildDocumentOrderClause(orderBy, direction) {
|
|
1101
|
+
// `order_key` is the fractional-index column for `orderable: true`
|
|
1102
|
+
// collections. Always sort NULLS LAST with a `created_at DESC` tiebreaker
|
|
1103
|
+
// so unkeyed rows (existing rows in a newly-opted-in collection, or rows
|
|
1104
|
+
// from before the column existed) fall to the bottom in a stable order
|
|
1105
|
+
// until the editor drags them into position.
|
|
1106
|
+
if (orderBy === 'order_key') {
|
|
1107
|
+
return direction === 'desc'
|
|
1108
|
+
? sql `d.order_key DESC NULLS LAST, d.created_at DESC`
|
|
1109
|
+
: sql `d.order_key ASC NULLS LAST, d.created_at DESC`;
|
|
1110
|
+
}
|
|
1040
1111
|
const columnMap = {
|
|
1041
1112
|
created_at: 'd.created_at',
|
|
1042
1113
|
updated_at: 'd.updated_at',
|
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": "1.
|
|
5
|
+
"version": "1.11.1",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">=20.9.0"
|
|
8
8
|
},
|
|
@@ -52,9 +52,9 @@
|
|
|
52
52
|
"pg": "^8.20.0",
|
|
53
53
|
"uuid": "^14.0.0",
|
|
54
54
|
"zod": "^4.4.3",
|
|
55
|
-
"@byline/
|
|
56
|
-
"@byline/
|
|
57
|
-
"@byline/admin": "1.
|
|
55
|
+
"@byline/core": "1.11.1",
|
|
56
|
+
"@byline/auth": "1.11.1",
|
|
57
|
+
"@byline/admin": "1.11.1"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@biomejs/biome": "2.4.15",
|