@byline/host-tanstack-start 4.19.0 → 5.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.
- package/dist/admin-shell/chrome/admin-app-bar.d.ts +7 -0
- package/dist/admin-shell/chrome/admin-app-bar.js +10 -2
- package/dist/admin-shell/chrome/session-change-boundary.d.ts +14 -0
- package/dist/admin-shell/chrome/session-change-boundary.js +87 -0
- package/dist/admin-shell/chrome/session-change-boundary.test.d.ts +8 -0
- package/dist/admin-shell/chrome/sign-in-page.d.ts +2 -1
- package/dist/admin-shell/chrome/sign-in-page.js +60 -3
- 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-admin-services.js +7 -1
- package/dist/integrations/byline-field-services.js +2 -9
- package/dist/integrations/client-ip.d.ts +19 -0
- package/dist/integrations/client-ip.js +34 -0
- package/dist/integrations/session-coordination.d.ts +24 -0
- package/dist/integrations/session-coordination.js +85 -0
- package/dist/integrations/session-middleware.d.ts +11 -0
- package/dist/integrations/session-middleware.js +94 -0
- package/dist/integrations/session-request-kind.d.ts +9 -0
- package/dist/integrations/session-request-kind.js +10 -0
- package/dist/integrations/session-request-middleware.d.ts +9 -0
- package/dist/integrations/session-request-middleware.js +7 -0
- package/dist/integrations/sign-in-body.d.ts +12 -0
- package/dist/integrations/sign-in-body.js +52 -0
- package/dist/integrations/sign-in-middleware.d.ts +9 -0
- package/dist/integrations/sign-in-middleware.js +10 -0
- package/dist/routes/create-admin-layout-route.js +46 -31
- 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-sign-in-route.js +4 -2
- package/dist/routes/create-singleton-route.d.ts +2 -0
- package/dist/routes/create-singleton-route.js +4 -3
- package/dist/server-fns/admin-account/change-password.d.ts +3 -1
- package/dist/server-fns/admin-account/change-password.js +9 -3
- package/dist/server-fns/admin-account/get.d.ts +3 -1
- package/dist/server-fns/admin-account/get.js +4 -1
- package/dist/server-fns/admin-account/index.d.ts +5 -5
- package/dist/server-fns/admin-account/update.d.ts +3 -1
- package/dist/server-fns/admin-account/update.js +4 -1
- package/dist/server-fns/admin-activity/get.d.ts +3 -1
- package/dist/server-fns/admin-activity/get.js +4 -1
- package/dist/server-fns/admin-permissions/get-role-abilities.d.ts +3 -1
- package/dist/server-fns/admin-permissions/get-role-abilities.js +4 -1
- package/dist/server-fns/admin-permissions/index.d.ts +4 -4
- package/dist/server-fns/admin-permissions/list-registered.d.ts +3 -1
- package/dist/server-fns/admin-permissions/list-registered.js +4 -1
- package/dist/server-fns/admin-permissions/set-role-abilities.d.ts +3 -1
- package/dist/server-fns/admin-permissions/set-role-abilities.js +4 -1
- package/dist/server-fns/admin-permissions/who-has.d.ts +3 -1
- package/dist/server-fns/admin-permissions/who-has.js +4 -1
- package/dist/server-fns/admin-roles/create.d.ts +3 -1
- package/dist/server-fns/admin-roles/create.js +4 -1
- package/dist/server-fns/admin-roles/delete.d.ts +3 -1
- package/dist/server-fns/admin-roles/delete.js +4 -1
- package/dist/server-fns/admin-roles/get.d.ts +3 -1
- package/dist/server-fns/admin-roles/get.js +4 -1
- package/dist/server-fns/admin-roles/index.d.ts +6 -6
- package/dist/server-fns/admin-roles/list.d.ts +3 -1
- package/dist/server-fns/admin-roles/list.js +4 -1
- package/dist/server-fns/admin-roles/reorder.d.ts +3 -1
- package/dist/server-fns/admin-roles/reorder.js +4 -1
- package/dist/server-fns/admin-roles/update.d.ts +3 -1
- package/dist/server-fns/admin-roles/update.js +4 -1
- package/dist/server-fns/admin-users/create.d.ts +3 -1
- package/dist/server-fns/admin-users/create.js +4 -1
- package/dist/server-fns/admin-users/delete.d.ts +3 -1
- package/dist/server-fns/admin-users/delete.js +4 -1
- package/dist/server-fns/admin-users/disable.d.ts +3 -1
- package/dist/server-fns/admin-users/disable.js +4 -1
- package/dist/server-fns/admin-users/enable.d.ts +3 -1
- package/dist/server-fns/admin-users/enable.js +4 -1
- package/dist/server-fns/admin-users/get-user-roles.d.ts +3 -1
- package/dist/server-fns/admin-users/get-user-roles.js +4 -1
- package/dist/server-fns/admin-users/get.d.ts +3 -1
- package/dist/server-fns/admin-users/get.js +4 -1
- package/dist/server-fns/admin-users/index.d.ts +10 -10
- package/dist/server-fns/admin-users/list.d.ts +3 -1
- package/dist/server-fns/admin-users/list.js +4 -1
- package/dist/server-fns/admin-users/set-password.d.ts +3 -1
- package/dist/server-fns/admin-users/set-password.js +4 -1
- package/dist/server-fns/admin-users/set-user-roles.d.ts +3 -1
- package/dist/server-fns/admin-users/set-user-roles.js +4 -1
- package/dist/server-fns/admin-users/update.d.ts +3 -1
- package/dist/server-fns/admin-users/update.js +4 -1
- package/dist/server-fns/ai/execute.d.ts +3 -1
- package/dist/server-fns/ai/execute.js +4 -1
- package/dist/server-fns/ai/index.d.ts +1 -1
- package/dist/server-fns/analytics/maintenance.d.ts +6 -2
- package/dist/server-fns/analytics/maintenance.js +7 -2
- package/dist/server-fns/analytics/queries.d.ts +18 -6
- package/dist/server-fns/analytics/queries.js +19 -6
- package/dist/server-fns/auth/current-user.d.ts +1 -0
- package/dist/server-fns/auth/current-user.js +5 -2
- package/dist/server-fns/auth/renew.d.ts +13 -0
- package/dist/server-fns/auth/renew.js +45 -0
- package/dist/server-fns/auth/sign-in.d.ts +2 -1
- package/dist/server-fns/auth/sign-in.js +88 -17
- package/dist/server-fns/auth/sign-out.d.ts +3 -1
- package/dist/server-fns/auth/sign-out.js +38 -6
- package/dist/server-fns/collections/audit.d.ts +3 -1
- package/dist/server-fns/collections/audit.js +4 -1
- package/dist/server-fns/collections/copy-to-locale.d.ts +5 -1
- package/dist/server-fns/collections/copy-to-locale.js +7 -2
- package/dist/server-fns/collections/create.d.ts +4 -1
- package/dist/server-fns/collections/create.js +8 -3
- package/dist/server-fns/collections/delete-locale.d.ts +5 -1
- package/dist/server-fns/collections/delete-locale.js +7 -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 +5 -1
- package/dist/server-fns/collections/delete.js +8 -3
- package/dist/server-fns/collections/duplicate.d.ts +5 -1
- package/dist/server-fns/collections/duplicate.js +8 -3
- package/dist/server-fns/collections/get.d.ts +1 -0
- package/dist/server-fns/collections/get.js +12 -6
- package/dist/server-fns/collections/history.d.ts +3 -1
- package/dist/server-fns/collections/history.js +4 -1
- package/dist/server-fns/collections/index.d.ts +21 -21
- package/dist/server-fns/collections/list.d.ts +3 -1
- package/dist/server-fns/collections/list.js +15 -4
- package/dist/server-fns/collections/reindex.d.ts +3 -1
- package/dist/server-fns/collections/reindex.js +4 -1
- package/dist/server-fns/collections/reorder.d.ts +10 -2
- package/dist/server-fns/collections/reorder.js +23 -76
- package/dist/server-fns/collections/restore-version.d.ts +6 -1
- package/dist/server-fns/collections/restore-version.js +8 -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 +64 -7
- package/dist/server-fns/collections/scheduled-publication.js +42 -21
- package/dist/server-fns/collections/set-list-view-preference.d.ts +3 -1
- package/dist/server-fns/collections/set-list-view-preference.js +4 -1
- package/dist/server-fns/collections/stats.js +4 -1
- package/dist/server-fns/collections/status.d.ts +14 -2
- package/dist/server-fns/collections/status.js +18 -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 +29 -6
- package/dist/server-fns/collections/tree.js +32 -17
- package/dist/server-fns/collections/update.d.ts +18 -6
- package/dist/server-fns/collections/update.js +39 -20
- package/dist/server-fns/collections/upload.d.ts +11 -1
- package/dist/server-fns/collections/upload.js +6 -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/i18n/set-locale.d.ts +3 -1
- package/dist/server-fns/i18n/set-locale.js +18 -3
- package/dist/server-fns/preview/disable.d.ts +3 -1
- package/dist/server-fns/preview/disable.js +4 -1
- package/dist/server-fns/preview/enable.d.ts +3 -1
- package/dist/server-fns/preview/enable.js +4 -1
- 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 +9 -2
- package/dist/server-fns/singletons/cancel-scheduled-publish.js +7 -1
- package/dist/server-fns/singletons/change-status.d.ts +5 -1
- package/dist/server-fns/singletons/change-status.js +7 -1
- package/dist/server-fns/singletons/confirm-scheduled-publish.d.ts +8 -2
- package/dist/server-fns/singletons/confirm-scheduled-publish.js +7 -2
- package/dist/server-fns/singletons/copy-to-locale.d.ts +5 -1
- package/dist/server-fns/singletons/copy-to-locale.js +7 -2
- package/dist/server-fns/singletons/find-by-version.d.ts +3 -1
- package/dist/server-fns/singletons/find-by-version.js +4 -1
- package/dist/server-fns/singletons/get-scheduled-publish.d.ts +3 -1
- package/dist/server-fns/singletons/get-scheduled-publish.js +4 -1
- package/dist/server-fns/singletons/get.d.ts +6 -4
- package/dist/server-fns/singletons/get.js +4 -1
- package/dist/server-fns/singletons/history.d.ts +3 -1
- package/dist/server-fns/singletons/history.js +4 -1
- package/dist/server-fns/singletons/restore-version.d.ts +5 -1
- package/dist/server-fns/singletons/restore-version.js +9 -3
- package/dist/server-fns/singletons/schedule-publish.d.ts +8 -2
- package/dist/server-fns/singletons/schedule-publish.js +7 -2
- package/dist/server-fns/singletons/unpublish.d.ts +5 -1
- package/dist/server-fns/singletons/unpublish.js +7 -1
- package/dist/server-fns/singletons/update.d.ts +6 -4
- package/dist/server-fns/singletons/update.js +8 -4
- package/dist/server-fns/structural-receipt.d.ts +4 -0
- package/dist/server-fns/structural-receipt.js +31 -0
- package/package.json +20 -20
- package/src/admin-shell/chrome/admin-app-bar.tsx +11 -6
- package/src/admin-shell/chrome/session-change-boundary.test.tsx +78 -0
- package/src/admin-shell/chrome/session-change-boundary.tsx +94 -0
- package/src/admin-shell/chrome/sign-in-page.tsx +68 -3
- 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-admin-services.ts +7 -1
- package/src/integrations/byline-field-services.ts +2 -3
- package/src/integrations/client-ip.test.node.ts +45 -0
- package/src/integrations/client-ip.ts +54 -0
- package/src/integrations/framework-fetch-shape.test.node.ts +56 -0
- package/src/integrations/session-client.test.node.ts +121 -0
- package/src/integrations/session-coordination.test.node.ts +77 -0
- package/src/integrations/session-coordination.ts +96 -0
- package/src/integrations/session-middleware.test.node.ts +87 -0
- package/src/integrations/session-middleware.ts +107 -0
- package/src/integrations/session-request-kind.ts +18 -0
- package/src/integrations/session-request-middleware.ts +17 -0
- package/src/integrations/sign-in-body.test.node.ts +59 -0
- package/src/integrations/sign-in-body.ts +50 -0
- package/src/integrations/sign-in-middleware.ts +24 -0
- package/src/routes/create-admin-layout-route.tsx +48 -30
- package/src/routes/create-collection-edit-route.tsx +1 -0
- package/src/routes/create-collection-list-route.tsx +13 -2
- package/src/routes/create-sign-in-route.tsx +10 -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/admin-account/change-password.test.node.ts +69 -0
- package/src/server-fns/admin-account/change-password.ts +13 -2
- package/src/server-fns/admin-account/get.ts +2 -0
- package/src/server-fns/admin-account/update.ts +2 -0
- package/src/server-fns/admin-activity/get.ts +2 -0
- package/src/server-fns/admin-permissions/get-role-abilities.ts +2 -0
- package/src/server-fns/admin-permissions/list-registered.ts +5 -4
- package/src/server-fns/admin-permissions/set-role-abilities.ts +2 -0
- package/src/server-fns/admin-permissions/who-has.ts +2 -0
- package/src/server-fns/admin-roles/create.ts +2 -0
- package/src/server-fns/admin-roles/delete.ts +2 -0
- package/src/server-fns/admin-roles/get.ts +2 -0
- package/src/server-fns/admin-roles/list.ts +5 -4
- package/src/server-fns/admin-roles/reorder.ts +2 -0
- package/src/server-fns/admin-roles/update.ts +2 -0
- package/src/server-fns/admin-users/create.ts +2 -0
- package/src/server-fns/admin-users/delete.ts +2 -0
- package/src/server-fns/admin-users/disable.ts +2 -0
- package/src/server-fns/admin-users/enable.ts +2 -0
- package/src/server-fns/admin-users/get-user-roles.ts +2 -0
- package/src/server-fns/admin-users/get.ts +2 -0
- package/src/server-fns/admin-users/list.ts +2 -0
- package/src/server-fns/admin-users/set-password.ts +2 -0
- package/src/server-fns/admin-users/set-user-roles.ts +2 -0
- package/src/server-fns/admin-users/update.ts +2 -0
- package/src/server-fns/ai/execute.ts +3 -0
- package/src/server-fns/analytics/maintenance.ts +4 -0
- package/src/server-fns/analytics/queries.ts +14 -8
- package/src/server-fns/auth/current-user.ts +7 -3
- package/src/server-fns/auth/renew.test.node.ts +85 -0
- package/src/server-fns/auth/renew.ts +54 -0
- package/src/server-fns/auth/sign-in.test.node.ts +114 -0
- package/src/server-fns/auth/sign-in.ts +80 -27
- package/src/server-fns/auth/sign-out.test.node.ts +85 -0
- package/src/server-fns/auth/sign-out.ts +44 -19
- package/src/server-fns/collections/audit.ts +2 -0
- package/src/server-fns/collections/copy-to-locale.ts +43 -36
- package/src/server-fns/collections/create.ts +56 -50
- package/src/server-fns/collections/delete-locale.ts +43 -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 +46 -38
- package/src/server-fns/collections/duplicate.ts +40 -32
- package/src/server-fns/collections/get.ts +11 -4
- package/src/server-fns/collections/history.ts +2 -0
- package/src/server-fns/collections/list.ts +10 -3
- package/src/server-fns/collections/reindex.ts +2 -0
- package/src/server-fns/collections/reorder.ts +34 -124
- package/src/server-fns/collections/restore-version.ts +49 -39
- package/src/server-fns/collections/revision-input.test.node.ts +122 -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 +149 -115
- package/src/server-fns/collections/set-list-view-preference.ts +2 -0
- package/src/server-fns/collections/stats.ts +2 -0
- package/src/server-fns/collections/status.ts +89 -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 +156 -122
- package/src/server-fns/collections/update.ts +113 -86
- package/src/server-fns/collections/upload-singleton.test.node.ts +10 -7
- package/src/server-fns/collections/upload.ts +91 -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/i18n/set-locale.ts +19 -3
- package/src/server-fns/preview/disable.ts +8 -4
- package/src/server-fns/preview/enable.ts +9 -5
- package/src/server-fns/singleton-document-read.ts +7 -3
- package/src/server-fns/singletons/cancel-scheduled-publish.ts +12 -3
- package/src/server-fns/singletons/change-status.ts +12 -3
- package/src/server-fns/singletons/confirm-scheduled-publish.ts +14 -6
- package/src/server-fns/singletons/copy-to-locale.ts +22 -15
- package/src/server-fns/singletons/find-by-version.ts +2 -0
- package/src/server-fns/singletons/get-scheduled-publish.ts +2 -0
- package/src/server-fns/singletons/get.ts +5 -3
- package/src/server-fns/singletons/history.ts +2 -0
- package/src/server-fns/singletons/restore-version.ts +19 -12
- package/src/server-fns/singletons/schedule-publish.ts +20 -7
- package/src/server-fns/singletons/singletons.test.node.ts +69 -25
- package/src/server-fns/singletons/unpublish.ts +12 -3
- package/src/server-fns/singletons/update.ts +23 -16
- package/src/server-fns/structural-receipt.ts +41 -0
|
@@ -16,6 +16,10 @@ describe('delete outcome transport and admin interpretation', () => {
|
|
|
16
16
|
// Simulate malformed runtime data from an older or compromised source. The
|
|
17
17
|
// core type rejects this shape, but the transport still sanitizes it.
|
|
18
18
|
const unsafeResult = {
|
|
19
|
+
documentId: 'doc-1',
|
|
20
|
+
revision: 2,
|
|
21
|
+
affectedDocuments: [{ documentId: 'child', revision: 3 }],
|
|
22
|
+
scheduledPublicationsNeedReconfirmation: true,
|
|
19
23
|
deletedVersionCount: 2,
|
|
20
24
|
outcome: 'committed-with-side-effect-failures',
|
|
21
25
|
sideEffectFailures: [
|
|
@@ -36,6 +40,10 @@ describe('delete outcome transport and admin interpretation', () => {
|
|
|
36
40
|
|
|
37
41
|
expect(response).toEqual({
|
|
38
42
|
status: 'ok',
|
|
43
|
+
documentId: 'doc-1',
|
|
44
|
+
revision: 2,
|
|
45
|
+
affectedDocuments: [{ documentId: 'child', revision: 3 }],
|
|
46
|
+
scheduledPublicationsNeedReconfirmation: true,
|
|
39
47
|
deletedVersionCount: 2,
|
|
40
48
|
outcome: 'committed-with-side-effect-failures',
|
|
41
49
|
sideEffectFailures: [
|
|
@@ -53,6 +61,10 @@ describe('delete outcome transport and admin interpretation', () => {
|
|
|
53
61
|
|
|
54
62
|
it('preserves the committed success discriminant and empty failures', () => {
|
|
55
63
|
const response = toDeleteDocumentResponse({
|
|
64
|
+
documentId: 'doc-1',
|
|
65
|
+
revision: 2,
|
|
66
|
+
affectedDocuments: [{ documentId: 'child', revision: 3 }],
|
|
67
|
+
scheduledPublicationsNeedReconfirmation: true,
|
|
56
68
|
deletedVersionCount: 2,
|
|
57
69
|
outcome: 'committed',
|
|
58
70
|
sideEffectFailures: [],
|
|
@@ -60,6 +72,10 @@ describe('delete outcome transport and admin interpretation', () => {
|
|
|
60
72
|
|
|
61
73
|
expect(response).toEqual({
|
|
62
74
|
status: 'ok',
|
|
75
|
+
documentId: 'doc-1',
|
|
76
|
+
revision: 2,
|
|
77
|
+
affectedDocuments: [{ documentId: 'child', revision: 3 }],
|
|
78
|
+
scheduledPublicationsNeedReconfirmation: true,
|
|
63
79
|
deletedVersionCount: 2,
|
|
64
80
|
outcome: 'committed',
|
|
65
81
|
sideEffectFailures: [],
|
|
@@ -10,6 +10,7 @@ import type {
|
|
|
10
10
|
DeleteDocumentResult,
|
|
11
11
|
DeleteDocumentSideEffectCode,
|
|
12
12
|
DeleteDocumentSideEffectPhase,
|
|
13
|
+
StructuralMutationReceipt,
|
|
13
14
|
} from '@byline/core'
|
|
14
15
|
import { ErrorCodes } from '@byline/core'
|
|
15
16
|
|
|
@@ -21,22 +22,28 @@ export interface DeleteDocumentPublicSideEffectFailure {
|
|
|
21
22
|
code: DeleteDocumentPublicSideEffectCode
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
export type DeleteDocumentResponse =
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
25
|
+
export type DeleteDocumentResponse = StructuralMutationReceipt &
|
|
26
|
+
(
|
|
27
|
+
| {
|
|
28
|
+
status: 'ok'
|
|
29
|
+
documentId: string
|
|
30
|
+
revision: number
|
|
31
|
+
deletedVersionCount: number
|
|
32
|
+
outcome: 'committed'
|
|
33
|
+
sideEffectFailures: []
|
|
34
|
+
}
|
|
35
|
+
| {
|
|
36
|
+
status: 'ok'
|
|
37
|
+
documentId: string
|
|
38
|
+
revision: number
|
|
39
|
+
deletedVersionCount: number
|
|
40
|
+
outcome: 'committed-with-side-effect-failures'
|
|
41
|
+
sideEffectFailures: [
|
|
42
|
+
DeleteDocumentPublicSideEffectFailure,
|
|
43
|
+
...DeleteDocumentPublicSideEffectFailure[],
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
)
|
|
40
47
|
|
|
41
48
|
function sanitizePhase(phase: DeleteDocumentSideEffectPhase): DeleteDocumentPublicSideEffectPhase {
|
|
42
49
|
if (phase === 'afterTreeChange' || phase === 'afterDelete') {
|
|
@@ -67,6 +74,10 @@ export function toDeleteDocumentResponse(result: DeleteDocumentResult): DeleteDo
|
|
|
67
74
|
const [firstFailure, ...remainingFailures] = result.sideEffectFailures
|
|
68
75
|
return {
|
|
69
76
|
status: 'ok',
|
|
77
|
+
documentId: result.documentId,
|
|
78
|
+
revision: result.revision,
|
|
79
|
+
affectedDocuments: result.affectedDocuments,
|
|
80
|
+
scheduledPublicationsNeedReconfirmation: result.scheduledPublicationsNeedReconfirmation,
|
|
70
81
|
deletedVersionCount: result.deletedVersionCount,
|
|
71
82
|
outcome: result.outcome,
|
|
72
83
|
sideEffectFailures: [sanitizeFailure(firstFailure), ...remainingFailures.map(sanitizeFailure)],
|
|
@@ -14,6 +14,8 @@ import type { DocumentLifecycleContext } from '@byline/core/services'
|
|
|
14
14
|
import { deleteDocument as deleteDocumentService } from '@byline/core/services'
|
|
15
15
|
|
|
16
16
|
import { ensureCollection } from '../../integrations/api-utils.js'
|
|
17
|
+
import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
|
|
18
|
+
import { withDocumentMutationErrors } from '../document-mutation-errors.js'
|
|
17
19
|
import { toDeleteDocumentResponse } from './delete-outcome.js'
|
|
18
20
|
|
|
19
21
|
// ---------------------------------------------------------------------------
|
|
@@ -21,43 +23,49 @@ import { toDeleteDocumentResponse } from './delete-outcome.js'
|
|
|
21
23
|
// ---------------------------------------------------------------------------
|
|
22
24
|
|
|
23
25
|
export const deleteDocument = createServerFn({ method: 'POST' })
|
|
24
|
-
.
|
|
25
|
-
.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
.middleware([adminSessionMiddleware])
|
|
27
|
+
.validator((input: { expectedRevision: number; collection: string; id: string }) => input)
|
|
28
|
+
.handler(
|
|
29
|
+
withDocumentMutationErrors(async ({ data: input }) => {
|
|
30
|
+
const { collection: path, id } = input
|
|
31
|
+
const logger = getLogger()
|
|
32
|
+
const config = await ensureCollection(path)
|
|
33
|
+
if (!config) {
|
|
34
|
+
throw ERR_NOT_FOUND({
|
|
35
|
+
message: 'Collection not found',
|
|
36
|
+
details: { collectionPath: path },
|
|
37
|
+
}).log(logger)
|
|
38
|
+
}
|
|
35
39
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
40
|
+
const serverConfig = getServerConfig()
|
|
41
|
+
// Resolve the storage provider so the lifecycle service can clean up
|
|
42
|
+
// uploaded files and variants on deletion. With per-field upload
|
|
43
|
+
// config, a collection may have one (or more) image/file fields with
|
|
44
|
+
// their own storage. The delete path needs *a* provider; we pick the
|
|
45
|
+
// first upload-capable field's, falling back to the site-wide
|
|
46
|
+
// default. Multi-storage collections are out of scope today —
|
|
47
|
+
// deletion routes everything through one provider, which is fine
|
|
48
|
+
// when all upload fields target the same backend (the common case).
|
|
49
|
+
const firstUploadField = getUploadFields(config.definition)[0]
|
|
50
|
+
const storage = firstUploadField?.upload?.storage ?? serverConfig.storage
|
|
51
|
+
const db = serverConfig.db
|
|
52
|
+
const ctx: DocumentLifecycleContext = {
|
|
53
|
+
db,
|
|
54
|
+
definition: config.definition,
|
|
55
|
+
collectionId: config.collection.id,
|
|
56
|
+
collectionVersion: config.collection.version,
|
|
57
|
+
collectionPath: path,
|
|
58
|
+
...(storage ? { storage } : {}),
|
|
59
|
+
logger,
|
|
60
|
+
defaultLocale: serverConfig.i18n.content.defaultLocale,
|
|
61
|
+
slugifier: serverConfig.slugifier,
|
|
62
|
+
requestContext: await getAdminRequestContext(),
|
|
63
|
+
}
|
|
60
64
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
const result = await deleteDocumentService(ctx, {
|
|
66
|
+
documentId: id,
|
|
67
|
+
expectedRevision: input.expectedRevision,
|
|
68
|
+
})
|
|
69
|
+
return toDeleteDocumentResponse(result)
|
|
70
|
+
})
|
|
71
|
+
)
|
|
@@ -14,6 +14,8 @@ import type { DocumentLifecycleContext, DuplicateDocumentResult } from '@byline/
|
|
|
14
14
|
import { duplicateDocument } from '@byline/core/services'
|
|
15
15
|
|
|
16
16
|
import { ensureCollection } from '../../integrations/api-utils.js'
|
|
17
|
+
import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
|
|
18
|
+
import { withDocumentMutationErrors } from '../document-mutation-errors.js'
|
|
17
19
|
import {
|
|
18
20
|
type CollectionDocumentCommittedHookFailureResponse,
|
|
19
21
|
toCommittedDocumentHookFailureResponse,
|
|
@@ -35,40 +37,46 @@ import {
|
|
|
35
37
|
* TanStack Start's transport layer for the client to branch on.
|
|
36
38
|
*/
|
|
37
39
|
export const duplicateCollectionDocument = createServerFn({ method: 'POST' })
|
|
38
|
-
.
|
|
40
|
+
.middleware([adminSessionMiddleware])
|
|
41
|
+
.validator((input: { expectedRevision: number; collection: string; id: string }) => input)
|
|
39
42
|
.handler(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
43
|
+
withDocumentMutationErrors(
|
|
44
|
+
async ({
|
|
45
|
+
data: input,
|
|
46
|
+
}): Promise<DuplicateDocumentResult | CollectionDocumentCommittedHookFailureResponse> => {
|
|
47
|
+
const { collection: path, id: sourceDocumentId } = input
|
|
48
|
+
const logger = getLogger()
|
|
49
|
+
const config = await ensureCollection(path)
|
|
50
|
+
if (!config) {
|
|
51
|
+
throw ERR_NOT_FOUND({
|
|
52
|
+
message: 'Collection not found',
|
|
53
|
+
details: { collectionPath: path },
|
|
54
|
+
}).log(logger)
|
|
55
|
+
}
|
|
52
56
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
57
|
+
const serverConfig = getServerConfig()
|
|
58
|
+
const ctx: DocumentLifecycleContext = {
|
|
59
|
+
db: serverConfig.db,
|
|
60
|
+
definition: config.definition,
|
|
61
|
+
collectionId: config.collection.id,
|
|
62
|
+
collectionVersion: config.collection.version,
|
|
63
|
+
collectionPath: path,
|
|
64
|
+
logger,
|
|
65
|
+
defaultLocale: serverConfig.i18n.content.defaultLocale,
|
|
66
|
+
slugifier: serverConfig.slugifier,
|
|
67
|
+
requestContext: await getAdminRequestContext(),
|
|
68
|
+
}
|
|
65
69
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
try {
|
|
71
|
+
return await duplicateDocument(ctx, {
|
|
72
|
+
sourceDocumentId,
|
|
73
|
+
expectedRevision: input.expectedRevision,
|
|
74
|
+
})
|
|
75
|
+
} catch (error) {
|
|
76
|
+
const committedFailure = toCommittedDocumentHookFailureResponse(error)
|
|
77
|
+
if (committedFailure != null) return committedFailure
|
|
78
|
+
throw error
|
|
79
|
+
}
|
|
72
80
|
}
|
|
73
|
-
|
|
81
|
+
)
|
|
74
82
|
)
|
|
@@ -20,7 +20,9 @@ import {
|
|
|
20
20
|
} from '@byline/core'
|
|
21
21
|
|
|
22
22
|
import { ensureCollection } from '../../integrations/api-utils.js'
|
|
23
|
+
import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
|
|
23
24
|
import { resolveAdminDocumentRead } from '../admin-document-presentation.js'
|
|
25
|
+
import { withEditableRevision } from '../editable-revision.js'
|
|
24
26
|
import { serialise } from './utils'
|
|
25
27
|
|
|
26
28
|
// ---------------------------------------------------------------------------
|
|
@@ -28,6 +30,7 @@ import { serialise } from './utils'
|
|
|
28
30
|
// ---------------------------------------------------------------------------
|
|
29
31
|
|
|
30
32
|
const getDocumentFn = createServerFn({ method: 'GET' })
|
|
33
|
+
.middleware([adminSessionMiddleware])
|
|
31
34
|
.validator(
|
|
32
35
|
(input: {
|
|
33
36
|
collection: string
|
|
@@ -51,13 +54,16 @@ const getDocumentFn = createServerFn({ method: 'GET' })
|
|
|
51
54
|
const client = getAdminBylineClient()
|
|
52
55
|
const handle = client.collection(path)
|
|
53
56
|
|
|
54
|
-
const {
|
|
57
|
+
const {
|
|
58
|
+
options: { status: _status, ...readOptions },
|
|
59
|
+
populatedTree,
|
|
60
|
+
} = resolveAdminDocumentRead(config.definition, {
|
|
55
61
|
locale,
|
|
56
62
|
depth,
|
|
57
63
|
populateRelations,
|
|
58
64
|
})
|
|
59
65
|
|
|
60
|
-
const document = await handle.
|
|
66
|
+
const document = await handle.findByIdForEdit(id, {
|
|
61
67
|
...readOptions,
|
|
62
68
|
})
|
|
63
69
|
|
|
@@ -141,13 +147,13 @@ const getDocumentFn = createServerFn({ method: 'GET' })
|
|
|
141
147
|
actor?.hasAbility(documentAbilityKey(config.definition, 'changeStatus')) === true &&
|
|
142
148
|
actor.hasAbility(documentAbilityKey(config.definition, 'publish'))
|
|
143
149
|
if (canSchedulePublication) {
|
|
144
|
-
scheduledPublish =
|
|
150
|
+
scheduledPublish = document.scheduledPublication
|
|
145
151
|
}
|
|
146
152
|
}
|
|
147
153
|
const serializedSchedule = scheduledPublish == null ? null : serialise(scheduledPublish)
|
|
148
154
|
|
|
149
155
|
return {
|
|
150
|
-
...(parsed
|
|
156
|
+
...withEditableRevision(parsed, document),
|
|
151
157
|
_publishedVersion: publishedVersion,
|
|
152
158
|
...(restoreWarnings && restoreWarnings.length > 0
|
|
153
159
|
? { _restoreWarnings: restoreWarnings }
|
|
@@ -173,6 +179,7 @@ const getDocumentFn = createServerFn({ method: 'GET' })
|
|
|
173
179
|
// ---------------------------------------------------------------------------
|
|
174
180
|
|
|
175
181
|
const getDocumentByVersionFn = createServerFn({ method: 'GET' })
|
|
182
|
+
.middleware([adminSessionMiddleware])
|
|
176
183
|
.validator((input: { collection: string; versionId: string; locale?: string }) => input)
|
|
177
184
|
.handler(async ({ data }) => {
|
|
178
185
|
const { collection: path, versionId, locale } = data
|
|
@@ -12,6 +12,7 @@ import { getAdminBylineClient } from '@byline/client/server'
|
|
|
12
12
|
import { ERR_NOT_FOUND, getCollectionSchemasForPath, getLogger } from '@byline/core'
|
|
13
13
|
|
|
14
14
|
import { ensureCollection } from '../../integrations/api-utils.js'
|
|
15
|
+
import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
|
|
15
16
|
import { type ActorLabelMap, resolveActorLabels } from './actors.js'
|
|
16
17
|
import { serialise } from './utils'
|
|
17
18
|
|
|
@@ -32,6 +33,7 @@ export interface HistorySearchParams {
|
|
|
32
33
|
// ---------------------------------------------------------------------------
|
|
33
34
|
|
|
34
35
|
export const getCollectionDocumentHistory = createServerFn({ method: 'GET' })
|
|
36
|
+
.middleware([adminSessionMiddleware])
|
|
35
37
|
.validator((input: { collection: string; id: string; params: HistorySearchParams }) => input)
|
|
36
38
|
.handler(async ({ data }) => {
|
|
37
39
|
const { collection: path, id, params } = data
|
|
@@ -24,6 +24,8 @@ import {
|
|
|
24
24
|
|
|
25
25
|
import { ensureCollection } from '../../integrations/api-utils.js'
|
|
26
26
|
import { bylineCore } from '../../integrations/byline-core.js'
|
|
27
|
+
import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
|
|
28
|
+
import { withEditableRevision } from '../editable-revision.js'
|
|
27
29
|
import { resolveListViewState, sortableFieldNames } from './list-view-state.js'
|
|
28
30
|
import { serialise } from './utils'
|
|
29
31
|
import type { ListViewPreferenceValue } from './list-view-state.js'
|
|
@@ -48,6 +50,7 @@ export interface CollectionSearchParams {
|
|
|
48
50
|
// ---------------------------------------------------------------------------
|
|
49
51
|
|
|
50
52
|
export const getCollectionDocuments = createServerFn({ method: 'GET' })
|
|
53
|
+
.middleware([adminSessionMiddleware])
|
|
51
54
|
.validator((input: { collection: string; params: CollectionSearchParams }) => input)
|
|
52
55
|
.handler(async ({ data }) => {
|
|
53
56
|
const { collection: path, params } = data
|
|
@@ -131,7 +134,7 @@ export const getCollectionDocuments = createServerFn({ method: 'GET' })
|
|
|
131
134
|
const hasRelations = Object.keys(populateMap).length > 0
|
|
132
135
|
const populate: PopulateSpec | undefined = hasRelations ? populateMap : undefined
|
|
133
136
|
|
|
134
|
-
const result = await handle.
|
|
137
|
+
const result = await handle.findForEdit({
|
|
135
138
|
where: Object.keys(where).length > 0 ? where : undefined,
|
|
136
139
|
sort: viewState.sort,
|
|
137
140
|
locale: params.locale ?? 'en',
|
|
@@ -140,7 +143,6 @@ export const getCollectionDocuments = createServerFn({ method: 'GET' })
|
|
|
140
143
|
select: params.fields,
|
|
141
144
|
populate,
|
|
142
145
|
depth: hasRelations ? 1 : undefined,
|
|
143
|
-
status: 'any',
|
|
144
146
|
// Admin list: show the raw per-locale state (untranslated docs render
|
|
145
147
|
// empty in the active locale's columns) rather than falling back to the
|
|
146
148
|
// default locale. Consistent with the edit view; overrides the client's
|
|
@@ -205,5 +207,10 @@ export const getCollectionDocuments = createServerFn({ method: 'GET' })
|
|
|
205
207
|
return serialised as unknown as ReturnType<typeof list.parse>
|
|
206
208
|
}
|
|
207
209
|
|
|
208
|
-
|
|
210
|
+
const parsed = list.parse(serialised)
|
|
211
|
+
const observations = new Map(result.docs.map((doc) => [doc.id, doc]))
|
|
212
|
+
return {
|
|
213
|
+
...parsed,
|
|
214
|
+
docs: parsed.docs.map((doc) => withEditableRevision(doc, observations.get(doc.id))),
|
|
215
|
+
}
|
|
209
216
|
})
|
|
@@ -26,10 +26,12 @@ import { getAdminBylineClient } from '@byline/client/server'
|
|
|
26
26
|
import { ERR_NOT_FOUND, getLogger } from '@byline/core'
|
|
27
27
|
|
|
28
28
|
import { ensureCollection } from '../../integrations/api-utils.js'
|
|
29
|
+
import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
|
|
29
30
|
|
|
30
31
|
export type { ReindexResult }
|
|
31
32
|
|
|
32
33
|
export const reindexCollection = createServerFn({ method: 'POST' })
|
|
34
|
+
.middleware([adminSessionMiddleware])
|
|
33
35
|
.validator((input: { collection: string }) => input)
|
|
34
36
|
.handler(async ({ data }): Promise<ReindexResult> => {
|
|
35
37
|
const { collection } = data
|
|
@@ -9,17 +9,11 @@
|
|
|
9
9
|
import { createServerFn } from '@tanstack/react-start'
|
|
10
10
|
|
|
11
11
|
import { getAdminRequestContext } from '@byline/client/server'
|
|
12
|
-
import {
|
|
13
|
-
assertActorCanPerform,
|
|
14
|
-
ERR_NOT_FOUND,
|
|
15
|
-
ERR_VALIDATION,
|
|
16
|
-
generateKeyBetween,
|
|
17
|
-
generateNKeysBetween,
|
|
18
|
-
getLogger,
|
|
19
|
-
getServerConfig,
|
|
20
|
-
} from '@byline/core'
|
|
12
|
+
import { ERR_NOT_FOUND, getLogger, getServerConfig, reorderDocument } from '@byline/core'
|
|
21
13
|
|
|
22
14
|
import { ensureCollection } from '../../integrations/api-utils.js'
|
|
15
|
+
import { adminSessionMiddleware } from '../../integrations/session-middleware.js'
|
|
16
|
+
import { withDocumentMutationErrors } from '../document-mutation-errors.js'
|
|
23
17
|
|
|
24
18
|
// ---------------------------------------------------------------------------
|
|
25
19
|
// Reorder a single document within an `orderable: true` collection.
|
|
@@ -27,138 +21,54 @@ import { ensureCollection } from '../../integrations/api-utils.js'
|
|
|
27
21
|
// One of `beforeDocumentId` / `afterDocumentId` should be provided — they
|
|
28
22
|
// identify the neighbours the dragged row should land between. Either may
|
|
29
23
|
// be null:
|
|
30
|
-
// - both null →
|
|
31
|
-
// a fresh key)
|
|
24
|
+
// - both null → append to the end; retain the key if already there
|
|
32
25
|
// - beforeId set, afterId null → append after `beforeId`
|
|
33
26
|
// - beforeId null, afterId set → prepend before `afterId`
|
|
34
27
|
//
|
|
35
|
-
//
|
|
36
|
-
//
|
|
28
|
+
// Updates ordering and any necessary sibling-key repairs in one guarded
|
|
29
|
+
// transaction, without creating content versions. Uses `collections.<path>.update`;
|
|
37
30
|
// reordering is metadata-level update, not a new ability slug.
|
|
38
31
|
// ---------------------------------------------------------------------------
|
|
39
32
|
|
|
40
33
|
export const reorderCollectionDocument = createServerFn({ method: 'POST' })
|
|
34
|
+
.middleware([adminSessionMiddleware])
|
|
41
35
|
.validator(
|
|
42
36
|
(input: {
|
|
37
|
+
expectedRevision: number
|
|
43
38
|
collection: string
|
|
44
39
|
documentId: string
|
|
45
40
|
beforeDocumentId?: string | null
|
|
46
41
|
afterDocumentId?: string | null
|
|
47
42
|
}) => input
|
|
48
43
|
)
|
|
49
|
-
.handler(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (config.definition.orderable !== true) {
|
|
62
|
-
throw ERR_VALIDATION({
|
|
63
|
-
message: `collection '${path}' is not orderable; set \`orderable: true\` on its collection definition to enable reordering`,
|
|
64
|
-
details: { collectionPath: path },
|
|
65
|
-
}).log(logger)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const requestContext = await getAdminRequestContext()
|
|
69
|
-
assertActorCanPerform(requestContext, config.definition, 'update')
|
|
70
|
-
|
|
71
|
-
const serverConfig = getServerConfig()
|
|
72
|
-
const collectionId = config.collection.id
|
|
73
|
-
|
|
74
|
-
// Read the whole collection in canonical display order. Small by design
|
|
75
|
-
// for orderable use cases (bios, FAQs, sections), so a full read is
|
|
76
|
-
// cheap — and it gives us a single, consistent snapshot to reason about
|
|
77
|
-
// both backfill and recovery in one pass.
|
|
78
|
-
const canonical = await serverConfig.db.queries.documents.getCanonicalDocumentOrder({
|
|
79
|
-
collection_id: collectionId,
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
// Detect pathological key state — duplicates or non-ascending runs of
|
|
83
|
-
// keyed rows. These can land in the DB from prior buggy code paths
|
|
84
|
-
// or interrupted writes; once present, `generateKeyBetween` throws
|
|
85
|
-
// with `a >= b`. When detected, re-key the entire collection in the
|
|
86
|
-
// editor's current visible order so subsequent operations work from
|
|
87
|
-
// a clean baseline.
|
|
88
|
-
let corrupted = false
|
|
89
|
-
{
|
|
90
|
-
const seen = new Set<string>()
|
|
91
|
-
let lastKey: string | null = null
|
|
92
|
-
for (const doc of canonical) {
|
|
93
|
-
if (doc.order_key == null) continue
|
|
94
|
-
if (seen.has(doc.order_key)) {
|
|
95
|
-
corrupted = true
|
|
96
|
-
break
|
|
97
|
-
}
|
|
98
|
-
if (lastKey != null && doc.order_key <= lastKey) {
|
|
99
|
-
corrupted = true
|
|
100
|
-
break
|
|
101
|
-
}
|
|
102
|
-
seen.add(doc.order_key)
|
|
103
|
-
lastKey = doc.order_key
|
|
44
|
+
.handler(
|
|
45
|
+
withDocumentMutationErrors(async ({ data: input }) => {
|
|
46
|
+
const { collection: path, documentId, beforeDocumentId, afterDocumentId } = input
|
|
47
|
+
const logger = getLogger()
|
|
48
|
+
|
|
49
|
+
const config = await ensureCollection(path)
|
|
50
|
+
if (!config) {
|
|
51
|
+
throw ERR_NOT_FOUND({
|
|
52
|
+
message: 'Collection not found',
|
|
53
|
+
details: { collectionPath: path },
|
|
54
|
+
}).log(logger)
|
|
104
55
|
}
|
|
105
|
-
}
|
|
106
56
|
|
|
107
|
-
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
} else {
|
|
116
|
-
// Happy path — backfill trailing NULLs after the largest existing
|
|
117
|
-
// key. After canonical sort the NULL rows are always contiguous at
|
|
118
|
-
// the tail (`NULLS LAST`).
|
|
119
|
-
const firstNullIdx = canonical.findIndex((d) => d.order_key == null)
|
|
120
|
-
if (firstNullIdx !== -1) {
|
|
121
|
-
const nullDocs = canonical.slice(firstNullIdx)
|
|
122
|
-
const lastExistingKey = firstNullIdx === 0 ? null : canonical[firstNullIdx - 1]?.order_key
|
|
123
|
-
const newKeys = generateNKeysBetween(lastExistingKey, null, nullDocs.length)
|
|
124
|
-
for (let i = 0; i < nullDocs.length; i++) {
|
|
125
|
-
await serverConfig.db.commands.documents.setOrderKey({
|
|
126
|
-
document_id: nullDocs[i]?.id,
|
|
127
|
-
order_key: newKeys[i]!,
|
|
128
|
-
})
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Keys are now clean — resolve neighbours and place the moved row.
|
|
134
|
-
const { left, right } = await serverConfig.db.queries.documents.getNeighborOrderKeys({
|
|
135
|
-
collection_id: collectionId,
|
|
136
|
-
before_document_id: beforeDocumentId ?? null,
|
|
137
|
-
after_document_id: afterDocumentId ?? null,
|
|
138
|
-
})
|
|
139
|
-
|
|
140
|
-
let newKey: string
|
|
141
|
-
try {
|
|
142
|
-
newKey = generateKeyBetween(left, right)
|
|
143
|
-
} catch (err) {
|
|
144
|
-
throw ERR_VALIDATION({
|
|
145
|
-
message: 'cannot generate order_key between supplied neighbors',
|
|
146
|
-
details: {
|
|
57
|
+
const serverConfig = getServerConfig()
|
|
58
|
+
const result = await reorderDocument(
|
|
59
|
+
{
|
|
60
|
+
db: serverConfig.db,
|
|
61
|
+
definition: config.definition,
|
|
62
|
+
collectionId: config.collection.id,
|
|
63
|
+
collectionVersion: config.collection.version,
|
|
147
64
|
collectionPath: path,
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
right,
|
|
153
|
-
cause: err instanceof Error ? err.message : String(err),
|
|
65
|
+
requestContext: await getAdminRequestContext(),
|
|
66
|
+
logger,
|
|
67
|
+
defaultLocale: serverConfig.i18n.content.defaultLocale,
|
|
68
|
+
slugifier: serverConfig.slugifier,
|
|
154
69
|
},
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
await serverConfig.db.commands.documents.setOrderKey({
|
|
159
|
-
document_id: documentId,
|
|
160
|
-
order_key: newKey,
|
|
70
|
+
{ documentId, expectedRevision: input.expectedRevision, beforeDocumentId, afterDocumentId }
|
|
71
|
+
)
|
|
72
|
+
return { status: 'ok' as const, ...result }
|
|
161
73
|
})
|
|
162
|
-
|
|
163
|
-
return { status: 'ok' as const, orderKey: newKey }
|
|
164
|
-
})
|
|
74
|
+
)
|