@forge-cms/runtime 0.5.0 → 0.6.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.
Files changed (63) hide show
  1. package/dist/auth-managed.d.ts +19 -0
  2. package/dist/auth-managed.d.ts.map +1 -0
  3. package/dist/auth-managed.js +24 -0
  4. package/dist/auth-managed.js.map +1 -0
  5. package/dist/concurrency.d.ts +8 -0
  6. package/dist/concurrency.d.ts.map +1 -0
  7. package/dist/concurrency.js +15 -0
  8. package/dist/concurrency.js.map +1 -0
  9. package/dist/context.d.ts +5 -0
  10. package/dist/context.d.ts.map +1 -1
  11. package/dist/errors.d.ts +29 -1
  12. package/dist/errors.d.ts.map +1 -1
  13. package/dist/errors.js +38 -0
  14. package/dist/errors.js.map +1 -1
  15. package/dist/files.d.ts +15 -1
  16. package/dist/files.d.ts.map +1 -1
  17. package/dist/files.js +55 -14
  18. package/dist/files.js.map +1 -1
  19. package/dist/globals.d.ts +21 -3
  20. package/dist/globals.d.ts.map +1 -1
  21. package/dist/globals.js +216 -28
  22. package/dist/globals.js.map +1 -1
  23. package/dist/handlers.d.ts +3 -2
  24. package/dist/handlers.d.ts.map +1 -1
  25. package/dist/handlers.js +36 -47
  26. package/dist/handlers.js.map +1 -1
  27. package/dist/index.d.ts +3 -1
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +4 -1
  30. package/dist/index.js.map +1 -1
  31. package/dist/localization.d.ts +17 -0
  32. package/dist/localization.d.ts.map +1 -1
  33. package/dist/localization.js +56 -0
  34. package/dist/localization.js.map +1 -1
  35. package/dist/operations.d.ts +51 -12
  36. package/dist/operations.d.ts.map +1 -1
  37. package/dist/operations.js +728 -125
  38. package/dist/operations.js.map +1 -1
  39. package/dist/relation-integrity.d.ts +31 -13
  40. package/dist/relation-integrity.d.ts.map +1 -1
  41. package/dist/relation-integrity.js +62 -6
  42. package/dist/relation-integrity.js.map +1 -1
  43. package/dist/relation-lifecycle.d.ts +95 -0
  44. package/dist/relation-lifecycle.d.ts.map +1 -0
  45. package/dist/relation-lifecycle.js +424 -0
  46. package/dist/relation-lifecycle.js.map +1 -0
  47. package/dist/runtime.d.ts +21 -0
  48. package/dist/runtime.d.ts.map +1 -1
  49. package/dist/runtime.js +112 -20
  50. package/dist/runtime.js.map +1 -1
  51. package/dist/storage-intents.d.ts +96 -0
  52. package/dist/storage-intents.d.ts.map +1 -0
  53. package/dist/storage-intents.js +217 -0
  54. package/dist/storage-intents.js.map +1 -0
  55. package/dist/system-fields.d.ts +27 -0
  56. package/dist/system-fields.d.ts.map +1 -0
  57. package/dist/system-fields.js +74 -0
  58. package/dist/system-fields.js.map +1 -0
  59. package/dist/versions.d.ts +73 -1
  60. package/dist/versions.d.ts.map +1 -1
  61. package/dist/versions.js +204 -17
  62. package/dist/versions.js.map +1 -1
  63. package/package.json +9 -7
@@ -1,4 +1,5 @@
1
1
  import type { CmsUser, CollectionDefinition, Version } from '@forge-cms/core';
2
+ import type { DatabaseAdapter, DatabaseRecord } from '@forge-cms/db';
2
3
  import type { OperationContext } from './context.js';
