@kywi-software/core 0.2.1 → 0.3.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/README.md +57 -2
- package/dist/admin/app.d.ts +10 -1
- package/dist/admin/app.d.ts.map +1 -1
- package/dist/admin/app.js +2 -2
- package/dist/admin/app.js.map +1 -1
- package/dist/admin/approval-queue.d.ts +3 -1
- package/dist/admin/approval-queue.d.ts.map +1 -1
- package/dist/admin/approval-queue.js +2 -2
- package/dist/admin/approval-queue.js.map +1 -1
- package/dist/admin/audience-list.d.ts.map +1 -1
- package/dist/admin/audience-list.js +9 -1
- package/dist/admin/audience-list.js.map +1 -1
- package/dist/admin/chrome.d.ts +7 -1
- package/dist/admin/chrome.d.ts.map +1 -1
- package/dist/admin/chrome.js +2 -1
- package/dist/admin/chrome.js.map +1 -1
- package/dist/admin/content-editor-api.d.ts +27 -1
- package/dist/admin/content-editor-api.d.ts.map +1 -1
- package/dist/admin/content-editor-api.js +60 -2
- package/dist/admin/content-editor-api.js.map +1 -1
- package/dist/admin/content-form.d.ts +62 -6
- package/dist/admin/content-form.d.ts.map +1 -1
- package/dist/admin/content-form.js +118 -13
- package/dist/admin/content-form.js.map +1 -1
- package/dist/admin/content-permissions-tab.d.ts +13 -0
- package/dist/admin/content-permissions-tab.d.ts.map +1 -0
- package/dist/admin/content-permissions-tab.js +90 -0
- package/dist/admin/content-permissions-tab.js.map +1 -0
- package/dist/admin/context.d.ts +8 -0
- package/dist/admin/context.d.ts.map +1 -1
- package/dist/admin/context.js.map +1 -1
- package/dist/admin/feed-builder.d.ts.map +1 -1
- package/dist/admin/feed-builder.js +20 -1
- package/dist/admin/feed-builder.js.map +1 -1
- package/dist/admin/field-components.d.ts.map +1 -1
- package/dist/admin/field-components.js +26 -1
- package/dist/admin/field-components.js.map +1 -1
- package/dist/admin/form-builder.js +6 -1
- package/dist/admin/form-builder.js.map +1 -1
- package/dist/admin/form-helpers.d.ts.map +1 -1
- package/dist/admin/form-helpers.js +2 -0
- package/dist/admin/form-helpers.js.map +1 -1
- package/dist/admin/layout-editor/component-actions.d.ts +18 -0
- package/dist/admin/layout-editor/component-actions.d.ts.map +1 -1
- package/dist/admin/layout-editor/component-actions.js +19 -0
- package/dist/admin/layout-editor/component-actions.js.map +1 -1
- package/dist/admin/layout-editor/component-picker-field.d.ts +20 -0
- package/dist/admin/layout-editor/component-picker-field.d.ts.map +1 -0
- package/dist/admin/layout-editor/component-picker-field.js +16 -0
- package/dist/admin/layout-editor/component-picker-field.js.map +1 -0
- package/dist/admin/layout-editor/drag-utils.d.ts +48 -0
- package/dist/admin/layout-editor/drag-utils.d.ts.map +1 -1
- package/dist/admin/layout-editor/drag-utils.js +43 -0
- package/dist/admin/layout-editor/drag-utils.js.map +1 -1
- package/dist/admin/layout-editor/editor-canvas.d.ts +9 -1
- package/dist/admin/layout-editor/editor-canvas.d.ts.map +1 -1
- package/dist/admin/layout-editor/editor-canvas.js +41 -15
- package/dist/admin/layout-editor/editor-canvas.js.map +1 -1
- package/dist/admin/layout-editor/editor-state.d.ts +9 -1
- package/dist/admin/layout-editor/editor-state.d.ts.map +1 -1
- package/dist/admin/layout-editor/editor-state.js +34 -0
- package/dist/admin/layout-editor/editor-state.js.map +1 -1
- package/dist/admin/layout-editor/editor.css +83 -0
- package/dist/admin/layout-editor/form-picker-field.d.ts +17 -0
- package/dist/admin/layout-editor/form-picker-field.d.ts.map +1 -0
- package/dist/admin/layout-editor/form-picker-field.js +35 -0
- package/dist/admin/layout-editor/form-picker-field.js.map +1 -0
- package/dist/admin/layout-editor/layout-editor.d.ts.map +1 -1
- package/dist/admin/layout-editor/layout-editor.js +95 -28
- package/dist/admin/layout-editor/layout-editor.js.map +1 -1
- package/dist/admin/layout-editor/mode-toggle.d.ts.map +1 -1
- package/dist/admin/layout-editor/mode-toggle.js +1 -1
- package/dist/admin/layout-editor/mode-toggle.js.map +1 -1
- package/dist/admin/layout-editor/module-overlay.d.ts +10 -1
- package/dist/admin/layout-editor/module-overlay.d.ts.map +1 -1
- package/dist/admin/layout-editor/module-overlay.js +3 -3
- package/dist/admin/layout-editor/module-overlay.js.map +1 -1
- package/dist/admin/layout-editor/props-panel.d.ts +10 -1
- package/dist/admin/layout-editor/props-panel.d.ts.map +1 -1
- package/dist/admin/layout-editor/props-panel.js +25 -2
- package/dist/admin/layout-editor/props-panel.js.map +1 -1
- package/dist/admin/layout-editor/section-insert-line.d.ts.map +1 -1
- package/dist/admin/layout-editor/section-insert-line.js +1 -1
- package/dist/admin/layout-editor/section-insert-line.js.map +1 -1
- package/dist/admin/layout-editor/section-overlay.d.ts.map +1 -1
- package/dist/admin/layout-editor/section-overlay.js +1 -1
- package/dist/admin/layout-editor/section-overlay.js.map +1 -1
- package/dist/admin/layout-editor/section-template-picker.d.ts +9 -1
- package/dist/admin/layout-editor/section-template-picker.d.ts.map +1 -1
- package/dist/admin/layout-editor/section-template-picker.js +45 -2
- package/dist/admin/layout-editor/section-template-picker.js.map +1 -1
- package/dist/admin/registry.d.ts.map +1 -1
- package/dist/admin/registry.js +11 -0
- package/dist/admin/registry.js.map +1 -1
- package/dist/admin/server.d.ts +15 -2
- package/dist/admin/server.d.ts.map +1 -1
- package/dist/admin/server.js +37 -1
- package/dist/admin/server.js.map +1 -1
- package/dist/admin/styles/admin.css +16 -4
- package/dist/admin/surface-matcher.d.ts +27 -0
- package/dist/admin/surface-matcher.d.ts.map +1 -1
- package/dist/admin/surface-matcher.js +11 -0
- package/dist/admin/surface-matcher.js.map +1 -1
- package/dist/admin/surfaces/approvals/approvals-data.d.ts +29 -9
- package/dist/admin/surfaces/approvals/approvals-data.d.ts.map +1 -1
- package/dist/admin/surfaces/approvals/approvals-data.js +65 -22
- package/dist/admin/surfaces/approvals/approvals-data.js.map +1 -1
- package/dist/admin/surfaces/approvals/approvals-index.d.ts.map +1 -1
- package/dist/admin/surfaces/approvals/approvals-index.js +47 -14
- package/dist/admin/surfaces/approvals/approvals-index.js.map +1 -1
- package/dist/admin/surfaces/content/content-edit.d.ts.map +1 -1
- package/dist/admin/surfaces/content/content-edit.js +34 -8
- package/dist/admin/surfaces/content/content-edit.js.map +1 -1
- package/dist/admin/surfaces/content/content-index.d.ts.map +1 -1
- package/dist/admin/surfaces/content/content-index.js +29 -2
- package/dist/admin/surfaces/content/content-index.js.map +1 -1
- package/dist/admin/surfaces/content/content-new.d.ts.map +1 -1
- package/dist/admin/surfaces/content/content-new.js +6 -4
- package/dist/admin/surfaces/content/content-new.js.map +1 -1
- package/dist/admin/surfaces/contentTree/content-tree.d.ts.map +1 -1
- package/dist/admin/surfaces/contentTree/content-tree.js +25 -2
- package/dist/admin/surfaces/contentTree/content-tree.js.map +1 -1
- package/dist/admin/surfaces/contentTypes/content-types-designer.d.ts.map +1 -1
- package/dist/admin/surfaces/contentTypes/content-types-designer.js +78 -47
- package/dist/admin/surfaces/contentTypes/content-types-designer.js.map +1 -1
- package/dist/admin/surfaces/feeds/feed-editor.d.ts.map +1 -1
- package/dist/admin/surfaces/feeds/feed-editor.js +21 -4
- package/dist/admin/surfaces/feeds/feed-editor.js.map +1 -1
- package/dist/admin/surfaces/layouts/layout-editor-client.d.ts.map +1 -1
- package/dist/admin/surfaces/layouts/layout-editor-client.js +7 -4
- package/dist/admin/surfaces/layouts/layout-editor-client.js.map +1 -1
- package/dist/admin/surfaces/media/media-client.d.ts.map +1 -1
- package/dist/admin/surfaces/media/media-client.js +10 -2
- package/dist/admin/surfaces/media/media-client.js.map +1 -1
- package/dist/admin/surfaces/settings/settings-site.d.ts.map +1 -1
- package/dist/admin/surfaces/settings/settings-site.js +39 -2
- package/dist/admin/surfaces/settings/settings-site.js.map +1 -1
- package/dist/admin/surfaces/settings/settings-sites.js +18 -0
- package/dist/admin/surfaces/settings/settings-sites.js.map +1 -1
- package/dist/admin/surfaces/trash/trash-index.d.ts.map +1 -1
- package/dist/admin/surfaces/trash/trash-index.js +45 -8
- package/dist/admin/surfaces/trash/trash-index.js.map +1 -1
- package/dist/admin/surfaces/users/users-data.d.ts +11 -0
- package/dist/admin/surfaces/users/users-data.d.ts.map +1 -1
- package/dist/admin/surfaces/users/users-data.js +20 -1
- package/dist/admin/surfaces/users/users-data.js.map +1 -1
- package/dist/admin/surfaces/webServices/web-services-data.d.ts +11 -1
- package/dist/admin/surfaces/webServices/web-services-data.d.ts.map +1 -1
- package/dist/admin/surfaces/webServices/web-services-data.js +13 -0
- package/dist/admin/surfaces/webServices/web-services-data.js.map +1 -1
- package/dist/admin/surfaces/webServices/webhooks.d.ts +3 -0
- package/dist/admin/surfaces/webServices/webhooks.d.ts.map +1 -0
- package/dist/admin/surfaces/webServices/webhooks.js +69 -0
- package/dist/admin/surfaces/webServices/webhooks.js.map +1 -0
- package/dist/admin/webhook-manager.d.ts +32 -0
- package/dist/admin/webhook-manager.d.ts.map +1 -0
- package/dist/admin/webhook-manager.js +62 -0
- package/dist/admin/webhook-manager.js.map +1 -0
- package/dist/api/admin-features-routes.d.ts.map +1 -1
- package/dist/api/admin-features-routes.js +30 -0
- package/dist/api/admin-features-routes.js.map +1 -1
- package/dist/api/api-key-routes.d.ts.map +1 -1
- package/dist/api/api-key-routes.js +6 -1
- package/dist/api/api-key-routes.js.map +1 -1
- package/dist/api/auth.d.ts +8 -0
- package/dist/api/auth.d.ts.map +1 -1
- package/dist/api/auth.js +11 -1
- package/dist/api/auth.js.map +1 -1
- package/dist/api/comment-routes.d.ts.map +1 -1
- package/dist/api/comment-routes.js +102 -47
- package/dist/api/comment-routes.js.map +1 -1
- package/dist/api/config-routes.d.ts +10 -2
- package/dist/api/config-routes.d.ts.map +1 -1
- package/dist/api/config-routes.js +46 -25
- package/dist/api/config-routes.js.map +1 -1
- package/dist/api/content-routes.d.ts.map +1 -1
- package/dist/api/content-routes.js +41 -0
- package/dist/api/content-routes.js.map +1 -1
- package/dist/api/content-schemas.d.ts.map +1 -1
- package/dist/api/content-schemas.js +34 -1
- package/dist/api/content-schemas.js.map +1 -1
- package/dist/api/content-type-routes.d.ts.map +1 -1
- package/dist/api/content-type-routes.js +58 -3
- package/dist/api/content-type-routes.js.map +1 -1
- package/dist/api/feed-routes.d.ts +180 -0
- package/dist/api/feed-routes.d.ts.map +1 -1
- package/dist/api/feed-routes.js +10 -2
- package/dist/api/feed-routes.js.map +1 -1
- package/dist/api/form-routes.d.ts +6 -0
- package/dist/api/form-routes.d.ts.map +1 -1
- package/dist/api/form-routes.js +93 -14
- package/dist/api/form-routes.js.map +1 -1
- package/dist/api/graphql/resolvers.d.ts +4 -4
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +12 -1
- package/dist/api/index.js.map +1 -1
- package/dist/api/media-routes.d.ts.map +1 -1
- package/dist/api/media-routes.js +18 -1
- package/dist/api/media-routes.js.map +1 -1
- package/dist/api/webhook-routes.d.ts.map +1 -1
- package/dist/api/webhook-routes.js +19 -2
- package/dist/api/webhook-routes.js.map +1 -1
- package/dist/api/workflow-routes.d.ts.map +1 -1
- package/dist/api/workflow-routes.js +163 -4
- package/dist/api/workflow-routes.js.map +1 -1
- package/dist/auth/roles.d.ts +28 -0
- package/dist/auth/roles.d.ts.map +1 -1
- package/dist/auth/roles.js +49 -0
- package/dist/auth/roles.js.map +1 -1
- package/dist/config/reserved-field-names.d.ts +29 -0
- package/dist/config/reserved-field-names.d.ts.map +1 -0
- package/dist/config/reserved-field-names.js +59 -0
- package/dist/config/reserved-field-names.js.map +1 -0
- package/dist/config/types.d.ts +31 -2
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js.map +1 -1
- package/dist/db/analytics-queries.d.ts +1 -1
- package/dist/db/api-key-queries.d.ts +7 -2
- package/dist/db/api-key-queries.d.ts.map +1 -1
- package/dist/db/api-key-queries.js +8 -2
- package/dist/db/api-key-queries.js.map +1 -1
- package/dist/db/apply-snapshot.d.ts +58 -0
- package/dist/db/apply-snapshot.d.ts.map +1 -0
- package/dist/db/apply-snapshot.js +142 -0
- package/dist/db/apply-snapshot.js.map +1 -0
- package/dist/db/audit-queries.d.ts +3 -3
- package/dist/db/category-queries.d.ts +3 -3
- package/dist/db/changeset-audit-queries.d.ts +2 -2
- package/dist/db/changeset-queries.d.ts +5 -5
- package/dist/db/changeset-queries.d.ts.map +1 -1
- package/dist/db/changeset-queries.js +24 -7
- package/dist/db/changeset-queries.js.map +1 -1
- package/dist/db/content-queries.d.ts +6 -0
- package/dist/db/content-queries.d.ts.map +1 -1
- package/dist/db/content-queries.js +8 -0
- package/dist/db/content-queries.js.map +1 -1
- package/dist/db/content-type-queries.d.ts +20 -0
- package/dist/db/content-type-queries.d.ts.map +1 -1
- package/dist/db/content-type-queries.js +32 -0
- package/dist/db/content-type-queries.js.map +1 -1
- package/dist/db/dashboard-queries.d.ts.map +1 -1
- package/dist/db/dashboard-queries.js +5 -1
- package/dist/db/dashboard-queries.js.map +1 -1
- package/dist/db/dynamic-schema.d.ts.map +1 -1
- package/dist/db/dynamic-schema.js +2 -0
- package/dist/db/dynamic-schema.js.map +1 -1
- package/dist/db/extension-queries.d.ts +8 -8
- package/dist/db/feed-queries.d.ts +3 -3
- package/dist/db/index.d.ts +3 -0
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +7 -0
- package/dist/db/index.js.map +1 -1
- package/dist/db/media-queries.d.ts +31 -7
- package/dist/db/media-queries.d.ts.map +1 -1
- package/dist/db/media-queries.js +13 -1
- package/dist/db/media-queries.js.map +1 -1
- package/dist/db/membership-dedupe.d.ts +26 -0
- package/dist/db/membership-dedupe.d.ts.map +1 -0
- package/dist/db/membership-dedupe.js +68 -0
- package/dist/db/membership-dedupe.js.map +1 -0
- package/dist/db/revision-queries.d.ts +122 -0
- package/dist/db/revision-queries.d.ts.map +1 -0
- package/dist/db/revision-queries.js +213 -0
- package/dist/db/revision-queries.js.map +1 -0
- package/dist/db/schema-apply.d.ts +8 -0
- package/dist/db/schema-apply.d.ts.map +1 -1
- package/dist/db/schema-apply.js +17 -0
- package/dist/db/schema-apply.js.map +1 -1
- package/dist/db/schema-field-queries.d.ts +2 -0
- package/dist/db/schema-field-queries.d.ts.map +1 -1
- package/dist/db/schema-field-queries.js +4 -0
- package/dist/db/schema-field-queries.js.map +1 -1
- package/dist/db/site-plugin-queries.d.ts +2 -2
- package/dist/db/user-queries.d.ts +12 -0
- package/dist/db/user-queries.d.ts.map +1 -1
- package/dist/db/user-queries.js +18 -4
- package/dist/db/user-queries.js.map +1 -1
- package/dist/db/version-queries.d.ts +37 -0
- package/dist/db/version-queries.d.ts.map +1 -1
- package/dist/db/version-queries.js +36 -0
- package/dist/db/version-queries.js.map +1 -1
- package/dist/db/webhook-queries.d.ts +27 -5
- package/dist/db/webhook-queries.d.ts.map +1 -1
- package/dist/db/webhook-queries.js +17 -0
- package/dist/db/webhook-queries.js.map +1 -1
- package/dist/db/workflow-queries.d.ts +2 -2
- package/dist/experiments/schema.d.ts +1 -1
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/webhook-retry.d.ts +22 -1
- package/dist/hooks/webhook-retry.d.ts.map +1 -1
- package/dist/hooks/webhook-retry.js +38 -1
- package/dist/hooks/webhook-retry.js.map +1 -1
- package/dist/host/index.d.ts +28 -0
- package/dist/host/index.d.ts.map +1 -1
- package/dist/host/index.js +56 -1
- package/dist/host/index.js.map +1 -1
- package/dist/layout/comments-module.d.ts +18 -0
- package/dist/layout/comments-module.d.ts.map +1 -0
- package/dist/layout/comments-module.js +130 -0
- package/dist/layout/comments-module.js.map +1 -0
- package/dist/layout/feed-hydration.d.ts +75 -0
- package/dist/layout/feed-hydration.d.ts.map +1 -0
- package/dist/layout/feed-hydration.js +158 -0
- package/dist/layout/feed-hydration.js.map +1 -0
- package/dist/layout/index.d.ts +2 -1
- package/dist/layout/index.d.ts.map +1 -1
- package/dist/layout/index.js +2 -1
- package/dist/layout/index.js.map +1 -1
- package/dist/layout/module-render-context.d.ts +13 -0
- package/dist/layout/module-render-context.d.ts.map +1 -0
- package/dist/layout/module-render-context.js +15 -0
- package/dist/layout/module-render-context.js.map +1 -0
- package/dist/layout/modules-extended.d.ts.map +1 -1
- package/dist/layout/modules-extended.js +92 -13
- package/dist/layout/modules-extended.js.map +1 -1
- package/dist/layout/registry.d.ts.map +1 -1
- package/dist/layout/registry.js +22 -6
- package/dist/layout/registry.js.map +1 -1
- package/dist/layout/renderer.d.ts +17 -1
- package/dist/layout/renderer.d.ts.map +1 -1
- package/dist/layout/renderer.js +11 -4
- package/dist/layout/renderer.js.map +1 -1
- package/dist/nav/index.d.ts +1 -0
- package/dist/nav/index.d.ts.map +1 -1
- package/dist/nav/index.js +4 -0
- package/dist/nav/index.js.map +1 -1
- package/dist/nav/url-resolver.d.ts +10 -2
- package/dist/nav/url-resolver.d.ts.map +1 -1
- package/dist/nav/url-resolver.js +17 -3
- package/dist/nav/url-resolver.js.map +1 -1
- package/dist/schema/base.d.ts +37 -1
- package/dist/schema/base.d.ts.map +1 -1
- package/dist/schema/base.js +20 -2
- package/dist/schema/base.js.map +1 -1
- package/dist/schema/generate.d.ts +8 -0
- package/dist/schema/generate.d.ts.map +1 -1
- package/dist/schema/generate.js +7 -4
- package/dist/schema/generate.js.map +1 -1
- package/dist/schema/mapper.d.ts.map +1 -1
- package/dist/schema/mapper.js +2 -0
- package/dist/schema/mapper.js.map +1 -1
- package/dist/schema/mysql-tables.d.ts +34 -0
- package/dist/schema/mysql-tables.d.ts.map +1 -1
- package/dist/schema/mysql-tables.js +14 -2
- package/dist/schema/mysql-tables.js.map +1 -1
- package/dist/server.d.ts +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1 -0
- package/dist/server.js.map +1 -1
- package/dist/site/styles.css +384 -0
- package/package.json +2 -1
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import type { PgTableWithColumns } from 'drizzle-orm/pg-core';
|
|
2
|
+
import { type ContentWithCustomFields } from './content-queries.js';
|
|
3
|
+
import type { KywiDb } from './client.js';
|
|
4
|
+
/**
|
|
5
|
+
* Pending revisions (#42) — reviewing edits to already-published content without
|
|
6
|
+
* unpublishing the live version.
|
|
7
|
+
*
|
|
8
|
+
* The problem: an editor could only push edits to a live page by direct-publish;
|
|
9
|
+
* `published → pending` was a forbidden transition, and even if allowed it would
|
|
10
|
+
* pull the page off the live site (only `published` renders). There was no
|
|
11
|
+
* "draft of a published page under review" concept.
|
|
12
|
+
*
|
|
13
|
+
* The model, built entirely on the EXISTING kywi_content_versions table (no new
|
|
14
|
+
* table, no schema migration): a pending revision is a version row with
|
|
15
|
+
* `status = 'pending'` whose snapshot carries the {@link REVISION_MARKER} flag
|
|
16
|
+
* and the PROPOSED (edited) content. The live kywi_content row is never touched
|
|
17
|
+
* on submit, so the published page keeps serving its current content. The marker
|
|
18
|
+
* distinguishes an OUTSTANDING revision from the ordinary historical
|
|
19
|
+
* status='pending' snapshot the draft→pending→approve cycle also produces, so the
|
|
20
|
+
* approvals queue never confuses the two. On resolution the marked row is
|
|
21
|
+
* deleted, so "outstanding revision" == "a marked pending version exists".
|
|
22
|
+
*/
|
|
23
|
+
/** Snapshot flag marking a version row as an outstanding pending revision. */
|
|
24
|
+
export declare const REVISION_MARKER = "__pendingRevision";
|
|
25
|
+
/** Return a copy of a revision snapshot with the internal marker removed. */
|
|
26
|
+
export declare function stripRevisionMarker(snapshot: Record<string, unknown>): Record<string, unknown>;
|
|
27
|
+
/** A pending-revision version joined with its live content, for the queue. */
|
|
28
|
+
export interface PendingRevisionRow {
|
|
29
|
+
versionId: string;
|
|
30
|
+
version: number;
|
|
31
|
+
contentId: string;
|
|
32
|
+
contentTypeName: string;
|
|
33
|
+
title: string;
|
|
34
|
+
siteId: string;
|
|
35
|
+
status: string;
|
|
36
|
+
createdBy: string | null;
|
|
37
|
+
createdAt: Date;
|
|
38
|
+
changeNote: string | null;
|
|
39
|
+
snapshot: Record<string, unknown>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Create a pending revision: a version snapshot of the proposed content with the
|
|
43
|
+
* revision marker, status 'pending'. The live content row is deliberately NOT
|
|
44
|
+
* modified — the caller has already confirmed the content is published/approved
|
|
45
|
+
* and the point is that it keeps serving until approval.
|
|
46
|
+
*
|
|
47
|
+
* Uses createVersion directly (not recordContentVersion) so a pending revision is
|
|
48
|
+
* never pruned by the retention cap while it awaits review.
|
|
49
|
+
*/
|
|
50
|
+
export declare function createPendingRevision(db: KywiDb, data: {
|
|
51
|
+
contentId: string;
|
|
52
|
+
siteId: string;
|
|
53
|
+
proposed: Record<string, unknown>;
|
|
54
|
+
changeNote?: string | undefined;
|
|
55
|
+
createdBy: string | null;
|
|
56
|
+
}): Promise<{
|
|
57
|
+
id: string;
|
|
58
|
+
siteId: string;
|
|
59
|
+
status: string;
|
|
60
|
+
createdAt: Date;
|
|
61
|
+
createdBy: string | null;
|
|
62
|
+
contentId: string;
|
|
63
|
+
version: number;
|
|
64
|
+
snapshot: unknown;
|
|
65
|
+
changeNote: string | null;
|
|
66
|
+
}>;
|
|
67
|
+
/**
|
|
68
|
+
* List outstanding pending revisions for a site — one row per revision version
|
|
69
|
+
* carrying the marker, joined to its (non-deleted) live content. Ordered newest
|
|
70
|
+
* first. Feeds the approvals queue alongside the plain status='pending' drafts.
|
|
71
|
+
*/
|
|
72
|
+
export declare function listPendingRevisions(db: KywiDb, siteId: string): Promise<PendingRevisionRow[]>;
|
|
73
|
+
/**
|
|
74
|
+
* Fetch a single pending-revision version by id, validating it is a marked,
|
|
75
|
+
* still-pending revision belonging to `contentId`. Returns null otherwise (an
|
|
76
|
+
* already-resolved or non-revision version id).
|
|
77
|
+
*/
|
|
78
|
+
export declare function getPendingRevision(db: KywiDb, contentId: string, versionId: string): Promise<{
|
|
79
|
+
id: string;
|
|
80
|
+
version: number;
|
|
81
|
+
siteId: string;
|
|
82
|
+
snapshot: Record<string, unknown>;
|
|
83
|
+
changeNote: string | null;
|
|
84
|
+
} | null>;
|
|
85
|
+
/**
|
|
86
|
+
* Approve a pending revision: apply its proposed snapshot onto the live content
|
|
87
|
+
* (publishing it), record a normal published version of the result, and delete
|
|
88
|
+
* the marked revision row so it leaves the queue. The live page transitions from
|
|
89
|
+
* its old content to the approved content in one step, staying published.
|
|
90
|
+
*/
|
|
91
|
+
export declare function approvePendingRevision(db: KywiDb, opts: {
|
|
92
|
+
contentId: string;
|
|
93
|
+
versionId: string;
|
|
94
|
+
userId: string;
|
|
95
|
+
userEmail: string;
|
|
96
|
+
customTable: PgTableWithColumns<any> | null;
|
|
97
|
+
customFieldNames?: readonly string[];
|
|
98
|
+
}): Promise<{
|
|
99
|
+
success: boolean;
|
|
100
|
+
content?: ContentWithCustomFields;
|
|
101
|
+
error?: string;
|
|
102
|
+
}>;
|
|
103
|
+
/**
|
|
104
|
+
* Reject a pending revision: discard the proposed snapshot (delete the marked
|
|
105
|
+
* row) and record a version on the UNCHANGED live content whose changeNote is
|
|
106
|
+
* `Rejected: <reason>`. Recording it as a version (matching the draft-reject
|
|
107
|
+
* flow) is what surfaces the reason back to the editor — the edit screen reads
|
|
108
|
+
* the latest `Rejected:` version note. The live content is never modified.
|
|
109
|
+
*/
|
|
110
|
+
export declare function rejectPendingRevision(db: KywiDb, opts: {
|
|
111
|
+
contentId: string;
|
|
112
|
+
versionId: string;
|
|
113
|
+
reason?: string | undefined;
|
|
114
|
+
userId: string;
|
|
115
|
+
userEmail: string;
|
|
116
|
+
customTable: PgTableWithColumns<any> | null;
|
|
117
|
+
}): Promise<{
|
|
118
|
+
success: boolean;
|
|
119
|
+
content?: ContentWithCustomFields;
|
|
120
|
+
error?: string;
|
|
121
|
+
}>;
|
|
122
|
+
//# sourceMappingURL=revision-queries.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revision-queries.d.ts","sourceRoot":"","sources":["../../src/db/revision-queries.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { eq, and, desc, sql } from 'drizzle-orm';
|
|
2
|
+
import { kywiContent, kywiContentVersions } from '../schema/base.js';
|
|
3
|
+
import { createVersion, getLatestVersionNumber, recordContentVersion } from './version-queries.js';
|
|
4
|
+
import { getContentById } from './content-queries.js';
|
|
5
|
+
import { applyContentSnapshot } from './apply-snapshot.js';
|
|
6
|
+
import { createAuditEntry } from './audit-queries.js';
|
|
7
|
+
/**
|
|
8
|
+
* Pending revisions (#42) — reviewing edits to already-published content without
|
|
9
|
+
* unpublishing the live version.
|
|
10
|
+
*
|
|
11
|
+
* The problem: an editor could only push edits to a live page by direct-publish;
|
|
12
|
+
* `published → pending` was a forbidden transition, and even if allowed it would
|
|
13
|
+
* pull the page off the live site (only `published` renders). There was no
|
|
14
|
+
* "draft of a published page under review" concept.
|
|
15
|
+
*
|
|
16
|
+
* The model, built entirely on the EXISTING kywi_content_versions table (no new
|
|
17
|
+
* table, no schema migration): a pending revision is a version row with
|
|
18
|
+
* `status = 'pending'` whose snapshot carries the {@link REVISION_MARKER} flag
|
|
19
|
+
* and the PROPOSED (edited) content. The live kywi_content row is never touched
|
|
20
|
+
* on submit, so the published page keeps serving its current content. The marker
|
|
21
|
+
* distinguishes an OUTSTANDING revision from the ordinary historical
|
|
22
|
+
* status='pending' snapshot the draft→pending→approve cycle also produces, so the
|
|
23
|
+
* approvals queue never confuses the two. On resolution the marked row is
|
|
24
|
+
* deleted, so "outstanding revision" == "a marked pending version exists".
|
|
25
|
+
*/
|
|
26
|
+
/** Snapshot flag marking a version row as an outstanding pending revision. */
|
|
27
|
+
export const REVISION_MARKER = '__pendingRevision';
|
|
28
|
+
/** Return a copy of a revision snapshot with the internal marker removed. */
|
|
29
|
+
export function stripRevisionMarker(snapshot) {
|
|
30
|
+
const { [REVISION_MARKER]: _marker, ...rest } = snapshot;
|
|
31
|
+
return rest;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Create a pending revision: a version snapshot of the proposed content with the
|
|
35
|
+
* revision marker, status 'pending'. The live content row is deliberately NOT
|
|
36
|
+
* modified — the caller has already confirmed the content is published/approved
|
|
37
|
+
* and the point is that it keeps serving until approval.
|
|
38
|
+
*
|
|
39
|
+
* Uses createVersion directly (not recordContentVersion) so a pending revision is
|
|
40
|
+
* never pruned by the retention cap while it awaits review.
|
|
41
|
+
*/
|
|
42
|
+
export async function createPendingRevision(db, data) {
|
|
43
|
+
const latest = await getLatestVersionNumber(db, data.contentId);
|
|
44
|
+
const snapshot = { ...data.proposed, [REVISION_MARKER]: true };
|
|
45
|
+
return createVersion(db, {
|
|
46
|
+
contentId: data.contentId,
|
|
47
|
+
siteId: data.siteId,
|
|
48
|
+
version: latest + 1,
|
|
49
|
+
snapshot,
|
|
50
|
+
status: 'pending',
|
|
51
|
+
createdBy: data.createdBy,
|
|
52
|
+
...(data.changeNote !== undefined ? { changeNote: data.changeNote } : {}),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* List outstanding pending revisions for a site — one row per revision version
|
|
57
|
+
* carrying the marker, joined to its (non-deleted) live content. Ordered newest
|
|
58
|
+
* first. Feeds the approvals queue alongside the plain status='pending' drafts.
|
|
59
|
+
*/
|
|
60
|
+
export async function listPendingRevisions(db, siteId) {
|
|
61
|
+
const rows = await db
|
|
62
|
+
.select({
|
|
63
|
+
versionId: kywiContentVersions.id,
|
|
64
|
+
version: kywiContentVersions.version,
|
|
65
|
+
contentId: kywiContentVersions.contentId,
|
|
66
|
+
siteId: kywiContentVersions.siteId,
|
|
67
|
+
createdBy: kywiContentVersions.createdBy,
|
|
68
|
+
createdAt: kywiContentVersions.createdAt,
|
|
69
|
+
changeNote: kywiContentVersions.changeNote,
|
|
70
|
+
snapshot: kywiContentVersions.snapshot,
|
|
71
|
+
contentTypeName: kywiContent.contentTypeName,
|
|
72
|
+
title: kywiContent.title,
|
|
73
|
+
contentStatus: kywiContent.status,
|
|
74
|
+
})
|
|
75
|
+
.from(kywiContentVersions)
|
|
76
|
+
.innerJoin(kywiContent, eq(kywiContent.id, kywiContentVersions.contentId))
|
|
77
|
+
.where(and(eq(kywiContentVersions.siteId, siteId), eq(kywiContentVersions.status, 'pending'), sql `(${kywiContentVersions.snapshot} ->> ${REVISION_MARKER}) = 'true'`, sql `${kywiContent.deletedAt} IS NULL`))
|
|
78
|
+
.orderBy(desc(kywiContentVersions.createdAt));
|
|
79
|
+
return rows.map((r) => ({
|
|
80
|
+
versionId: r.versionId,
|
|
81
|
+
version: r.version,
|
|
82
|
+
contentId: r.contentId,
|
|
83
|
+
contentTypeName: r.contentTypeName,
|
|
84
|
+
title: r.title,
|
|
85
|
+
siteId: r.siteId,
|
|
86
|
+
status: r.contentStatus,
|
|
87
|
+
createdBy: r.createdBy ?? null,
|
|
88
|
+
createdAt: r.createdAt,
|
|
89
|
+
changeNote: r.changeNote ?? null,
|
|
90
|
+
snapshot: r.snapshot,
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Fetch a single pending-revision version by id, validating it is a marked,
|
|
95
|
+
* still-pending revision belonging to `contentId`. Returns null otherwise (an
|
|
96
|
+
* already-resolved or non-revision version id).
|
|
97
|
+
*/
|
|
98
|
+
export async function getPendingRevision(db, contentId, versionId) {
|
|
99
|
+
const [row] = await db
|
|
100
|
+
.select()
|
|
101
|
+
.from(kywiContentVersions)
|
|
102
|
+
.where(eq(kywiContentVersions.id, versionId))
|
|
103
|
+
.limit(1);
|
|
104
|
+
if (!row)
|
|
105
|
+
return null;
|
|
106
|
+
if (row.contentId !== contentId)
|
|
107
|
+
return null;
|
|
108
|
+
if (row.status !== 'pending')
|
|
109
|
+
return null;
|
|
110
|
+
const snapshot = row.snapshot;
|
|
111
|
+
if (snapshot?.[REVISION_MARKER] !== true)
|
|
112
|
+
return null;
|
|
113
|
+
return {
|
|
114
|
+
id: row.id,
|
|
115
|
+
version: row.version,
|
|
116
|
+
siteId: row.siteId,
|
|
117
|
+
snapshot,
|
|
118
|
+
changeNote: row.changeNote ?? null,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Approve a pending revision: apply its proposed snapshot onto the live content
|
|
123
|
+
* (publishing it), record a normal published version of the result, and delete
|
|
124
|
+
* the marked revision row so it leaves the queue. The live page transitions from
|
|
125
|
+
* its old content to the approved content in one step, staying published.
|
|
126
|
+
*/
|
|
127
|
+
export async function approvePendingRevision(db, opts) {
|
|
128
|
+
const revision = await getPendingRevision(db, opts.contentId, opts.versionId);
|
|
129
|
+
if (!revision)
|
|
130
|
+
return { success: false, error: 'Pending revision not found' };
|
|
131
|
+
const content = await db.transaction(async (rawTx) => {
|
|
132
|
+
const tx = rawTx;
|
|
133
|
+
const clean = stripRevisionMarker(revision.snapshot);
|
|
134
|
+
await applyContentSnapshot(tx, opts.contentId, clean, {
|
|
135
|
+
forceStatus: 'published',
|
|
136
|
+
userId: opts.userId,
|
|
137
|
+
customTable: opts.customTable,
|
|
138
|
+
customFieldNames: opts.customFieldNames ?? [],
|
|
139
|
+
});
|
|
140
|
+
// Remove the revision row first so the published version we record next is
|
|
141
|
+
// the highest version number (and the revision leaves the queue).
|
|
142
|
+
await tx.delete(kywiContentVersions).where(eq(kywiContentVersions.id, opts.versionId));
|
|
143
|
+
const applied = await getContentById(tx, opts.customTable, opts.contentId);
|
|
144
|
+
if (applied) {
|
|
145
|
+
await recordContentVersion(tx, {
|
|
146
|
+
contentId: opts.contentId,
|
|
147
|
+
siteId: revision.siteId,
|
|
148
|
+
snapshot: applied,
|
|
149
|
+
status: 'published',
|
|
150
|
+
createdBy: opts.userId,
|
|
151
|
+
changeNote: revision.changeNote
|
|
152
|
+
? `Approved revision: ${revision.changeNote}`
|
|
153
|
+
: 'Approved revision',
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
await createAuditEntry(tx, {
|
|
157
|
+
siteId: revision.siteId,
|
|
158
|
+
contentId: opts.contentId,
|
|
159
|
+
action: 'approve',
|
|
160
|
+
fromStatus: 'published',
|
|
161
|
+
toStatus: 'published',
|
|
162
|
+
userId: opts.userId,
|
|
163
|
+
userEmail: opts.userEmail,
|
|
164
|
+
});
|
|
165
|
+
return applied;
|
|
166
|
+
});
|
|
167
|
+
const result = { success: true };
|
|
168
|
+
if (content)
|
|
169
|
+
result.content = content;
|
|
170
|
+
return result;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Reject a pending revision: discard the proposed snapshot (delete the marked
|
|
174
|
+
* row) and record a version on the UNCHANGED live content whose changeNote is
|
|
175
|
+
* `Rejected: <reason>`. Recording it as a version (matching the draft-reject
|
|
176
|
+
* flow) is what surfaces the reason back to the editor — the edit screen reads
|
|
177
|
+
* the latest `Rejected:` version note. The live content is never modified.
|
|
178
|
+
*/
|
|
179
|
+
export async function rejectPendingRevision(db, opts) {
|
|
180
|
+
const revision = await getPendingRevision(db, opts.contentId, opts.versionId);
|
|
181
|
+
if (!revision)
|
|
182
|
+
return { success: false, error: 'Pending revision not found' };
|
|
183
|
+
const content = await db.transaction(async (rawTx) => {
|
|
184
|
+
const tx = rawTx;
|
|
185
|
+
await tx.delete(kywiContentVersions).where(eq(kywiContentVersions.id, opts.versionId));
|
|
186
|
+
const current = await getContentById(tx, opts.customTable, opts.contentId);
|
|
187
|
+
if (current) {
|
|
188
|
+
await recordContentVersion(tx, {
|
|
189
|
+
contentId: opts.contentId,
|
|
190
|
+
siteId: revision.siteId,
|
|
191
|
+
snapshot: current,
|
|
192
|
+
status: current.status ?? 'published',
|
|
193
|
+
createdBy: opts.userId,
|
|
194
|
+
changeNote: opts.reason !== undefined ? `Rejected: ${opts.reason}` : 'Rejected',
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
await createAuditEntry(tx, {
|
|
198
|
+
siteId: revision.siteId,
|
|
199
|
+
contentId: opts.contentId,
|
|
200
|
+
action: 'reject',
|
|
201
|
+
fromStatus: current?.status ?? 'published',
|
|
202
|
+
toStatus: current?.status ?? 'published',
|
|
203
|
+
userId: opts.userId,
|
|
204
|
+
userEmail: opts.userEmail,
|
|
205
|
+
});
|
|
206
|
+
return current;
|
|
207
|
+
});
|
|
208
|
+
const result = { success: true };
|
|
209
|
+
if (content)
|
|
210
|
+
result.content = content;
|
|
211
|
+
return result;
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=revision-queries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"revision-queries.js","sourceRoot":"","sources":["../../src/db/revision-queries.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,14 @@ export interface SchemaDiff {
|
|
|
13
13
|
export declare function diffFields(actualColumns: string[], desiredFields: FieldDefinition[]): SchemaDiff;
|
|
14
14
|
/** Read actual column names for a table from information_schema. */
|
|
15
15
|
export declare function getActualColumns(db: KywiDb, tableName: string): Promise<string[]>;
|
|
16
|
+
/**
|
|
17
|
+
* List every dynamic content-type table (`kywi_ct_*`) that physically exists in
|
|
18
|
+
* the public schema. Used by `migrate:generate` (#38) to compute which dynamic
|
|
19
|
+
* tables are orphans (present in the DB but backed by neither a config type nor
|
|
20
|
+
* a currently-registered admin type) so they can be excluded from the drizzle-kit
|
|
21
|
+
* diff instead of being offered for DROP.
|
|
22
|
+
*/
|
|
23
|
+
export declare function listCustomContentTables(db: KywiDb): Promise<string[]>;
|
|
16
24
|
/** Does a table exist in the public schema? */
|
|
17
25
|
export declare function tableExists(db: KywiDb, tableName: string): Promise<boolean>;
|
|
18
26
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-apply.d.ts","sourceRoot":"","sources":["../../src/db/schema-apply.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAGzD,MAAM,WAAW,UAAU;IACzB,6EAA6E;IAC7E,KAAK,EAAE,eAAe,EAAE,CAAA;IACxB,8GAA8G;IAC9G,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,aAAa,EAAE,MAAM,EAAE,EAAE,aAAa,EAAE,eAAe,EAAE,GAAG,UAAU,CAQhG;
|
|
1
|
+
{"version":3,"file":"schema-apply.d.ts","sourceRoot":"","sources":["../../src/db/schema-apply.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAGzD,MAAM,WAAW,UAAU;IACzB,6EAA6E;IAC7E,KAAK,EAAE,eAAe,EAAE,CAAA;IACxB,8GAA8G;IAC9G,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,aAAa,EAAE,MAAM,EAAE,EAAE,aAAa,EAAE,eAAe,EAAE,GAAG,UAAU,CAQhG;AAmCD,oEAAoE;AACpE,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CASvF;AAED;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAO3E;AAED,+CAA+C;AAC/C,wBAAsB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOjF;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAAC,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUlG;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,MAAM,EACV,eAAe,EAAE,MAAM,EACvB,SAAS,EAAE,eAAe,EAAE,GAC3B,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CAelE"}
|
package/dist/db/schema-apply.js
CHANGED
|
@@ -17,9 +17,11 @@ function fieldTypeToSql(field) {
|
|
|
17
17
|
case 'text':
|
|
18
18
|
case 'richText':
|
|
19
19
|
case 'textarea':
|
|
20
|
+
case 'url':
|
|
20
21
|
return 'text';
|
|
21
22
|
case 'select':
|
|
22
23
|
case 'slug':
|
|
24
|
+
case 'email':
|
|
23
25
|
return 'varchar(255)';
|
|
24
26
|
case 'color':
|
|
25
27
|
return 'varchar(7)';
|
|
@@ -52,6 +54,21 @@ export async function getActualColumns(db, tableName) {
|
|
|
52
54
|
`);
|
|
53
55
|
return rows.map((r) => r.column_name);
|
|
54
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* List every dynamic content-type table (`kywi_ct_*`) that physically exists in
|
|
59
|
+
* the public schema. Used by `migrate:generate` (#38) to compute which dynamic
|
|
60
|
+
* tables are orphans (present in the DB but backed by neither a config type nor
|
|
61
|
+
* a currently-registered admin type) so they can be excluded from the drizzle-kit
|
|
62
|
+
* diff instead of being offered for DROP.
|
|
63
|
+
*/
|
|
64
|
+
export async function listCustomContentTables(db) {
|
|
65
|
+
const rows = await db.execute(sql `
|
|
66
|
+
SELECT table_name FROM information_schema.tables
|
|
67
|
+
WHERE table_schema = 'public' AND table_name LIKE 'kywi\\_ct\\_%'
|
|
68
|
+
ORDER BY table_name
|
|
69
|
+
`);
|
|
70
|
+
return rows.map((r) => r.table_name);
|
|
71
|
+
}
|
|
55
72
|
/** Does a table exist in the public schema? */
|
|
56
73
|
export async function tableExists(db, tableName) {
|
|
57
74
|
const rows = await db.execute(sql `
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-apply.js","sourceRoot":"","sources":["../../src/db/schema-apply.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AAGjC,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AAS1E;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,aAAuB,EAAE,aAAgC;IAClF,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAA;IAC7C,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAE7E,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACtF,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;IAE9F,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAA;AAC3B,CAAC;AAED,qFAAqF;AACrF,SAAS,cAAc,CAAC,KAAsB;IAC5C,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,MAAM,CAAC;QACZ,KAAK,UAAU,CAAC;QAChB,KAAK,UAAU;
|
|
1
|
+
{"version":3,"file":"schema-apply.js","sourceRoot":"","sources":["../../src/db/schema-apply.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,8 @@ export interface AdminFieldInput {
|
|
|
8
8
|
options?: string[] | undefined;
|
|
9
9
|
required?: boolean | undefined;
|
|
10
10
|
validation?: FieldValidation | undefined;
|
|
11
|
+
/** Target content type (or 'user') for a 'relationship' field (kywi-cms#12). */
|
|
12
|
+
relatedType?: string | undefined;
|
|
11
13
|
sortOrder?: number | undefined;
|
|
12
14
|
}
|
|
13
15
|
/** Load admin-defined fields for one content type. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-field-queries.d.ts","sourceRoot":"","sources":["../../src/db/schema-field-queries.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAE1E,MAAM,WAAW,eAAe;IAC9B,eAAe,EAAE,MAAM,CAAA;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;IAC9B,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC9B,UAAU,CAAC,EAAE,eAAe,GAAG,SAAS,CAAA;IACxC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC/B;
|
|
1
|
+
{"version":3,"file":"schema-field-queries.d.ts","sourceRoot":"","sources":["../../src/db/schema-field-queries.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAE1E,MAAM,WAAW,eAAe;IAC9B,eAAe,EAAE,MAAM,CAAA;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;IAC9B,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC9B,UAAU,CAAC,EAAE,eAAe,GAAG,SAAS,CAAA;IACxC,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAChC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC/B;AAkBD,sDAAsD;AACtD,wBAAsB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAA;AACtG,6DAA6D;AAC7D,wBAAsB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC,CAAC,CAAA;AA4B1F,wBAAsB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BtF;AAED,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,MAAM,EACV,eAAe,EAAE,MAAM,EACvB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,OAAO,CAAC,CAWlB;AAED,8FAA8F;AAC9F,wBAAsB,wBAAwB,CAAC,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIjG"}
|
|
@@ -3,6 +3,7 @@ import { kywiContentTypeFields } from '../schema/base.js';
|
|
|
3
3
|
function rowToFieldDef(row) {
|
|
4
4
|
const options = row.options ?? undefined;
|
|
5
5
|
const validation = row.validation ?? undefined;
|
|
6
|
+
const relatedType = row.relatedType ?? undefined;
|
|
6
7
|
return {
|
|
7
8
|
name: row.name,
|
|
8
9
|
type: row.type,
|
|
@@ -10,6 +11,7 @@ function rowToFieldDef(row) {
|
|
|
10
11
|
required: row.required,
|
|
11
12
|
...(options !== undefined && { options }),
|
|
12
13
|
...(validation !== undefined && { validation }),
|
|
14
|
+
...(relatedType !== undefined && { relatedType }),
|
|
13
15
|
source: 'admin',
|
|
14
16
|
};
|
|
15
17
|
}
|
|
@@ -45,6 +47,7 @@ export async function saveAdminField(db, input) {
|
|
|
45
47
|
options: input.options ?? null,
|
|
46
48
|
required: input.required ?? false,
|
|
47
49
|
validation: input.validation ?? null,
|
|
50
|
+
relatedType: input.relatedType ?? null,
|
|
48
51
|
sortOrder: input.sortOrder ?? 0,
|
|
49
52
|
})
|
|
50
53
|
.onConflictDoUpdate({
|
|
@@ -55,6 +58,7 @@ export async function saveAdminField(db, input) {
|
|
|
55
58
|
options: input.options ?? null,
|
|
56
59
|
required: input.required ?? false,
|
|
57
60
|
validation: input.validation ?? null,
|
|
61
|
+
relatedType: input.relatedType ?? null,
|
|
58
62
|
sortOrder: input.sortOrder ?? 0,
|
|
59
63
|
updatedAt: new Date(),
|
|
60
64
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-field-queries.js","sourceRoot":"","sources":["../../src/db/schema-field-queries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AAErC,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"schema-field-queries.js","sourceRoot":"","sources":["../../src/db/schema-field-queries.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,9 +7,9 @@ export declare function activatePlugin(db: KywiDb, siteId: string, pluginPackage
|
|
|
7
7
|
id: string;
|
|
8
8
|
siteId: string;
|
|
9
9
|
updatedAt: Date;
|
|
10
|
-
config: unknown;
|
|
11
10
|
createdAt: Date;
|
|
12
11
|
isActive: boolean;
|
|
12
|
+
config: unknown;
|
|
13
13
|
pluginPackage: string;
|
|
14
14
|
}>;
|
|
15
15
|
export declare function deactivatePlugin(db: KywiDb, siteId: string, pluginPackage: string): Promise<{
|
|
@@ -25,9 +25,9 @@ export declare function listPluginsForSite(db: KywiDb, siteId: string, activeOnl
|
|
|
25
25
|
id: string;
|
|
26
26
|
siteId: string;
|
|
27
27
|
updatedAt: Date;
|
|
28
|
-
config: unknown;
|
|
29
28
|
createdAt: Date;
|
|
30
29
|
isActive: boolean;
|
|
30
|
+
config: unknown;
|
|
31
31
|
pluginPackage: string;
|
|
32
32
|
}[]>;
|
|
33
33
|
export declare function getPluginConfig(db: KywiDb, siteId: string, pluginPackage: string): Promise<Record<string, unknown> | null>;
|
|
@@ -19,6 +19,18 @@ export declare function getUserById(db: KywiDb, id: string): Promise<KywiUsersRo
|
|
|
19
19
|
export declare function getUserGroups(db: KywiDb, userId: string): Promise<string[]>;
|
|
20
20
|
/**
|
|
21
21
|
* List users. If siteId is provided, return only users with a membership in that site.
|
|
22
|
+
*
|
|
23
|
+
* #40: this used to `innerJoin` kywi_site_memberships and filter on siteId —
|
|
24
|
+
* correct when a user has exactly one membership row for that site, but
|
|
25
|
+
* `kywi_site_memberships` has no uniqueness constraint on (userId, siteId), so
|
|
26
|
+
* a duplicate row (e.g. the New User form granting the same site twice — once
|
|
27
|
+
* implicitly via POST /users, once explicitly via POST /users/:id/sites/:sid)
|
|
28
|
+
* fanned the join out into one kywi_users row PER membership row, rendering
|
|
29
|
+
* the same user 2-3x in All Users, the ACL "Grant to → User" dropdown (both
|
|
30
|
+
* read this same query), and — downstream — the group-members panel (which
|
|
31
|
+
* filters this same user list by membership id). Filtering by an `IN`
|
|
32
|
+
* subquery instead of joining can never fan out kywi_users' own rows, no
|
|
33
|
+
* matter how many (or how few, post schema fix) membership rows exist.
|
|
22
34
|
*/
|
|
23
35
|
export declare function listUsers(db: KywiDb, siteId?: string): Promise<KywiUsersRow[]>;
|
|
24
36
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-queries.d.ts","sourceRoot":"","sources":["../../src/db/user-queries.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAClE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAGrD;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,GAAG,MAAM,CAAC,EACvC,UAAU,EAAE,MAAM,EAAE,GACnB,WAAW,CAMb;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAO9B;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAOtF;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAOjF;AAED
|
|
1
|
+
{"version":3,"file":"user-queries.d.ts","sourceRoot":"","sources":["../../src/db/user-queries.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAClE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAGrD;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,GAAG,MAAM,CAAC,EACvC,UAAU,EAAE,MAAM,EAAE,GACnB,WAAW,CAMb;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAO9B;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAOtF;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAOjF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAgBpF;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9E,OAAO,CAAC,YAAY,CAAC,CAYvB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,GAAG,WAAW,CAAC,CAAC,GACpD,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAO9B;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAMzE;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK3E;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE;IAAE,iBAAiB,EAAE,IAAI,GAAG,IAAI,CAAA;CAAE,EACxC,UAAU,EAAE,MAAM,GACjB,OAAO,CAIT"}
|
package/dist/db/user-queries.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { eq,
|
|
1
|
+
import { eq, inArray } from 'drizzle-orm';
|
|
2
2
|
import { kywiUsers, kywiUserGroups, kywiGroups, kywiSiteMemberships } from '../schema/base.js';
|
|
3
3
|
import { hashPassword } from '../auth/passwords.js';
|
|
4
4
|
/**
|
|
@@ -46,14 +46,28 @@ export async function getUserGroups(db, userId) {
|
|
|
46
46
|
}
|
|
47
47
|
/**
|
|
48
48
|
* List users. If siteId is provided, return only users with a membership in that site.
|
|
49
|
+
*
|
|
50
|
+
* #40: this used to `innerJoin` kywi_site_memberships and filter on siteId —
|
|
51
|
+
* correct when a user has exactly one membership row for that site, but
|
|
52
|
+
* `kywi_site_memberships` has no uniqueness constraint on (userId, siteId), so
|
|
53
|
+
* a duplicate row (e.g. the New User form granting the same site twice — once
|
|
54
|
+
* implicitly via POST /users, once explicitly via POST /users/:id/sites/:sid)
|
|
55
|
+
* fanned the join out into one kywi_users row PER membership row, rendering
|
|
56
|
+
* the same user 2-3x in All Users, the ACL "Grant to → User" dropdown (both
|
|
57
|
+
* read this same query), and — downstream — the group-members panel (which
|
|
58
|
+
* filters this same user list by membership id). Filtering by an `IN`
|
|
59
|
+
* subquery instead of joining can never fan out kywi_users' own rows, no
|
|
60
|
+
* matter how many (or how few, post schema fix) membership rows exist.
|
|
49
61
|
*/
|
|
50
62
|
export async function listUsers(db, siteId) {
|
|
51
63
|
if (siteId) {
|
|
52
64
|
return db
|
|
53
|
-
.select(
|
|
65
|
+
.select()
|
|
54
66
|
.from(kywiUsers)
|
|
55
|
-
.
|
|
56
|
-
.
|
|
67
|
+
.where(inArray(kywiUsers.id, db
|
|
68
|
+
.select({ userId: kywiSiteMemberships.userId })
|
|
69
|
+
.from(kywiSiteMemberships)
|
|
70
|
+
.where(eq(kywiSiteMemberships.siteId, siteId))));
|
|
57
71
|
}
|
|
58
72
|
return db.select().from(kywiUsers);
|
|
59
73
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-queries.js","sourceRoot":"","sources":["../../src/db/user-queries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"user-queries.js","sourceRoot":"","sources":["../../src/db/user-queries.ts"],"names":[],"mappings":"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"}
|