@byline/host-tanstack-start 4.19.0 → 5.0.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.
- package/dist/admin-shell/collections/edit.d.ts +1 -1
- package/dist/admin-shell/collections/edit.js +151 -31
- package/dist/admin-shell/collections/history.js +4 -2
- package/dist/admin-shell/collections/list.js +30 -6
- package/dist/admin-shell/collections/restore-version-modal.d.ts +3 -1
- package/dist/admin-shell/collections/restore-version-modal.js +9 -4
- package/dist/admin-shell/collections/tree-list.js +16 -6
- package/dist/admin-shell/collections/version-history.d.ts +2 -1
- package/dist/admin-shell/collections/version-history.js +11 -2
- package/dist/admin-shell/document-mutation-notice.d.ts +6 -0
- package/dist/admin-shell/document-mutation-notice.js +53 -0
- package/dist/admin-shell/document-mutation-state.d.ts +22 -0
- package/dist/admin-shell/document-mutation-state.js +71 -0
- package/dist/admin-shell/document-mutation-state.test.d.ts +1 -0
- package/dist/admin-shell/scheduled-publications/list.js +15 -5
- package/dist/admin-shell/singletons/history.js +4 -2
- package/dist/admin-shell/singletons/view.d.ts +1 -1
- package/dist/admin-shell/singletons/view.js +98 -19
- package/dist/integrations/byline-field-services.js +2 -9
- package/dist/routes/create-collection-edit-route.js +1 -1
- package/dist/routes/create-collection-list-route.d.ts +0 -7
- package/dist/routes/create-collection-list-route.js +7 -9
- package/dist/routes/create-singleton-route.d.ts +2 -0
- package/dist/routes/create-singleton-route.js +4 -3
- package/dist/server-fns/collections/copy-to-locale.d.ts +2 -7
- package/dist/server-fns/collections/copy-to-locale.js +4 -2
- package/dist/server-fns/collections/create.d.ts +1 -7
- package/dist/server-fns/collections/create.js +5 -3
- package/dist/server-fns/collections/delete-locale.d.ts +2 -7
- package/dist/server-fns/collections/delete-locale.js +4 -2
- package/dist/server-fns/collections/delete-outcome.d.ts +7 -3
- package/dist/server-fns/collections/delete-outcome.js +4 -0
- package/dist/server-fns/collections/delete.d.ts +2 -7
- package/dist/server-fns/collections/delete.js +5 -3
- package/dist/server-fns/collections/duplicate.d.ts +2 -7
- package/dist/server-fns/collections/duplicate.js +5 -3
- package/dist/server-fns/collections/get.d.ts +1 -7
- package/dist/server-fns/collections/get.js +5 -4
- package/dist/server-fns/collections/list.d.ts +0 -7
- package/dist/server-fns/collections/list.js +11 -3
- package/dist/server-fns/collections/reorder.d.ts +7 -8
- package/dist/server-fns/collections/reorder.js +20 -76
- package/dist/server-fns/collections/restore-version.d.ts +3 -7
- package/dist/server-fns/collections/restore-version.js +5 -2
- package/dist/server-fns/collections/save-outcome.d.ts +1 -0
- package/dist/server-fns/collections/save-outcome.js +1 -0
- package/dist/server-fns/collections/scheduled-publication.d.ts +49 -9
- package/dist/server-fns/collections/scheduled-publication.js +31 -21
- package/dist/server-fns/collections/status.d.ts +8 -7
- package/dist/server-fns/collections/status.js +13 -5
- package/dist/server-fns/collections/tree-mutation.d.ts +7 -6
- package/dist/server-fns/collections/tree-mutation.js +17 -5
- package/dist/server-fns/collections/tree.d.ts +14 -8
- package/dist/server-fns/collections/tree.js +21 -17
- package/dist/server-fns/collections/update.d.ts +12 -11
- package/dist/server-fns/collections/update.js +34 -20
- package/dist/server-fns/collections/upload.d.ts +1 -0
- package/dist/server-fns/collections/upload.js +3 -2
- package/dist/server-fns/document-mutation-errors.d.ts +5 -0
- package/dist/server-fns/document-mutation-errors.js +50 -0
- package/dist/server-fns/editable-revision.d.ts +9 -0
- package/dist/server-fns/editable-revision.js +11 -0
- package/dist/server-fns/singleton-document-read.d.ts +1 -1
- package/dist/server-fns/singleton-document-read.js +7 -3
- package/dist/server-fns/singletons/cancel-scheduled-publish.d.ts +6 -8
- package/dist/server-fns/singletons/cancel-scheduled-publish.js +4 -1
- package/dist/server-fns/singletons/change-status.d.ts +2 -7
- package/dist/server-fns/singletons/change-status.js +4 -1
- package/dist/server-fns/singletons/confirm-scheduled-publish.d.ts +5 -8
- package/dist/server-fns/singletons/confirm-scheduled-publish.js +4 -2
- package/dist/server-fns/singletons/copy-to-locale.d.ts +2 -7
- package/dist/server-fns/singletons/copy-to-locale.js +4 -2
- package/dist/server-fns/singletons/get.d.ts +4 -4
- package/dist/server-fns/singletons/restore-version.d.ts +2 -7
- package/dist/server-fns/singletons/restore-version.js +6 -3
- package/dist/server-fns/singletons/schedule-publish.d.ts +5 -8
- package/dist/server-fns/singletons/schedule-publish.js +4 -2
- package/dist/server-fns/singletons/unpublish.d.ts +2 -7
- package/dist/server-fns/singletons/unpublish.js +4 -1
- package/dist/server-fns/singletons/update.d.ts +4 -11
- package/dist/server-fns/singletons/update.js +5 -4
- package/dist/server-fns/structural-receipt.d.ts +4 -0
- package/dist/server-fns/structural-receipt.js +31 -0
- package/package.json +11 -11
- package/src/admin-shell/collections/edit.tsx +173 -54
- package/src/admin-shell/collections/history.tsx +11 -2
- package/src/admin-shell/collections/list.tsx +22 -6
- package/src/admin-shell/collections/restore-version-modal.tsx +12 -3
- package/src/admin-shell/collections/save-navigation.test.tsx +156 -8
- package/src/admin-shell/collections/tree-list.tsx +16 -6
- package/src/admin-shell/collections/version-history.tsx +13 -3
- package/src/admin-shell/document-mutation-notice.tsx +45 -0
- package/src/admin-shell/document-mutation-state.test.tsx +146 -0
- package/src/admin-shell/document-mutation-state.ts +95 -0
- package/src/admin-shell/scheduled-publications/list.tsx +16 -6
- package/src/admin-shell/singletons/history.test.tsx +3 -1
- package/src/admin-shell/singletons/history.tsx +10 -2
- package/src/admin-shell/singletons/view.test.tsx +59 -18
- package/src/admin-shell/singletons/view.tsx +110 -29
- package/src/integrations/byline-field-services.ts +2 -3
- package/src/routes/create-collection-edit-route.tsx +1 -0
- package/src/routes/create-collection-list-route.tsx +13 -2
- package/src/routes/create-singleton-route.test.node.ts +10 -2
- package/src/routes/create-singleton-route.tsx +6 -4
- package/src/server-fns/collections/copy-to-locale.ts +41 -36
- package/src/server-fns/collections/create.ts +54 -50
- package/src/server-fns/collections/delete-locale.ts +41 -32
- package/src/server-fns/collections/delete-outcome.test.node.ts +16 -0
- package/src/server-fns/collections/delete-outcome.ts +27 -16
- package/src/server-fns/collections/delete.ts +44 -38
- package/src/server-fns/collections/duplicate.ts +38 -32
- package/src/server-fns/collections/get.ts +8 -4
- package/src/server-fns/collections/list.ts +8 -3
- package/src/server-fns/collections/reorder.ts +32 -124
- package/src/server-fns/collections/restore-version.ts +47 -39
- package/src/server-fns/collections/revision-input.test.node.ts +108 -0
- package/src/server-fns/collections/save-outcome.test.node.ts +3 -0
- package/src/server-fns/collections/save-outcome.ts +2 -0
- package/src/server-fns/collections/scheduled-publication.ts +138 -111
- package/src/server-fns/collections/status.ts +86 -64
- package/src/server-fns/collections/tree-mutation.test.node.ts +87 -29
- package/src/server-fns/collections/tree-mutation.ts +28 -11
- package/src/server-fns/collections/tree.ts +150 -122
- package/src/server-fns/collections/update.ts +110 -86
- package/src/server-fns/collections/upload-singleton.test.node.ts +3 -7
- package/src/server-fns/collections/upload.ts +81 -77
- package/src/server-fns/document-mutation-errors.ts +67 -0
- package/src/server-fns/document-mutation-transport.test.node.ts +211 -0
- package/src/server-fns/editable-revision.test.node.ts +23 -0
- package/src/server-fns/editable-revision.ts +18 -0
- package/src/server-fns/singleton-document-read.ts +7 -3
- package/src/server-fns/singletons/cancel-scheduled-publish.ts +10 -3
- package/src/server-fns/singletons/change-status.ts +10 -3
- package/src/server-fns/singletons/confirm-scheduled-publish.ts +12 -6
- package/src/server-fns/singletons/copy-to-locale.ts +20 -15
- package/src/server-fns/singletons/get.ts +3 -3
- package/src/server-fns/singletons/restore-version.ts +17 -12
- package/src/server-fns/singletons/schedule-publish.ts +18 -7
- package/src/server-fns/singletons/singletons.test.node.ts +63 -25
- package/src/server-fns/singletons/unpublish.ts +10 -3
- package/src/server-fns/singletons/update.ts +21 -16
- package/src/server-fns/structural-receipt.ts +41 -0
|
@@ -6,7 +6,12 @@
|
|
|
6
6
|
* Copyright (c) Infonomic Company Limited
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
ERR_DOCUMENT_HOOK_COMMITTED,
|
|
11
|
+
ERR_LOCK_CONFLICT,
|
|
12
|
+
ErrorCodes,
|
|
13
|
+
getLockConflictDetails,
|
|
14
|
+
} from '@byline/core'
|
|
10
15
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
11
16
|
|
|
12
17
|
const mocks = vi.hoisted(() => ({
|
|
@@ -57,7 +62,7 @@ const invoke = (serverFunction: unknown, data: Record<string, any>) =>
|
|
|
57
62
|
(serverFunction as ServerFunction)({ data })
|
|
58
63
|
|
|
59
64
|
const handle = {
|
|
60
|
-
|
|
65
|
+
getForEdit: vi.fn(),
|
|
61
66
|
update: vi.fn(),
|
|
62
67
|
changeStatus: vi.fn(),
|
|
63
68
|
unpublish: vi.fn(),
|
|
@@ -84,14 +89,13 @@ describe('singleton server functions', () => {
|
|
|
84
89
|
const cases = [
|
|
85
90
|
{
|
|
86
91
|
serverFunction: getSingleton,
|
|
87
|
-
method: '
|
|
92
|
+
method: 'getForEdit',
|
|
88
93
|
input: { singleton: 'site-settings', locale: 'fr' },
|
|
89
94
|
args: [
|
|
90
95
|
{
|
|
91
96
|
locale: 'fr',
|
|
92
97
|
populate: undefined,
|
|
93
98
|
depth: undefined,
|
|
94
|
-
status: 'any',
|
|
95
99
|
onMissingLocale: 'empty',
|
|
96
100
|
lenient: true,
|
|
97
101
|
},
|
|
@@ -105,23 +109,23 @@ describe('singleton server functions', () => {
|
|
|
105
109
|
singleton: 'site-settings',
|
|
106
110
|
data: { title: 'Changed' },
|
|
107
111
|
locale: 'fr',
|
|
108
|
-
|
|
112
|
+
expectedRevision: 7,
|
|
109
113
|
},
|
|
110
|
-
args: [{ title: 'Changed' }, { locale: 'fr',
|
|
114
|
+
args: [{ title: 'Changed' }, { locale: 'fr', expectedRevision: 7 }],
|
|
111
115
|
result: { versionId: 'version-2' },
|
|
112
116
|
},
|
|
113
117
|
{
|
|
114
118
|
serverFunction: changeSingletonStatus,
|
|
115
119
|
method: 'changeStatus',
|
|
116
|
-
input: { singleton: 'site-settings', status: 'published' },
|
|
117
|
-
args: ['published'],
|
|
120
|
+
input: { singleton: 'site-settings', status: 'published', expectedRevision: 7 },
|
|
121
|
+
args: ['published', { expectedRevision: 7 }],
|
|
118
122
|
result: { newStatus: 'published' },
|
|
119
123
|
},
|
|
120
124
|
{
|
|
121
125
|
serverFunction: unpublishSingleton,
|
|
122
126
|
method: 'unpublish',
|
|
123
|
-
input: { singleton: 'site-settings' },
|
|
124
|
-
args: [],
|
|
127
|
+
input: { singleton: 'site-settings', expectedRevision: 7 },
|
|
128
|
+
args: [{ expectedRevision: 7 }],
|
|
125
129
|
result: { archivedCount: 1 },
|
|
126
130
|
},
|
|
127
131
|
{
|
|
@@ -130,11 +134,13 @@ describe('singleton server functions', () => {
|
|
|
130
134
|
input: {
|
|
131
135
|
singleton: 'site-settings',
|
|
132
136
|
publishAt: '2026-09-01T10:00:00Z',
|
|
137
|
+
expectedRevision: 7,
|
|
133
138
|
expectedVersionId: 'version-2',
|
|
134
139
|
},
|
|
135
140
|
args: [
|
|
136
141
|
{
|
|
137
142
|
publishAt: '2026-09-01T10:00:00Z',
|
|
143
|
+
expectedRevision: 7,
|
|
138
144
|
expectedVersionId: 'version-2',
|
|
139
145
|
},
|
|
140
146
|
],
|
|
@@ -143,15 +149,15 @@ describe('singleton server functions', () => {
|
|
|
143
149
|
{
|
|
144
150
|
serverFunction: confirmSingletonScheduledPublish,
|
|
145
151
|
method: 'confirmScheduledPublish',
|
|
146
|
-
input: { singleton: 'site-settings', expectedVersionId: 'version-3' },
|
|
147
|
-
args: [{ expectedVersionId: 'version-3' }],
|
|
152
|
+
input: { singleton: 'site-settings', expectedRevision: 7, expectedVersionId: 'version-3' },
|
|
153
|
+
args: [{ expectedRevision: 7, expectedVersionId: 'version-3' }],
|
|
148
154
|
result: { state: 'armed' },
|
|
149
155
|
},
|
|
150
156
|
{
|
|
151
157
|
serverFunction: cancelSingletonScheduledPublish,
|
|
152
158
|
method: 'cancelScheduledPublish',
|
|
153
|
-
input: { singleton: 'site-settings' },
|
|
154
|
-
args: [],
|
|
159
|
+
input: { singleton: 'site-settings', expectedRevision: 7 },
|
|
160
|
+
args: [{ expectedRevision: 7 }],
|
|
155
161
|
result: { state: 'cancelled' },
|
|
156
162
|
},
|
|
157
163
|
{
|
|
@@ -185,8 +191,8 @@ describe('singleton server functions', () => {
|
|
|
185
191
|
{
|
|
186
192
|
serverFunction: restoreSingletonVersion,
|
|
187
193
|
method: 'restoreVersion',
|
|
188
|
-
input: { singleton: 'site-settings', versionId: 'version-1' },
|
|
189
|
-
args: ['version-1'],
|
|
194
|
+
input: { singleton: 'site-settings', versionId: 'version-1', expectedRevision: 7 },
|
|
195
|
+
args: ['version-1', { expectedRevision: 7 }],
|
|
190
196
|
result: { versionId: 'version-4' },
|
|
191
197
|
},
|
|
192
198
|
{
|
|
@@ -194,18 +200,23 @@ describe('singleton server functions', () => {
|
|
|
194
200
|
method: 'copyToLocale',
|
|
195
201
|
input: {
|
|
196
202
|
singleton: 'site-settings',
|
|
203
|
+
expectedRevision: 7,
|
|
197
204
|
sourceLocale: 'en',
|
|
198
205
|
targetLocale: 'fr',
|
|
199
206
|
overwrite: true,
|
|
200
207
|
},
|
|
201
|
-
args: [{ sourceLocale: 'en', targetLocale: 'fr', overwrite: true }],
|
|
208
|
+
args: [{ expectedRevision: 7, sourceLocale: 'en', targetLocale: 'fr', overwrite: true }],
|
|
202
209
|
result: { versionId: 'version-5' },
|
|
203
210
|
},
|
|
204
211
|
] as const
|
|
205
212
|
|
|
206
213
|
for (const testCase of cases) {
|
|
207
214
|
const method = handle[testCase.method]
|
|
208
|
-
method.mockResolvedValueOnce(
|
|
215
|
+
method.mockResolvedValueOnce(
|
|
216
|
+
testCase.method === 'getForEdit'
|
|
217
|
+
? { state: 'document', document: testCase.result }
|
|
218
|
+
: testCase.result
|
|
219
|
+
)
|
|
209
220
|
|
|
210
221
|
const result = await invoke(testCase.serverFunction, testCase.input)
|
|
211
222
|
|
|
@@ -219,18 +230,18 @@ describe('singleton server functions', () => {
|
|
|
219
230
|
}
|
|
220
231
|
})
|
|
221
232
|
|
|
222
|
-
it('forwards the
|
|
233
|
+
it('forwards the observed revision to update unchanged', async () => {
|
|
223
234
|
handle.update.mockResolvedValueOnce({ versionId: 'version-next' })
|
|
224
235
|
|
|
225
236
|
await invoke(updateSingleton, {
|
|
226
237
|
singleton: 'site-settings',
|
|
227
238
|
data: { title: 'Changed' },
|
|
228
|
-
|
|
239
|
+
expectedRevision: 7,
|
|
229
240
|
})
|
|
230
241
|
|
|
231
242
|
expect(handle.update).toHaveBeenCalledWith(
|
|
232
243
|
{ title: 'Changed' },
|
|
233
|
-
{ locale: undefined,
|
|
244
|
+
{ locale: undefined, expectedRevision: 7 }
|
|
234
245
|
)
|
|
235
246
|
})
|
|
236
247
|
|
|
@@ -254,6 +265,7 @@ describe('singleton server functions', () => {
|
|
|
254
265
|
phase: 'afterSave',
|
|
255
266
|
documentId: 'doc-settings',
|
|
256
267
|
documentVersionId: 'version-next',
|
|
268
|
+
revision: 8,
|
|
257
269
|
sideEffectCode: ErrorCodes.UNHANDLED,
|
|
258
270
|
},
|
|
259
271
|
})
|
|
@@ -263,13 +275,14 @@ describe('singleton server functions', () => {
|
|
|
263
275
|
status: 'committed-hook-failed',
|
|
264
276
|
documentId: 'doc-settings',
|
|
265
277
|
documentVersionId: 'version-next',
|
|
278
|
+
revision: 8,
|
|
266
279
|
sideEffectFailure: { phase: 'afterSave', code: ErrorCodes.UNHANDLED },
|
|
267
280
|
})
|
|
268
281
|
})
|
|
269
282
|
|
|
270
283
|
it('preserves authentication failures from the handle', async () => {
|
|
271
284
|
const error = { code: 'ERR_UNAUTHENTICATED', message: 'sign in required' }
|
|
272
|
-
handle.
|
|
285
|
+
handle.getForEdit.mockRejectedValueOnce(error)
|
|
273
286
|
|
|
274
287
|
await expect(invoke(getSingleton, { singleton: 'site-settings' })).rejects.toBe(error)
|
|
275
288
|
})
|
|
@@ -301,9 +314,34 @@ describe('singleton server functions', () => {
|
|
|
301
314
|
expect(mocks.resolveActorLabels).toHaveBeenCalledWith([])
|
|
302
315
|
})
|
|
303
316
|
|
|
317
|
+
it('preserves confirmed lock failures as safe wire data through the host', async () => {
|
|
318
|
+
const conflict = ERR_LOCK_CONFLICT({
|
|
319
|
+
message: 'private diagnostic',
|
|
320
|
+
cause: new Error('driver SQL'),
|
|
321
|
+
})
|
|
322
|
+
handle.update.mockRejectedValueOnce(conflict)
|
|
323
|
+
let received: unknown
|
|
324
|
+
try {
|
|
325
|
+
await invoke(updateSingleton, {
|
|
326
|
+
singleton: 'site-settings',
|
|
327
|
+
data: { title: 'Changed' },
|
|
328
|
+
expectedRevision: 6,
|
|
329
|
+
})
|
|
330
|
+
} catch (error) {
|
|
331
|
+
received = error
|
|
332
|
+
}
|
|
333
|
+
expect(received).not.toHaveProperty('cause')
|
|
334
|
+
expect(getLockConflictDetails(JSON.parse(JSON.stringify(received)))).toEqual({
|
|
335
|
+
reason: 'lock_conflict',
|
|
336
|
+
rolledBack: true,
|
|
337
|
+
retryable: true,
|
|
338
|
+
})
|
|
339
|
+
expect(handle.update).toHaveBeenCalledTimes(1)
|
|
340
|
+
})
|
|
341
|
+
|
|
304
342
|
it('keeps missing-slot and stale-write failures distinguishable', async () => {
|
|
305
343
|
const missing = { code: 'ERR_NOT_FOUND', message: 'slot is empty' }
|
|
306
|
-
const stale = { code: '
|
|
344
|
+
const stale = { code: 'ERR_DOCUMENT_STALE', message: 'document changed' }
|
|
307
345
|
handle.changeStatus.mockRejectedValueOnce(missing)
|
|
308
346
|
handle.update.mockRejectedValueOnce(stale)
|
|
309
347
|
|
|
@@ -314,9 +352,9 @@ describe('singleton server functions', () => {
|
|
|
314
352
|
invoke(updateSingleton, {
|
|
315
353
|
singleton: 'site-settings',
|
|
316
354
|
data: { title: 'Changed' },
|
|
317
|
-
|
|
355
|
+
expectedRevision: 6,
|
|
318
356
|
})
|
|
319
|
-
).rejects.toMatchObject({ code: '
|
|
357
|
+
).rejects.toMatchObject({ code: 'ERR_DOCUMENT_STALE' })
|
|
320
358
|
})
|
|
321
359
|
|
|
322
360
|
it('serialises schedule dates at the transport boundary', async () => {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { withDocumentMutationErrors } from '../document-mutation-errors.js'
|
|
1
2
|
/**
|
|
2
3
|
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
4
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
@@ -13,7 +14,13 @@ import { getAdminBylineClient } from '@byline/client/server'
|
|
|
13
14
|
import { serialise } from '../serialise.js'
|
|
14
15
|
|
|
15
16
|
export const unpublishSingleton = createServerFn({ method: 'POST' })
|
|
16
|
-
.validator((input: { singleton: string }) => input)
|
|
17
|
-
.handler(
|
|
18
|
-
|
|
17
|
+
.validator((input: { expectedRevision: number; singleton: string }) => input)
|
|
18
|
+
.handler(
|
|
19
|
+
withDocumentMutationErrors(async ({ data }) =>
|
|
20
|
+
serialise(
|
|
21
|
+
await getAdminBylineClient()
|
|
22
|
+
.singleton(data.singleton)
|
|
23
|
+
.unpublish({ expectedRevision: data.expectedRevision })
|
|
24
|
+
)
|
|
25
|
+
)
|
|
19
26
|
)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { withDocumentMutationErrors } from '../document-mutation-errors.js'
|
|
1
2
|
/**
|
|
2
3
|
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
4
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
@@ -9,30 +10,34 @@
|
|
|
9
10
|
import { createServerFn } from '@tanstack/react-start'
|
|
10
11
|
|
|
11
12
|
import { getAdminBylineClient } from '@byline/client/server'
|
|
13
|
+
import type { SingletonSavePrecondition } from '@byline/core'
|
|
12
14
|
|
|
13
15
|
import { toCommittedDocumentHookFailureResponse } from '../collections/save-outcome.js'
|
|
14
16
|
import { serialise } from '../serialise.js'
|
|
15
17
|
|
|
16
|
-
export
|
|
18
|
+
export type UpdateSingletonInput = SingletonSavePrecondition & {
|
|
17
19
|
singleton: string
|
|
18
20
|
data: Record<string, any>
|
|
19
21
|
locale?: string
|
|
20
|
-
expectedVersionId?: string
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
export const updateSingleton = createServerFn({ method: 'POST' })
|
|
24
25
|
.validator((input: UpdateSingletonInput) => input)
|
|
25
|
-
.handler(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
26
|
+
.handler(
|
|
27
|
+
withDocumentMutationErrors(async ({ data }) => {
|
|
28
|
+
const { singleton, data: fields, locale, ...precondition } = data
|
|
29
|
+
try {
|
|
30
|
+
const result = await getAdminBylineClient()
|
|
31
|
+
.singleton(singleton)
|
|
32
|
+
.update(fields, {
|
|
33
|
+
locale,
|
|
34
|
+
...precondition,
|
|
35
|
+
})
|
|
36
|
+
return serialise(result)
|
|
37
|
+
} catch (error) {
|
|
38
|
+
const committedFailure = toCommittedDocumentHookFailureResponse(error)
|
|
39
|
+
if (committedFailure != null) return committedFailure
|
|
40
|
+
throw error
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ErrorCodes, isDocumentRevision, type StructuralMutationReceipt } from '@byline/core'
|
|
2
|
+
|
|
3
|
+
/** Copy only the authorized receipt fields emitted by the lifecycle service. */
|
|
4
|
+
export function structuralReceipt(value: unknown): StructuralMutationReceipt | null {
|
|
5
|
+
if (typeof value !== 'object' || value === null) return null
|
|
6
|
+
const documentId = Reflect.get(value, 'documentId')
|
|
7
|
+
const revision = Reflect.get(value, 'revision')
|
|
8
|
+
const suspended = Reflect.get(value, 'scheduledPublicationsNeedReconfirmation')
|
|
9
|
+
const affected = Reflect.get(value, 'affectedDocuments')
|
|
10
|
+
if (
|
|
11
|
+
typeof documentId !== 'string' ||
|
|
12
|
+
!isDocumentRevision(revision) ||
|
|
13
|
+
typeof suspended !== 'boolean' ||
|
|
14
|
+
!Array.isArray(affected)
|
|
15
|
+
)
|
|
16
|
+
return null
|
|
17
|
+
const affectedDocuments = []
|
|
18
|
+
for (const row of affected) {
|
|
19
|
+
if (typeof row !== 'object' || row === null) return null
|
|
20
|
+
const id = Reflect.get(row, 'documentId')
|
|
21
|
+
const token = Reflect.get(row, 'revision')
|
|
22
|
+
if (typeof id !== 'string' || !isDocumentRevision(token)) return null
|
|
23
|
+
affectedDocuments.push({ documentId: id, revision: token })
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
documentId,
|
|
27
|
+
revision,
|
|
28
|
+
affectedDocuments,
|
|
29
|
+
scheduledPublicationsNeedReconfirmation: suspended,
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function committedTreeReceipt(error: unknown): StructuralMutationReceipt | null {
|
|
34
|
+
if (
|
|
35
|
+
typeof error !== 'object' ||
|
|
36
|
+
error === null ||
|
|
37
|
+
Reflect.get(error, 'code') !== ErrorCodes.TREE_HOOK_COMMITTED
|
|
38
|
+
)
|
|
39
|
+
return null
|
|
40
|
+
return structuralReceipt(Reflect.get(error, 'details'))
|
|
41
|
+
}
|