3
4
  export interface ListVersionsArgs {
4
5
  collection: string;
@@ -29,6 +30,11 @@ export interface CreateVersionArgs {
29
30
  label?: string;
30
31
  }
31
32
  declare function versionsEnabled(collection: CollectionDefinition): boolean;
33
+ /**
34
+ * Whether `versions: { autosave: true }` is set. Nothing in the runtime acts on it today (spec 062 §11):
35
+ * automatic snapshots are always `autosave: false`; only a manual `createVersion({ autosave: true })`
36
+ * sets the flag.
37
+ */
32
38
  declare function autosaveEnabled(collection: CollectionDefinition): boolean;
33
39
  /**
34
40
  * Lists all versions of a document, newest first.
@@ -42,8 +48,74 @@ export declare function listVersions(ctx: OperationContext, args: ListVersionsAr
42
48
  */
43
49
  export declare function getVersion(ctx: OperationContext, args: GetVersionArgs): Promise<Version>;
44
50
  /**
45
- * Creates a new version of a document. Called automatically on updates when versions are enabled.
51
+ * Creates a version of a document by hand (trusted Local API only — there is no HTTP route). Stores
52
+ * `data` verbatim: no hooks, no access check, no check that the owner document still exists, and — since
53
+ * nothing guarantees the caller passed full content — the row is not marked as a full snapshot, so a
54
+ * restore of it only applies the fields it contains (spec 062 §7).
55
+ *
56
+ * The version number is `latest + 1`, made safe by the unique `(documentId, versionNumber)` index: when
57
+ * another writer takes that number first, the latest is re-read and the insert retried, at most
58
+ * {@link MAX_MANUAL_VERSION_ATTEMPTS} times in total, then {@link ConcurrentModificationError}. Retrying
59
+ * is safe here — and only here — because nothing but the number changes between attempts: no document
60
+ * write, no consumer code. Automatic snapshots are not created through this function; see
61
+ * `operations.ts`, which writes them in the same atomic batch as the document.
46
62
  */
47
63
  export declare function createVersion(ctx: OperationContext, args: CreateVersionArgs): Promise<Version>;
64
+ export declare function versionsCollectionSlug(collectionSlug: string): string;
65
+ /**
66
+ * The internal collection that stores a versioned collection's history. The compound unique
67
+ * `(documentId, versionNumber)` index is the version-identity invariant every automatic write relies
68
+ * on for serialization (spec 062 §1/§3); `snapshotFormat` tells a full snapshot from a pre-062 patch.
69
+ */
70
+ export declare function versionCollectionDefinition(collectionSlug: string): CollectionDefinition;
71
+ /** Whether `err` is the version table's `(documentId, versionNumber)` unique index rejecting a write. */
72
+ export declare function isVersionIdentityConflict(err: unknown, collection: CollectionDefinition): boolean;
73
+ /** The highest committed version number of a document, `0` when it has none. */
74
+ export declare function readLatestVersionNumber(database: DatabaseAdapter, collection: CollectionDefinition, documentId: string): Promise<number>;
75
+ /**
76
+ * The restorable content of a document (spec 062 §5): every field the collection declares — `null`
77
+ * when unset, so restoring can clear it — plus `_status` on a drafts collection. Never `id`,
78
+ * timestamps, `_storageKey` or undeclared keys.
79
+ */
80
+ export declare function buildSnapshot(collection: CollectionDefinition, content: Record<string, unknown>): Record<string, unknown>;
81
+ export declare function buildVersionRecord(input: {
82
+ documentId: string;
83
+ versionNumber: number;
84
+ data: Record<string, unknown>;
85
+ user: CmsUser | null;
86
+ /** `true` for automatic snapshots built with {@link buildSnapshot}. */
87
+ full: boolean;
88
+ autosave?: boolean;
89
+ label?: string;
90
+ }): DatabaseRecord;
91
+ /** A version as restore needs it: the public shape plus whether its data is a full snapshot. */
92
+ export interface RestorableVersion {
93
+ version: Version;
94
+ full: boolean;
95
+ }
96
+ /** Raw (trusted, unfiltered) version read for restore — `getVersion` does not expose the format marker. */
97
+ export declare function readVersionForRestore(ctx: OperationContext, collection: CollectionDefinition, versionId: string): Promise<RestorableVersion>;
98
+ /**
99
+ * What a restore sets (spec 062 §6). A full snapshot sets every *currently* declared field — a field the
100
+ * snapshot lacks did not exist then, so it becomes `null` (and fails current validation if it is now
101
+ * required). A legacy/manual snapshot may be a patch, so only the declared fields it contains are set.
102
+ * System metadata and undeclared keys are dropped either way.
103
+ */
104
+ export declare function restoreTarget(collection: CollectionDefinition, restorable: RestorableVersion): Record<string, unknown>;
105
+ /** Only the target fields whose value differs from the current document. */
106
+ export declare function diffAgainst(target: Record<string, unknown>, current: Record<string, unknown>): Record<string, unknown>;
107
+ /** One duplicated version identity found by {@link findDuplicateVersionIdentities}. */
108
+ export interface DuplicateVersionIdentity {
109
+ documentId: string;
110
+ versionNumber: number;
111
+ rows: number;
112
+ }
113
+ /**
114
+ * Scans a version table for `(documentId, versionNumber)` pairs held by more than one row — history the
115
+ * pre-062 read-then-insert race could produce, and which blocks the unique index (spec 062 §8). Reads
116
+ * only; never repairs. Pages through the table in identity order with the ordinary adapter API, so it
117
+ * works on every adapter (an upgrade/diagnostic path, not a hot path).
118
+ */
119
+ export declare function findDuplicateVersionIdentities(database: DatabaseAdapter, versionsCollection: string): Promise<DuplicateVersionIdentity[]>;
48
120
  export { versionsEnabled, autosaveEnabled };
49
121
  //# sourceMappingURL=versions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"versions.d.ts","sourceRoot":"","sources":["../src/versions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE9E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAMrD,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAQD,iBAAS,eAAe,CAAC,UAAU,EAAE,oBAAoB,GAAG,OAAO,CAKlE;AAED,iBAAS,eAAe,CAAC,UAAU,EAAE,oBAAoB,GAAG,OAAO,CAKlE;AAuCD;;GAEG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,OAAO,EAAE,CAAC,CA+BpB;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,gBAAgB,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAiB9F;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,OAAO,CAAC,CAiClB;AAiBD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"versions.d.ts","sourceRoot":"","sources":["../src/versions.ts"],"names":[],"mappings":"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"}
package/dist/versions.js CHANGED
@@ -1,7 +1,10 @@
1
- import { NotFoundError } from './errors.js';
1
+ import { defineField } from '@forge-cms/core';
2
+ import { isUniqueConstraintError as isDbUniqueConstraintError } from '@forge-cms/db';
3
+ import { ConcurrentModificationError, NotFoundError } from './errors.js';
2
4
  import { documentMatches } from './access.js';
3
5
  import { checkAccess, statusConstraint } from './read-policy.js';
4
6
  import { filterReadableFields } from './field-access.js';
7
+ import { FORGE_OWNED_KEYS } from './system-fields.js';
5
8
  function getCollectionOrThrow(ctx, slug) {
6
9
  const collection = ctx.getCollection(slug);
7
10
  if (!collection)
@@ -12,6 +15,11 @@ function versionsEnabled(collection) {
12
15
  return (collection.versions === true ||
13
16
  (typeof collection.versions === 'object' && collection.versions !== null));
14
17
  }
18
+ /**
19
+ * Whether `versions: { autosave: true }` is set. Nothing in the runtime acts on it today (spec 062 §11):
20
+ * automatic snapshots are always `autosave: false`; only a manual `createVersion({ autosave: true })`
21
+ * sets the flag.
22
+ */
15
23
  function autosaveEnabled(collection) {
16
24
  if (typeof collection.versions === 'object' && collection.versions !== null) {
17
25
  return collection.versions.autosave === true;
@@ -101,36 +109,215 @@ export async function getVersion(ctx, args) {
101
109
  await assertOwnerReadable(ctx, collection, version.documentId, user);
102
110
  return { ...version, data: await filterReadableFields(version.data, collection, user) };
103
111
  }
112
+ /** Attempts (in total) manual {@link createVersion} makes to allocate a version number under contention. */
113
+ const MAX_MANUAL_VERSION_ATTEMPTS = 3;
104
114
  /**
105
- * Creates a new version of a document. Called automatically on updates when versions are enabled.
115
+ * Creates a version of a document by hand (trusted Local API only — there is no HTTP route). Stores
116
+ * `data` verbatim: no hooks, no access check, no check that the owner document still exists, and — since
117
+ * nothing guarantees the caller passed full content — the row is not marked as a full snapshot, so a
118
+ * restore of it only applies the fields it contains (spec 062 §7).
119
+ *
120
+ * The version number is `latest + 1`, made safe by the unique `(documentId, versionNumber)` index: when
121
+ * another writer takes that number first, the latest is re-read and the insert retried, at most
122
+ * {@link MAX_MANUAL_VERSION_ATTEMPTS} times in total, then {@link ConcurrentModificationError}. Retrying
123
+ * is safe here — and only here — because nothing but the number changes between attempts: no document
124
+ * write, no consumer code. Automatic snapshots are not created through this function; see
125
+ * `operations.ts`, which writes them in the same atomic batch as the document.
106
126
  */
107
127
  export async function createVersion(ctx, args) {
108
128
  const collection = getCollectionOrThrow(ctx, args.collection);
109
129
  if (!versionsEnabled(collection)) {
110
130
  throw new Error(`Collection '${args.collection}' does not have versions enabled`);
111
131
  }
112
- const versionsCollection = `_versions_${args.collection}`;
113
- // Get the latest version number for this document
114
- const existingVersions = await ctx.adapters.database.findMany({
115
- collection: versionsCollection,
116
- where: { documentId: args.documentId },
132
+ for (let attempt = 1;; attempt++) {
133
+ const latest = await readLatestVersionNumber(ctx.adapters.database, collection, args.documentId);
134
+ const record = buildVersionRecord({
135
+ documentId: args.documentId,
136
+ versionNumber: latest + 1,
137
+ data: args.data,
138
+ user: args.user ?? null,
139
+ full: false,
140
+ ...(args.autosave !== undefined && { autosave: args.autosave }),
141
+ ...(args.label !== undefined && { label: args.label })
142
+ });
143
+ try {
144
+ const created = await ctx.adapters.database.create(versionsCollectionSlug(collection.slug), record);
145
+ return toVersion(created);
146
+ }
147
+ catch (err) {
148
+ if (!isVersionIdentityConflict(err, collection))
149
+ throw err;
150
+ if (attempt >= MAX_MANUAL_VERSION_ATTEMPTS) {
151
+ throw new ConcurrentModificationError(collection.slug, args.documentId);
152
+ }
153
+ }
154
+ }
155
+ }
156
+ // --- spec 062: version table, full snapshots, restore diff ---------------------------------------
157
+ /** Marker stored in `snapshotFormat` on every automatic snapshot written since spec 062. */
158
+ const FULL_SNAPSHOT = 'full';
159
+ export function versionsCollectionSlug(collectionSlug) {
160
+ return `_versions_${collectionSlug}`;
161
+ }
162
+ /**
163
+ * The internal collection that stores a versioned collection's history. The compound unique
164
+ * `(documentId, versionNumber)` index is the version-identity invariant every automatic write relies
165
+ * on for serialization (spec 062 §1/§3); `snapshotFormat` tells a full snapshot from a pre-062 patch.
166
+ */
167
+ export function versionCollectionDefinition(collectionSlug) {
168
+ const fields = {
169
+ documentId: defineField.text({ required: true }),
170
+ versionNumber: defineField.number({ required: true }),
171
+ data: defineField.json({ required: true }),
172
+ createdAt: defineField.date({ required: true }),
173
+ createdBy: defineField.text(),
174
+ autosave: defineField.boolean(),
175
+ label: defineField.text(),
176
+ snapshotFormat: defineField.text()
177
+ };
178
+ return {
179
+ slug: versionsCollectionSlug(collectionSlug),
180
+ fields,
181
+ indexes: [{ fields: ['documentId', 'versionNumber'], unique: true }]
182
+ };
183
+ }
184
+ /** Whether `err` is the version table's `(documentId, versionNumber)` unique index rejecting a write. */
185
+ export function isVersionIdentityConflict(err, collection) {
186
+ return (isDbUniqueConstraintError(err) && err.collection === versionsCollectionSlug(collection.slug));
187
+ }
188
+ /** The highest committed version number of a document, `0` when it has none. */
189
+ export async function readLatestVersionNumber(database, collection, documentId) {
190
+ const [latest] = await database.findMany({
191
+ collection: versionsCollectionSlug(collection.slug),
192
+ where: { documentId },
117
193
  sort: 'versionNumber',
118
194
  order: 'desc',
119
195
  limit: 1
120
196
  });
121
- const lastVersionNumber = existingVersions.length > 0 ? (existingVersions[0]?.versionNumber ?? 0) : 0;
122
- const versionRecord = {
197
+ const value = latest?.versionNumber;
198
+ return typeof value === 'number' ? value : 0;
199
+ }
200
+ /**
201
+ * The restorable content of a document (spec 062 §5): every field the collection declares — `null`
202
+ * when unset, so restoring can clear it — plus `_status` on a drafts collection. Never `id`,
203
+ * timestamps, `_storageKey` or undeclared keys.
204
+ */
205
+ export function buildSnapshot(collection, content) {
206
+ const snapshot = {};
207
+ for (const name of Object.keys(collection.fields)) {
208
+ snapshot[name] = content[name] ?? null;
209
+ }
210
+ if (collection.drafts === true && content._status !== undefined) {
211
+ snapshot._status = content._status;
212
+ }
213
+ return snapshot;
214
+ }
215
+ export function buildVersionRecord(input) {
216
+ return {
123
217
  id: crypto.randomUUID(),
124
- documentId: args.documentId,
125
- versionNumber: lastVersionNumber + 1,
126
- data: JSON.stringify(args.data),
218
+ documentId: input.documentId,
219
+ versionNumber: input.versionNumber,
220
+ data: JSON.stringify(input.data),
127
221
  createdAt: new Date().toISOString(),
128
- createdBy: args.user?.id ?? null,
129
- autosave: args.autosave ?? false,
130
- ...(args.label !== undefined && { label: args.label })
222
+ createdBy: input.user?.id ?? null,
223
+ autosave: input.autosave ?? false,
224
+ ...(input.full && { snapshotFormat: FULL_SNAPSHOT }),
225
+ ...(input.label !== undefined && { label: input.label })
131
226
  };
132
- const created = await ctx.adapters.database.create(versionsCollection, versionRecord);
133
- return toVersion(created);
227
+ }
228
+ /** Raw (trusted, unfiltered) version read for restore — `getVersion` does not expose the format marker. */
229
+ export async function readVersionForRestore(ctx, collection, versionId) {
230
+ const record = await ctx.adapters.database.findById(versionsCollectionSlug(collection.slug), versionId);
231
+ if (!record)
232
+ throw new NotFoundError(`Version '${versionId}' not found`);
233
+ return { version: toVersion(record), full: record.snapshotFormat === FULL_SNAPSHOT };
234
+ }
235
+ /**
236
+ * What a restore sets (spec 062 §6). A full snapshot sets every *currently* declared field — a field the
237
+ * snapshot lacks did not exist then, so it becomes `null` (and fails current validation if it is now
238
+ * required). A legacy/manual snapshot may be a patch, so only the declared fields it contains are set.
239
+ * System metadata and undeclared keys are dropped either way.
240
+ */
241
+ export function restoreTarget(collection, restorable) {
242
+ const data = restorable.version.data;
243
+ const target = {};
244
+ for (const name of Object.keys(collection.fields)) {
245
+ if (name in data)
246
+ target[name] = data[name];
247
+ else if (restorable.full)
248
+ target[name] = null;
249
+ }
250
+ if (collection.drafts === true && data._status !== undefined)
251
+ target._status = data._status;
252
+ // Adapter/system metadata is never restorable content (spec 062 §5, spec 063).
253
+ for (const key of FORGE_OWNED_KEYS)
254
+ delete target[key];
255
+ return target;
256
+ }
257
+ /** Only the target fields whose value differs from the current document. */
258
+ export function diffAgainst(target, current) {
259
+ const patch = {};
260
+ for (const [key, value] of Object.entries(target)) {
261
+ if (!sameValue(value, current[key]))
262
+ patch[key] = value;
263
+ }
264
+ return patch;
265
+ }
266
+ function comparable(value) {
267
+ if (value === undefined || value === null)
268
+ return null;
269
+ if (value instanceof Date)
270
+ return value.toISOString();
271
+ if (Array.isArray(value))
272
+ return value.map(comparable);
273
+ if (typeof value === 'object') {
274
+ return Object.fromEntries(Object.keys(value)
275
+ .sort()
276
+ .map((key) => [key, comparable(value[key])]));
277
+ }
278
+ return value;
279
+ }
280
+ function sameValue(a, b) {
281
+ return JSON.stringify(comparable(a)) === JSON.stringify(comparable(b));
282
+ }
283
+ const DUPLICATE_SCAN_PAGE = 500;
284
+ /**
285
+ * Scans a version table for `(documentId, versionNumber)` pairs held by more than one row — history the
286
+ * pre-062 read-then-insert race could produce, and which blocks the unique index (spec 062 §8). Reads
287
+ * only; never repairs. Pages through the table in identity order with the ordinary adapter API, so it
288
+ * works on every adapter (an upgrade/diagnostic path, not a hot path).
289
+ */
290
+ export async function findDuplicateVersionIdentities(database, versionsCollection) {
291
+ const duplicates = [];
292
+ let previous;
293
+ for (let offset = 0;; offset += DUPLICATE_SCAN_PAGE) {
294
+ const page = await database.findMany({
295
+ collection: versionsCollection,
296
+ sort: [
297
+ { field: 'documentId', order: 'asc' },
298
+ { field: 'versionNumber', order: 'asc' },
299
+ { field: 'id', order: 'asc' }
300
+ ],
301
+ limit: DUPLICATE_SCAN_PAGE,
302
+ offset
303
+ });
304
+ for (const row of page) {
305
+ const documentId = String(row.documentId);
306
+ const versionNumber = Number(row.versionNumber);
307
+ if (previous &&
308
+ previous.documentId === documentId &&
309
+ previous.versionNumber === versionNumber) {
310
+ previous.rows++;
311
+ if (previous.rows === 2)
312
+ duplicates.push(previous);
313
+ }
314
+ else {
315
+ previous = { documentId, versionNumber, rows: 1 };
316
+ }
317
+ }
318
+ if (page.length < DUPLICATE_SCAN_PAGE)
319
+ return duplicates;
320
+ }
134
321
  }
135
322
  function toVersion(record) {
136
323
  const data = typeof record.data === 'string' ? JSON.parse(record.data) : record.data;
@@ -1 +1 @@
1
- {"version":3,"file":"versions.js","sourceRoot":"","sources":["../src/versions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"versions.js","sourceRoot":"","sources":["../src/versions.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forge-cms/runtime",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Runtime orchestrator for ForgeCMS — binds schema, adapters, and handlers.",
5
5
  "author": "ForgeCMS contributors",
6
6
  "license": "MIT",
@@ -35,15 +35,17 @@
35
35
  }
36
36
  },
37
37
  "dependencies": {
38
- "@forge-cms/api": "0.5.0",
39
- "@forge-cms/db": "0.5.0",
40
- "@forge-cms/storage": "0.5.0",
41
- "@forge-cms/core": "0.5.0",
42
- "@forge-cms/auth": "0.5.0"
38
+ "@forge-cms/api": "0.6.0",
39
+ "@forge-cms/auth": "0.6.0",
40
+ "@forge-cms/core": "0.6.0",
41
+ "@forge-cms/db": "0.6.0",
42
+ "@forge-cms/storage": "0.6.0"
43
43
  },
44
44
  "devDependencies": {
45
+ "@libsql/client": "0.17.3",
45
46
  "typescript": "5.9.2",
46
- "vitest": "4.1.6"
47
+ "vitest": "4.1.6",
48
+ "@forge-cms/testing": "0.6.0"
47
49
  },
48
50
  "scripts": {
49
51
  "build": "tsc -p tsconfig.build.json",