@elytracms/studio 0.0.52 → 0.0.53
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/components/account/account-settings.js +4 -4
- package/dist/components/account/credential-panel.js +1 -1
- package/dist/components/account/self-account-view-source.js +3 -3
- package/dist/components/ai/ai-chat-panel-lazy.js +1 -1
- package/dist/components/ai/ai-chat-panel.js +4 -4
- package/dist/components/ai/ai-cms-panel.js +1 -1
- package/dist/components/ai/proposal-card.js +4 -4
- package/dist/components/ai/translate-document-action.js +1 -1
- package/dist/components/ai/translate-document-dialog.d.ts +1 -1
- package/dist/components/app-views/default-modules.d.ts +3 -3
- package/dist/components/app-views/default-modules.js +20 -20
- package/dist/components/app-views/sidebar.d.ts +1 -1
- package/dist/components/app-views/sidebar.js +2 -2
- package/dist/components/app-views/studio-config.d.ts +1 -1
- package/dist/components/assets/asset-detail.js +9 -9
- package/dist/components/assets/asset-grid.js +7 -7
- package/dist/components/assets/asset-thumb.d.ts +1 -1
- package/dist/components/assets/asset-thumb.js +2 -2
- package/dist/components/assets/assets-collection-view-source.js +3 -3
- package/dist/components/assets/assets-module.js +8 -8
- package/dist/components/assets/assets-store.d.ts +1 -1
- package/dist/components/assets/assets-store.js +1 -1
- package/dist/components/builder/blocks-model.js +1 -1
- package/dist/components/builder/blocks-panel.d.ts +1 -1
- package/dist/components/builder/blocks-panel.js +6 -6
- package/dist/components/builder/canvas.js +11 -11
- package/dist/components/builder/clipboard-actions.js +2 -2
- package/dist/components/builder/composition-field-editor-lazy.d.ts +1 -1
- package/dist/components/builder/composition-field-editor-lazy.js +1 -1
- package/dist/components/builder/composition-field-editor.d.ts +1 -1
- package/dist/components/builder/composition-field-editor.js +9 -9
- package/dist/components/builder/insert-context.d.ts +2 -2
- package/dist/components/builder/insert-context.js +2 -2
- package/dist/components/builder/insert-menu.d.ts +2 -2
- package/dist/components/builder/insert-menu.js +1 -1
- package/dist/components/builder/layout-inspector.js +1 -1
- package/dist/components/builder/page-tree.js +5 -5
- package/dist/components/builder/property-inspector.js +3 -3
- package/dist/components/builder/reuse-context.d.ts +1 -1
- package/dist/components/builder/reuse-context.js +3 -3
- package/dist/components/builder/spacing-handles.js +2 -2
- package/dist/components/cms/asset-picker.js +4 -4
- package/dist/components/cms/bulk-actions.js +1 -1
- package/dist/components/cms/bulk-bar.d.ts +1 -1
- package/dist/components/cms/bulk-bar.js +3 -3
- package/dist/components/cms/cell-edit.js +1 -1
- package/dist/components/cms/cell.js +2 -2
- package/dist/components/cms/cms-index.js +1 -1
- package/dist/components/cms/cms-store.d.ts +2 -2
- package/dist/components/cms/cms-store.js +6 -6
- package/dist/components/cms/collection-table.js +17 -17
- package/dist/components/cms/detail-editor.js +31 -31
- package/dist/components/cms/document-diff-view.js +4 -4
- package/dist/components/cms/editable-cell.d.ts +1 -1
- package/dist/components/cms/editable-cell.js +6 -6
- package/dist/components/cms/field-control.js +15 -15
- package/dist/components/cms/field-renderer.d.ts +2 -2
- package/dist/components/cms/filter-builder.js +3 -3
- package/dist/components/cms/import-export.js +1 -1
- package/dist/components/cms/issues-pane.js +1 -1
- package/dist/components/cms/prop-fields.js +3 -3
- package/dist/components/cms/reference-confirm.js +1 -1
- package/dist/components/cms/relation-picker.js +1 -1
- package/dist/components/cms/rich-text/block-commands.d.ts +1 -1
- package/dist/components/cms/rich-text/component-embed.js +2 -2
- package/dist/components/cms/rich-text/editor.js +8 -8
- package/dist/components/cms/rich-text/embed-inspector.d.ts +1 -1
- package/dist/components/cms/rich-text/embed-inspector.js +2 -2
- package/dist/components/cms/rich-text/embed-picker.js +1 -1
- package/dist/components/cms/rich-text/embed-props.js +1 -1
- package/dist/components/cms/rich-text/extensions.d.ts +1 -1
- package/dist/components/cms/rich-text/extensions.js +4 -4
- package/dist/components/cms/rich-text/index.d.ts +1 -1
- package/dist/components/cms/rich-text/index.js +1 -1
- package/dist/components/cms/rich-text/insert.d.ts +1 -1
- package/dist/components/cms/rich-text/lazy.d.ts +1 -1
- package/dist/components/cms/rich-text/lazy.js +1 -1
- package/dist/components/cms/rich-text/slash-command.js +1 -1
- package/dist/components/cms/rich-text/toolbar.d.ts +1 -1
- package/dist/components/cms/rich-text/toolbar.js +4 -4
- package/dist/components/cms/use-cell-edit.d.ts +1 -1
- package/dist/components/cms/use-cell-edit.js +2 -2
- package/dist/components/cms/use-compare-selection.d.ts +1 -1
- package/dist/components/cms/use-discard-controller.d.ts +1 -1
- package/dist/components/cms/use-discard-controller.js +2 -2
- package/dist/components/cms/use-document-versions.d.ts +1 -1
- package/dist/components/cms/use-document-versions.js +1 -1
- package/dist/components/cms/use-embed-inspector-host.d.ts +1 -1
- package/dist/components/cms/use-published-perspective.d.ts +2 -2
- package/dist/components/cms/use-published-perspective.js +2 -2
- package/dist/components/cms/use-restore-version.js +1 -1
- package/dist/components/cms/version-compare-lazy.js +1 -1
- package/dist/components/cms/version-compare.js +6 -6
- package/dist/components/cms/versions-model.d.ts +1 -1
- package/dist/components/cms/versions-pane.js +5 -5
- package/dist/components/cms/view-bar.js +2 -2
- package/dist/components/collab/collab-context.js +1 -1
- package/dist/components/collection-view/cms-collection-view-source.js +2 -2
- package/dist/components/components/component-preview.js +3 -3
- package/dist/components/components/components-index.js +2 -2
- package/dist/components/components/registry-browser.js +2 -2
- package/dist/components/components/transfer-dialog.js +5 -5
- package/dist/components/components/transfer.js +4 -4
- package/dist/components/current-user-menu.js +2 -2
- package/dist/components/delivery-health-banner.js +2 -2
- package/dist/components/operation-error.js +1 -1
- package/dist/components/project-list.js +5 -5
- package/dist/components/project-session.js +1 -1
- package/dist/components/project-switcher.js +3 -3
- package/dist/components/rail-store-status.js +1 -1
- package/dist/components/redirects/redirects-collection-view-source.js +3 -3
- package/dist/components/redirects/redirects-module.js +6 -6
- package/dist/components/section-nav.js +3 -3
- package/dist/components/section-surface.js +1 -1
- package/dist/components/studio-project-screen.js +7 -7
- package/dist/components/studio-shell.js +9 -9
- package/dist/components/use-hydration-phase.js +1 -1
- package/dist/components/users/users-collection-view-source.js +4 -4
- package/dist/components/users/users-module.js +9 -9
- package/dist/components/workspace-projects.js +1 -1
- package/dist/customization.d.ts +9 -9
- package/dist/customization.js +5 -5
- package/dist/lib/ai/anthropic-provider.d.ts +1 -1
- package/dist/lib/ai/apply-content.d.ts +1 -1
- package/dist/lib/ai/apply-content.js +3 -3
- package/dist/lib/ai/chat-state.d.ts +2 -2
- package/dist/lib/ai/config.d.ts +1 -1
- package/dist/lib/ai/create-flow.d.ts +2 -2
- package/dist/lib/ai/create-flow.js +3 -3
- package/dist/lib/ai/fake-provider.d.ts +1 -1
- package/dist/lib/ai/index.d.ts +15 -15
- package/dist/lib/ai/index.js +15 -15
- package/dist/lib/ai/knowledge.d.ts +1 -1
- package/dist/lib/ai/provenance.d.ts +1 -1
- package/dist/lib/ai/route-provider.d.ts +1 -1
- package/dist/lib/ai/route.d.ts +1 -1
- package/dist/lib/ai/shape.d.ts +1 -1
- package/dist/lib/ai/translate-document.d.ts +1 -1
- package/dist/lib/ai/translate-document.js +3 -3
- package/dist/lib/ai-panel.js +1 -1
- package/dist/lib/assets/index.d.ts +4 -4
- package/dist/lib/assets/index.js +4 -4
- package/dist/lib/assets/upload.d.ts +2 -2
- package/dist/lib/assets/upload.js +2 -2
- package/dist/lib/auth/convex-auth-adapter.d.ts +2 -2
- package/dist/lib/auth/convex-auth-adapter.js +1 -1
- package/dist/lib/auth/dev-auto-login-adapter.d.ts +1 -1
- package/dist/lib/auth/index.d.ts +9 -9
- package/dist/lib/auth/index.js +10 -10
- package/dist/lib/auth/local-auth-adapter.d.ts +1 -1
- package/dist/lib/auth/route-guard.d.ts +1 -1
- package/dist/lib/auth-errors.d.ts +1 -1
- package/dist/lib/clipboard/index.d.ts +3 -3
- package/dist/lib/clipboard/index.js +3 -3
- package/dist/lib/cms/published-documents.d.ts +1 -1
- package/dist/lib/cms-views/index.d.ts +2 -2
- package/dist/lib/cms-views/index.js +2 -2
- package/dist/lib/collection-view/collection-view-source.d.ts +4 -4
- package/dist/lib/data/collection-content.js +1 -1
- package/dist/lib/data/data-store.js +6 -6
- package/dist/lib/data/index.d.ts +4 -4
- package/dist/lib/data/index.js +4 -4
- package/dist/lib/data/sample-capture.js +4 -4
- package/dist/lib/data/sources-store.d.ts +1 -1
- package/dist/lib/diff-view-preference.js +1 -1
- package/dist/lib/dnd/gap-drag.d.ts +1 -1
- package/dist/lib/i18n/i18n.d.ts +1 -1
- package/dist/lib/i18n/i18n.js +1 -1
- package/dist/lib/i18n/index.d.ts +4 -4
- package/dist/lib/i18n/index.js +3 -3
- package/dist/lib/i18n/messages.en.d.ts +1 -1
- package/dist/lib/i18n/messages.en.js +1 -1
- package/dist/lib/locale/binding-fallback.d.ts +1 -1
- package/dist/lib/locale/binding-fallback.js +2 -2
- package/dist/lib/locale/index.d.ts +6 -6
- package/dist/lib/locale/index.js +6 -6
- package/dist/lib/locale/locale-switcher.js +3 -3
- package/dist/lib/locale/use-studio-locale.js +1 -1
- package/dist/lib/operations/asset-repository.d.ts +1 -1
- package/dist/lib/operations/cms-persistence.d.ts +1 -1
- package/dist/lib/operations/cms-persistence.js +1 -1
- package/dist/lib/operations/index.d.ts +6 -6
- package/dist/lib/operations/index.js +6 -6
- package/dist/lib/operations/session-hydration.d.ts +1 -1
- package/dist/lib/operations/session-hydration.js +1 -1
- package/dist/lib/operations/studio-operations.d.ts +1 -1
- package/dist/lib/operations/studio-operations.js +3 -3
- package/dist/lib/persistence/convex-adapter.js +2 -2
- package/dist/lib/persistence/convex-blob-storage.d.ts +1 -1
- package/dist/lib/persistence/convex-blob-storage.js +1 -1
- package/dist/lib/persistence/deployment-readiness.d.ts +2 -2
- package/dist/lib/persistence/index.d.ts +6 -6
- package/dist/lib/persistence/index.js +7 -7
- package/dist/lib/persona/labels.js +1 -1
- package/dist/lib/query/index.d.ts +2 -2
- package/dist/lib/query/index.js +1 -1
- package/dist/lib/rail.js +1 -1
- package/dist/lib/references/impact.d.ts +1 -1
- package/dist/lib/references/impact.js +1 -1
- package/dist/lib/references/index.d.ts +3 -3
- package/dist/lib/references/index.js +3 -3
- package/dist/lib/references/references-store.d.ts +2 -2
- package/dist/lib/references/references-store.js +3 -3
- package/dist/lib/registry/index.js +2 -2
- package/dist/lib/theme.js +1 -1
- package/dist/lib/webhooks/config.d.ts +1 -1
- package/dist/lib/webhooks/config.js +2 -2
- package/dist/lib/webhooks/dispatcher.js +2 -2
- package/dist/lib/webhooks/index.d.ts +6 -6
- package/dist/lib/webhooks/index.js +4 -4
- package/dist/lib/workspace/index.d.ts +7 -7
- package/dist/lib/workspace/index.js +3 -3
- package/dist/lib/workspace/switcher-source.d.ts +1 -1
- package/dist/router/index.d.ts +1 -1
- package/dist/router/index.js +1 -1
- package/dist/ui/avatar.js +1 -1
- package/dist/ui/badge.js +1 -1
- package/dist/ui/button.js +1 -1
- package/dist/ui/card.js +1 -1
- package/dist/ui/collapsible-section.js +2 -2
- package/dist/ui/dialog.js +1 -1
- package/dist/ui/dropdown-menu.js +1 -1
- package/dist/ui/field.js +1 -1
- package/dist/ui/index.d.ts +19 -19
- package/dist/ui/index.js +19 -19
- package/dist/ui/input.js +1 -1
- package/dist/ui/inspector.js +1 -1
- package/dist/ui/layout.js +1 -1
- package/dist/ui/panel.js +2 -2
- package/dist/ui/popover.js +1 -1
- package/dist/ui/row-item.js +2 -2
- package/dist/ui/segmented-control.js +1 -1
- package/dist/ui/separator.js +1 -1
- package/dist/ui/toolbar.js +2 -2
- package/dist/ui/typography.js +1 -1
- package/package.json +3 -3
- package/dist/components/assets/asset-library.d.ts +0 -14
- package/dist/components/assets/asset-library.js +0 -202
- package/dist/components/assets/asset-library.js.map +0 -1
- package/dist/components/backend-gate.d.ts +0 -19
- package/dist/components/backend-gate.js +0 -64
- package/dist/components/backend-gate.js.map +0 -1
- package/dist/components/builder/composition-scope.d.ts +0 -16
- package/dist/components/builder/composition-scope.js +0 -7
- package/dist/components/builder/composition-scope.js.map +0 -1
- package/dist/components/cms/alias-selector.d.ts +0 -20
- package/dist/components/cms/alias-selector.js +0 -34
- package/dist/components/cms/alias-selector.js.map +0 -1
- package/dist/components/cms/collections-sidebar.d.ts +0 -18
- package/dist/components/cms/collections-sidebar.js +0 -36
- package/dist/components/cms/collections-sidebar.js.map +0 -1
- package/dist/components/cms/new-page-dialog.d.ts +0 -22
- package/dist/components/cms/new-page-dialog.js +0 -42
- package/dist/components/cms/new-page-dialog.js.map +0 -1
- package/dist/components/cms/rich-text/embed-control.d.ts +0 -17
- package/dist/components/cms/rich-text/embed-control.js +0 -62
- package/dist/components/cms/rich-text/embed-control.js.map +0 -1
- package/dist/components/cms/rich-text/image-control.d.ts +0 -16
- package/dist/components/cms/rich-text/image-control.js +0 -36
- package/dist/components/cms/rich-text/image-control.js.map +0 -1
- package/dist/components/components/fixture-runner.d.ts +0 -10
- package/dist/components/components/fixture-runner.js +0 -27
- package/dist/components/components/fixture-runner.js.map +0 -1
- package/dist/components/references/builder-deep-link.d.ts +0 -12
- package/dist/components/references/builder-deep-link.js +0 -53
- package/dist/components/references/builder-deep-link.js.map +0 -1
- package/dist/components/routes/redirect-chain.d.ts +0 -9
- package/dist/components/routes/redirect-chain.js +0 -16
- package/dist/components/routes/redirect-chain.js.map +0 -1
- package/dist/components/routes/redirect-manager.d.ts +0 -13
- package/dist/components/routes/redirect-manager.js +0 -24
- package/dist/components/routes/redirect-manager.js.map +0 -1
- package/dist/components/routes/route-list.d.ts +0 -35
- package/dist/components/routes/route-list.js +0 -69
- package/dist/components/routes/route-list.js.map +0 -1
- package/dist/components/routes/routes-shell.d.ts +0 -14
- package/dist/components/routes/routes-shell.js +0 -68
- package/dist/components/routes/routes-shell.js.map +0 -1
- package/dist/components/sections.d.ts +0 -37
- package/dist/components/sections.js +0 -62
- package/dist/components/sections.js.map +0 -1
- package/dist/components/users/user-search.d.ts +0 -8
- package/dist/components/users/user-search.js +0 -13
- package/dist/components/users/user-search.js.map +0 -1
- package/dist/components/workspace-gate.d.ts +0 -12
- package/dist/components/workspace-gate.js +0 -28
- package/dist/components/workspace-gate.js.map +0 -1
- package/dist/lib/cms-views/views-store.d.ts +0 -70
- package/dist/lib/cms-views/views-store.js +0 -129
- package/dist/lib/cms-views/views-store.js.map +0 -1
- package/dist/lib/operations/graph-commands.d.ts +0 -136
- package/dist/lib/operations/graph-commands.js +0 -85
- package/dist/lib/operations/graph-commands.js.map +0 -1
- package/dist/lib/operations/graph-persistence.d.ts +0 -27
- package/dist/lib/operations/graph-persistence.js +0 -35
- package/dist/lib/operations/graph-persistence.js.map +0 -1
- package/dist/lib/routing/index.d.ts +0 -10
- package/dist/lib/routing/index.js +0 -11
- package/dist/lib/routing/index.js.map +0 -1
- package/dist/lib/routing/routing-analysis.d.ts +0 -26
- package/dist/lib/routing/routing-analysis.js +0 -37
- package/dist/lib/routing/routing-analysis.js.map +0 -1
- package/dist/lib/routing/routing-store.d.ts +0 -50
- package/dist/lib/routing/routing-store.js +0 -72
- package/dist/lib/routing/routing-store.js.map +0 -1
- package/dist/lib/working-graph.d.ts +0 -82
- package/dist/lib/working-graph.js +0 -113
- package/dist/lib/working-graph.js.map +0 -1
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import type { CmsDocument, CollectionDef } from '@elytracms/core/cms-core';
|
|
3
|
-
import type { OperationResult, OperationsClient } from '../operations';
|
|
4
|
-
/**
|
|
5
|
-
* Saved-view persistence for the CMS collection table (EC-169).
|
|
6
|
-
*
|
|
7
|
-
* Views are project-scoped (shared by every editor on the project) and follow
|
|
8
|
-
* the EC-170 routing-store pattern: one system collection holds one document
|
|
9
|
-
* per saved view, and every mutation goes through the *existing*
|
|
10
|
-
* `@elytracms/core/operations` commands (`schema.upsertCollection`,
|
|
11
|
-
* `documents.upsert`, `documents.delete`). The settings domain was the other
|
|
12
|
-
* candidate, but `settings.update` patches the closed `projectSettingsSchema`
|
|
13
|
-
* (locales/environments/export target) — saved views don't fit it without a
|
|
14
|
-
* studio-core schema change, while the system collection needs no new
|
|
15
|
-
* operations surface at all.
|
|
16
|
-
*
|
|
17
|
-
* Deleting a saved view is exactly one `documents.delete` against THIS
|
|
18
|
-
* collection — it can never touch content documents.
|
|
19
|
-
*/
|
|
20
|
-
export declare const VIEWS_COLLECTION = "cms-saved-views";
|
|
21
|
-
/** System collection holding one document per {@link SavedViewRecord}. */
|
|
22
|
-
export declare const viewsCollectionDef: CollectionDef;
|
|
23
|
-
/** A persisted saved view: identity + the table state it restores. */
|
|
24
|
-
export declare const savedViewRecordSchema: z.ZodObject<{
|
|
25
|
-
id: z.ZodString;
|
|
26
|
-
name: z.ZodString;
|
|
27
|
-
collection: z.ZodString;
|
|
28
|
-
state: z.ZodObject<{
|
|
29
|
-
filters: z.ZodArray<z.ZodObject<{
|
|
30
|
-
field: z.ZodString;
|
|
31
|
-
op: z.ZodEnum<{
|
|
32
|
-
in: "in";
|
|
33
|
-
eq: "eq";
|
|
34
|
-
gt: "gt";
|
|
35
|
-
gte: "gte";
|
|
36
|
-
lt: "lt";
|
|
37
|
-
lte: "lte";
|
|
38
|
-
}>;
|
|
39
|
-
value: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>]>;
|
|
40
|
-
}, z.core.$strip>>;
|
|
41
|
-
sort: z.ZodNullable<z.ZodObject<{
|
|
42
|
-
field: z.ZodString;
|
|
43
|
-
dir: z.ZodEnum<{
|
|
44
|
-
desc: "desc";
|
|
45
|
-
asc: "asc";
|
|
46
|
-
}>;
|
|
47
|
-
}, z.core.$strip>>;
|
|
48
|
-
columns: z.ZodArray<z.ZodString>;
|
|
49
|
-
hidden: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
50
|
-
}, z.core.$strip>;
|
|
51
|
-
}, z.core.$strip>;
|
|
52
|
-
export type SavedViewRecord = z.infer<typeof savedViewRecordSchema>;
|
|
53
|
-
export declare function viewToDocument(record: SavedViewRecord): CmsDocument;
|
|
54
|
-
export declare function documentToView(document: CmsDocument): SavedViewRecord | undefined;
|
|
55
|
-
/** Load every persisted saved view of a project (malformed records dropped). */
|
|
56
|
-
export declare function loadSavedViews(operations: OperationsClient, projectId: string): Promise<OperationResult<SavedViewRecord[]>>;
|
|
57
|
-
/** Group loaded records by their content collection (for per-collection lookup). */
|
|
58
|
-
export declare function groupSavedViews(records: readonly SavedViewRecord[]): Record<string, SavedViewRecord[]>;
|
|
59
|
-
/**
|
|
60
|
-
* Make sure the system collection exists in the project's CMS schema so
|
|
61
|
-
* `documents.upsert` accepts view documents. Idempotent. Callers that share a
|
|
62
|
-
* project with the CMS session must run the session's persisted baseline
|
|
63
|
-
* FIRST — creating this collection on a schema-less project would otherwise
|
|
64
|
-
* make the baseline think the content schema is already persisted.
|
|
65
|
-
*/
|
|
66
|
-
export declare function ensureViewsCollection(_operations: OperationsClient, _projectId: string): Promise<OperationResult<void>>;
|
|
67
|
-
/** Create or update a saved view (operations command). */
|
|
68
|
-
export declare function saveSavedView(operations: OperationsClient, projectId: string, record: SavedViewRecord): Promise<OperationResult<void>>;
|
|
69
|
-
/** Delete a saved view — a view-only operation on the system collection. */
|
|
70
|
-
export declare function deleteSavedView(operations: OperationsClient, projectId: string, viewId: string): Promise<OperationResult<void>>;
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { tableViewStateSchema } from './view-model';
|
|
3
|
-
/**
|
|
4
|
-
* Saved-view persistence for the CMS collection table (EC-169).
|
|
5
|
-
*
|
|
6
|
-
* Views are project-scoped (shared by every editor on the project) and follow
|
|
7
|
-
* the EC-170 routing-store pattern: one system collection holds one document
|
|
8
|
-
* per saved view, and every mutation goes through the *existing*
|
|
9
|
-
* `@elytracms/core/operations` commands (`schema.upsertCollection`,
|
|
10
|
-
* `documents.upsert`, `documents.delete`). The settings domain was the other
|
|
11
|
-
* candidate, but `settings.update` patches the closed `projectSettingsSchema`
|
|
12
|
-
* (locales/environments/export target) — saved views don't fit it without a
|
|
13
|
-
* studio-core schema change, while the system collection needs no new
|
|
14
|
-
* operations surface at all.
|
|
15
|
-
*
|
|
16
|
-
* Deleting a saved view is exactly one `documents.delete` against THIS
|
|
17
|
-
* collection — it can never touch content documents.
|
|
18
|
-
*/
|
|
19
|
-
export const VIEWS_COLLECTION = 'cms-saved-views';
|
|
20
|
-
/** System collection holding one document per {@link SavedViewRecord}. */
|
|
21
|
-
export const viewsCollectionDef = {
|
|
22
|
-
id: VIEWS_COLLECTION,
|
|
23
|
-
kind: 'document',
|
|
24
|
-
titleField: 'name',
|
|
25
|
-
form: {
|
|
26
|
-
label: 'Saved views',
|
|
27
|
-
labelSingular: 'Saved view',
|
|
28
|
-
description: 'System collection managed by the CMS collection table.',
|
|
29
|
-
},
|
|
30
|
-
fields: [
|
|
31
|
-
{ name: 'name', type: 'text', validation: { required: true } },
|
|
32
|
-
{ name: 'collection', type: 'text', validation: { required: true } },
|
|
33
|
-
/** The view's filter/sort/column state, JSON-serialized (validated by Zod on read). */
|
|
34
|
-
{ name: 'config', type: 'text', validation: { required: true } },
|
|
35
|
-
],
|
|
36
|
-
};
|
|
37
|
-
/** A persisted saved view: identity + the table state it restores. */
|
|
38
|
-
export const savedViewRecordSchema = z.object({
|
|
39
|
-
id: z.string().min(1),
|
|
40
|
-
name: z.string().min(1),
|
|
41
|
-
/** The content collection the view belongs to. */
|
|
42
|
-
collection: z.string().min(1),
|
|
43
|
-
state: tableViewStateSchema,
|
|
44
|
-
});
|
|
45
|
-
// ---- Record ⇄ document mapping ----
|
|
46
|
-
export function viewToDocument(record) {
|
|
47
|
-
const parsed = savedViewRecordSchema.parse(record);
|
|
48
|
-
return {
|
|
49
|
-
collection: VIEWS_COLLECTION,
|
|
50
|
-
id: parsed.id,
|
|
51
|
-
values: {
|
|
52
|
-
name: parsed.name,
|
|
53
|
-
collection: parsed.collection,
|
|
54
|
-
config: JSON.stringify(parsed.state),
|
|
55
|
-
},
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
export function documentToView(document) {
|
|
59
|
-
const values = document.values;
|
|
60
|
-
let state;
|
|
61
|
-
try {
|
|
62
|
-
state = typeof values.config === 'string' ? JSON.parse(values.config) : undefined;
|
|
63
|
-
}
|
|
64
|
-
catch {
|
|
65
|
-
return undefined;
|
|
66
|
-
}
|
|
67
|
-
const parsed = savedViewRecordSchema.safeParse({
|
|
68
|
-
id: document.id,
|
|
69
|
-
name: values.name,
|
|
70
|
-
collection: values.collection,
|
|
71
|
-
state,
|
|
72
|
-
});
|
|
73
|
-
return parsed.success ? parsed.data : undefined;
|
|
74
|
-
}
|
|
75
|
-
// ---- Reads & writes through @elytracms/operations ----
|
|
76
|
-
/** Load every persisted saved view of a project (malformed records dropped). */
|
|
77
|
-
export async function loadSavedViews(operations, projectId) {
|
|
78
|
-
const result = await operations.documents.list({ projectId, collection: VIEWS_COLLECTION });
|
|
79
|
-
if (!result.ok)
|
|
80
|
-
return result;
|
|
81
|
-
return {
|
|
82
|
-
ok: true,
|
|
83
|
-
value: result.value
|
|
84
|
-
.map((record) => documentToView(record.document))
|
|
85
|
-
.filter((view) => view !== undefined),
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
/** Group loaded records by their content collection (for per-collection lookup). */
|
|
89
|
-
export function groupSavedViews(records) {
|
|
90
|
-
const grouped = {};
|
|
91
|
-
for (const record of records) {
|
|
92
|
-
;
|
|
93
|
-
(grouped[record.collection] ??= []).push(record);
|
|
94
|
-
}
|
|
95
|
-
return grouped;
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Make sure the system collection exists in the project's CMS schema so
|
|
99
|
-
* `documents.upsert` accepts view documents. Idempotent. Callers that share a
|
|
100
|
-
* project with the CMS session must run the session's persisted baseline
|
|
101
|
-
* FIRST — creating this collection on a schema-less project would otherwise
|
|
102
|
-
* make the baseline think the content schema is already persisted.
|
|
103
|
-
*/
|
|
104
|
-
export async function ensureViewsCollection(_operations, _projectId) {
|
|
105
|
-
// No-op (EC-183, AD-11): the saved-views system collection is config-owned and
|
|
106
|
-
// the backend stores documents without a schema-membership check — nothing to
|
|
107
|
-
// register. `viewsCollectionDef` remains the canonical document shape.
|
|
108
|
-
return { ok: true, value: undefined };
|
|
109
|
-
}
|
|
110
|
-
/** Create or update a saved view (operations command). */
|
|
111
|
-
export async function saveSavedView(operations, projectId, record) {
|
|
112
|
-
const ensured = await ensureViewsCollection(operations, projectId);
|
|
113
|
-
if (!ensured.ok)
|
|
114
|
-
return ensured;
|
|
115
|
-
const result = await operations.documents.upsert({
|
|
116
|
-
projectId,
|
|
117
|
-
document: viewToDocument(record),
|
|
118
|
-
});
|
|
119
|
-
return result.ok ? { ok: true, value: undefined } : result;
|
|
120
|
-
}
|
|
121
|
-
/** Delete a saved view — a view-only operation on the system collection. */
|
|
122
|
-
export async function deleteSavedView(operations, projectId, viewId) {
|
|
123
|
-
const result = await operations.documents.delete({
|
|
124
|
-
projectId,
|
|
125
|
-
ref: { collection: VIEWS_COLLECTION, id: viewId },
|
|
126
|
-
});
|
|
127
|
-
return result.ok ? { ok: true, value: undefined } : result;
|
|
128
|
-
}
|
|
129
|
-
//# sourceMappingURL=views-store.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"views-store.js","sourceRoot":"","sources":["../../../src/lib/cms-views/views-store.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod'\nimport type { CmsDocument, CollectionDef } from '@elytracms/core/cms-core'\nimport type { OperationResult, OperationsClient } from '../operations'\nimport { tableViewStateSchema } from './view-model'\n\n/**\n * Saved-view persistence for the CMS collection table (EC-169).\n *\n * Views are project-scoped (shared by every editor on the project) and follow\n * the EC-170 routing-store pattern: one system collection holds one document\n * per saved view, and every mutation goes through the *existing*\n * `@elytracms/core/operations` commands (`schema.upsertCollection`,\n * `documents.upsert`, `documents.delete`). The settings domain was the other\n * candidate, but `settings.update` patches the closed `projectSettingsSchema`\n * (locales/environments/export target) — saved views don't fit it without a\n * studio-core schema change, while the system collection needs no new\n * operations surface at all.\n *\n * Deleting a saved view is exactly one `documents.delete` against THIS\n * collection — it can never touch content documents.\n */\n\nexport const VIEWS_COLLECTION = 'cms-saved-views'\n\n/** System collection holding one document per {@link SavedViewRecord}. */\nexport const viewsCollectionDef: CollectionDef = {\n id: VIEWS_COLLECTION,\n kind: 'document',\n titleField: 'name',\n form: {\n label: 'Saved views',\n labelSingular: 'Saved view',\n description: 'System collection managed by the CMS collection table.',\n },\n fields: [\n { name: 'name', type: 'text', validation: { required: true } },\n { name: 'collection', type: 'text', validation: { required: true } },\n /** The view's filter/sort/column state, JSON-serialized (validated by Zod on read). */\n { name: 'config', type: 'text', validation: { required: true } },\n ],\n}\n\n/** A persisted saved view: identity + the table state it restores. */\nexport const savedViewRecordSchema = z.object({\n id: z.string().min(1),\n name: z.string().min(1),\n /** The content collection the view belongs to. */\n collection: z.string().min(1),\n state: tableViewStateSchema,\n})\nexport type SavedViewRecord = z.infer<typeof savedViewRecordSchema>\n\n// ---- Record ⇄ document mapping ----\n\nexport function viewToDocument(record: SavedViewRecord): CmsDocument {\n const parsed = savedViewRecordSchema.parse(record)\n return {\n collection: VIEWS_COLLECTION,\n id: parsed.id,\n values: {\n name: parsed.name,\n collection: parsed.collection,\n config: JSON.stringify(parsed.state),\n },\n }\n}\n\nexport function documentToView(document: CmsDocument): SavedViewRecord | undefined {\n const values = document.values\n let state: unknown\n try {\n state = typeof values.config === 'string' ? JSON.parse(values.config) : undefined\n } catch {\n return undefined\n }\n const parsed = savedViewRecordSchema.safeParse({\n id: document.id,\n name: values.name,\n collection: values.collection,\n state,\n })\n return parsed.success ? parsed.data : undefined\n}\n\n// ---- Reads & writes through @elytracms/operations ----\n\n/** Load every persisted saved view of a project (malformed records dropped). */\nexport async function loadSavedViews(\n operations: OperationsClient,\n projectId: string,\n): Promise<OperationResult<SavedViewRecord[]>> {\n const result = await operations.documents.list({ projectId, collection: VIEWS_COLLECTION })\n if (!result.ok) return result\n return {\n ok: true,\n value: result.value\n .map((record) => documentToView(record.document))\n .filter((view): view is SavedViewRecord => view !== undefined),\n }\n}\n\n/** Group loaded records by their content collection (for per-collection lookup). */\nexport function groupSavedViews(\n records: readonly SavedViewRecord[],\n): Record<string, SavedViewRecord[]> {\n const grouped: Record<string, SavedViewRecord[]> = {}\n for (const record of records) {\n ;(grouped[record.collection] ??= []).push(record)\n }\n return grouped\n}\n\n/**\n * Make sure the system collection exists in the project's CMS schema so\n * `documents.upsert` accepts view documents. Idempotent. Callers that share a\n * project with the CMS session must run the session's persisted baseline\n * FIRST — creating this collection on a schema-less project would otherwise\n * make the baseline think the content schema is already persisted.\n */\nexport async function ensureViewsCollection(\n _operations: OperationsClient,\n _projectId: string,\n): Promise<OperationResult<void>> {\n // No-op (EC-183, AD-11): the saved-views system collection is config-owned and\n // the backend stores documents without a schema-membership check — nothing to\n // register. `viewsCollectionDef` remains the canonical document shape.\n return { ok: true, value: undefined }\n}\n\n/** Create or update a saved view (operations command). */\nexport async function saveSavedView(\n operations: OperationsClient,\n projectId: string,\n record: SavedViewRecord,\n): Promise<OperationResult<void>> {\n const ensured = await ensureViewsCollection(operations, projectId)\n if (!ensured.ok) return ensured\n const result = await operations.documents.upsert({\n projectId,\n document: viewToDocument(record),\n })\n return result.ok ? { ok: true, value: undefined } : result\n}\n\n/** Delete a saved view — a view-only operation on the system collection. */\nexport async function deleteSavedView(\n operations: OperationsClient,\n projectId: string,\n viewId: string,\n): Promise<OperationResult<void>> {\n const result = await operations.documents.delete({\n projectId,\n ref: { collection: VIEWS_COLLECTION, id: viewId },\n })\n return result.ok ? { ok: true, value: undefined } : result\n}\n"]}
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import type { ComponentNode, InsertTarget, ProjectGraph, PropValue } from '@elytracms/core/project-graph';
|
|
2
|
-
import type { WorkingGraph, WorkingPageSeo } from '../working-graph';
|
|
3
|
-
import type { OperationResult, OperationsClient } from './operations-package';
|
|
4
|
-
/**
|
|
5
|
-
* Builder action → graph operation mapping (EC-141, reshaped by EC-187).
|
|
6
|
-
*
|
|
7
|
-
* The canonical `ProjectGraph` is now LAYOUTS-ONLY, and the page-node graph
|
|
8
|
-
* commands (`graph.insertNode`/`removeNode`/`duplicateNode`/`moveNode`/
|
|
9
|
-
* `reorderNode`/`setNodeProp`/`removeNodeProp`/`setNodeCondition`) were DELETED
|
|
10
|
-
* from the operations layer — a page is a CMS document now, edited through the
|
|
11
|
-
* composition-field path, not mirrored as node ops. So every page-tree edit
|
|
12
|
-
* here returns `null`: the legacy `/builder` page editor is in-memory-only for
|
|
13
|
-
* page edits (it is retired in a later slice).
|
|
14
|
-
*
|
|
15
|
-
* What still persists: `loadGraph` (restoring a saved revision), `undo`, and
|
|
16
|
-
* `redo` each save the whole graph via `graph.save` — but a `graph.save`
|
|
17
|
-
* persists a CANONICAL layouts-only `ProjectGraph`, so the WorkingGraph
|
|
18
|
-
* `present` is converted via `toProjectGraph` before it is sent.
|
|
19
|
-
*/
|
|
20
|
-
/** The builder store's action union (owned here so the mapping stays React-free). */
|
|
21
|
-
export type BuilderAction =
|
|
22
|
-
/** `pageId` additionally switches the active page (reference deep links, EC-172). */
|
|
23
|
-
{
|
|
24
|
-
type: 'select';
|
|
25
|
-
id: string | null;
|
|
26
|
-
pageId?: string;
|
|
27
|
-
} | {
|
|
28
|
-
type: 'hover';
|
|
29
|
-
id: string | null;
|
|
30
|
-
} | {
|
|
31
|
-
type: 'viewport';
|
|
32
|
-
viewport: 'desktop' | 'tablet' | 'mobile';
|
|
33
|
-
} | {
|
|
34
|
-
type: 'undo';
|
|
35
|
-
} | {
|
|
36
|
-
type: 'redo';
|
|
37
|
-
} | {
|
|
38
|
-
type: 'insert';
|
|
39
|
-
target: InsertTarget;
|
|
40
|
-
node: ComponentNode;
|
|
41
|
-
select?: boolean;
|
|
42
|
-
} | {
|
|
43
|
-
type: 'remove';
|
|
44
|
-
id: string;
|
|
45
|
-
} | {
|
|
46
|
-
type: 'duplicate';
|
|
47
|
-
id: string;
|
|
48
|
-
} | {
|
|
49
|
-
type: 'reorder';
|
|
50
|
-
id: string;
|
|
51
|
-
delta: -1 | 1;
|
|
52
|
-
} | {
|
|
53
|
-
type: 'move';
|
|
54
|
-
id: string;
|
|
55
|
-
target: InsertTarget;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* EC-162 layout gesture: wrap the reference node and the dragged subject in
|
|
59
|
-
* a two-column Grid container as ONE atomic structural edit (one undo step).
|
|
60
|
-
*/
|
|
61
|
-
| {
|
|
62
|
-
type: 'wrap';
|
|
63
|
-
referenceId: string;
|
|
64
|
-
side: 'left' | 'right';
|
|
65
|
-
subject: {
|
|
66
|
-
kind: 'node';
|
|
67
|
-
nodeId: string;
|
|
68
|
-
} | {
|
|
69
|
-
kind: 'component';
|
|
70
|
-
node: ComponentNode;
|
|
71
|
-
};
|
|
72
|
-
} | {
|
|
73
|
-
type: 'setProp';
|
|
74
|
-
id: string;
|
|
75
|
-
name: string;
|
|
76
|
-
value: PropValue;
|
|
77
|
-
coalesceKey?: string;
|
|
78
|
-
} | {
|
|
79
|
-
type: 'removeProp';
|
|
80
|
-
id: string;
|
|
81
|
-
name: string;
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* EC-171 legacy page SEO (in-memory only): set a working page's `seo` block.
|
|
85
|
-
* Page SEO persists via the `page` CMS document now, never as a node op — so
|
|
86
|
-
* this action does not mirror to a `graph.*` command.
|
|
87
|
-
*/
|
|
88
|
-
| {
|
|
89
|
-
type: 'setPageSeo';
|
|
90
|
-
pageId: string;
|
|
91
|
-
seo: WorkingPageSeo | undefined;
|
|
92
|
-
} | {
|
|
93
|
-
type: 'loadGraph';
|
|
94
|
-
graph: ProjectGraph;
|
|
95
|
-
};
|
|
96
|
-
/** The slice of builder state the mapping needs (pre-dispatch snapshot). */
|
|
97
|
-
export interface BuilderSnapshot {
|
|
98
|
-
present: WorkingGraph;
|
|
99
|
-
pageId: string;
|
|
100
|
-
nodeSeq: number;
|
|
101
|
-
}
|
|
102
|
-
/** A graph operation invocation, dispatchable via `operations.execute`. */
|
|
103
|
-
export interface GraphInvocation {
|
|
104
|
-
operation: string;
|
|
105
|
-
input: unknown;
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Map a dispatched builder action onto the `graph.*` command that persists it.
|
|
109
|
-
*
|
|
110
|
-
* After EC-187 only the whole-graph operations survive: `loadGraph`/`undo`/
|
|
111
|
-
* `redo` persist a layouts-only `ProjectGraph` via `graph.save`. Every
|
|
112
|
-
* page-tree edit (insert/remove/duplicate/move/reorder/wrap/setProp/
|
|
113
|
-
* removeProp) returns `null` — page-node graph commands are gone;
|
|
114
|
-
* those edits stay in-memory until the page is saved as a CMS document.
|
|
115
|
-
*/
|
|
116
|
-
export declare function graphInvocationFor(projectId: string, action: BuilderAction, prev: BuilderSnapshot, next: {
|
|
117
|
-
present: WorkingGraph;
|
|
118
|
-
}): GraphInvocation | null;
|
|
119
|
-
/**
|
|
120
|
-
* Make the persisted latest revision equal `graph` (the session's working
|
|
121
|
-
* graph) so node-level `graph.*` commands apply onto identical state. Saves a
|
|
122
|
-
* baseline revision when the project has no revision yet or the persisted
|
|
123
|
-
* latest diverged from the session (the builder session is the source of
|
|
124
|
-
* truth for the draft timeline — see the builder-store design note).
|
|
125
|
-
*/
|
|
126
|
-
export declare function ensureGraphBaseline(operations: OperationsClient, projectId: string, graph: ProjectGraph | WorkingGraph): Promise<OperationResult<unknown>>;
|
|
127
|
-
/**
|
|
128
|
-
* Persist "publish the session's latest state" (EC-141): ensure the working
|
|
129
|
-
* graph is the persisted latest revision (as the canonical layouts-only
|
|
130
|
-
* graph), then pin it live via `publishing.publish`. Single-environment
|
|
131
|
-
* (EC-179): a deployment IS one environment, so there is no target environment
|
|
132
|
-
* and no promote.
|
|
133
|
-
*/
|
|
134
|
-
export declare function persistPublish(operations: OperationsClient, projectId: string, workingGraph: ProjectGraph | WorkingGraph): Promise<OperationResult<unknown>>;
|
|
135
|
-
/** Persist an unpublish: revert the deployment to draft. */
|
|
136
|
-
export declare function persistUnpublish(operations: OperationsClient, projectId: string): Promise<OperationResult<unknown>>;
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { toProjectGraph } from '../working-graph';
|
|
2
|
-
/**
|
|
3
|
-
* Map a dispatched builder action onto the `graph.*` command that persists it.
|
|
4
|
-
*
|
|
5
|
-
* After EC-187 only the whole-graph operations survive: `loadGraph`/`undo`/
|
|
6
|
-
* `redo` persist a layouts-only `ProjectGraph` via `graph.save`. Every
|
|
7
|
-
* page-tree edit (insert/remove/duplicate/move/reorder/wrap/setProp/
|
|
8
|
-
* removeProp) returns `null` — page-node graph commands are gone;
|
|
9
|
-
* those edits stay in-memory until the page is saved as a CMS document.
|
|
10
|
-
*/
|
|
11
|
-
export function graphInvocationFor(projectId, action, prev, next) {
|
|
12
|
-
switch (action.type) {
|
|
13
|
-
case 'undo':
|
|
14
|
-
case 'redo': {
|
|
15
|
-
if (prev.present === next.present)
|
|
16
|
-
return null;
|
|
17
|
-
return {
|
|
18
|
-
operation: 'graph.save',
|
|
19
|
-
input: {
|
|
20
|
-
projectId,
|
|
21
|
-
// graph.save persists the canonical layouts-only graph.
|
|
22
|
-
graph: toProjectGraph(next.present),
|
|
23
|
-
message: action.type === 'undo' ? 'Undo' : 'Redo',
|
|
24
|
-
},
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
case 'loadGraph':
|
|
28
|
-
return {
|
|
29
|
-
operation: 'graph.save',
|
|
30
|
-
// `loadGraph` carries a canonical (layouts-only) ProjectGraph restore.
|
|
31
|
-
input: { projectId, graph: action.graph, message: 'Load graph' },
|
|
32
|
-
};
|
|
33
|
-
// Page-tree edits no longer mirror to node-level graph commands (those
|
|
34
|
-
// operations were deleted) — the page editor is in-memory-only now.
|
|
35
|
-
case 'select':
|
|
36
|
-
case 'hover':
|
|
37
|
-
case 'viewport':
|
|
38
|
-
case 'insert':
|
|
39
|
-
case 'remove':
|
|
40
|
-
case 'duplicate':
|
|
41
|
-
case 'reorder':
|
|
42
|
-
case 'move':
|
|
43
|
-
case 'wrap':
|
|
44
|
-
case 'setProp':
|
|
45
|
-
case 'removeProp':
|
|
46
|
-
case 'setPageSeo':
|
|
47
|
-
return null;
|
|
48
|
-
default:
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Make the persisted latest revision equal `graph` (the session's working
|
|
54
|
-
* graph) so node-level `graph.*` commands apply onto identical state. Saves a
|
|
55
|
-
* baseline revision when the project has no revision yet or the persisted
|
|
56
|
-
* latest diverged from the session (the builder session is the source of
|
|
57
|
-
* truth for the draft timeline — see the builder-store design note).
|
|
58
|
-
*/
|
|
59
|
-
export async function ensureGraphBaseline(operations, projectId, graph) {
|
|
60
|
-
// A working graph (the live session) is persisted as the canonical
|
|
61
|
-
// layouts-only graph; a canonical graph passes through unchanged.
|
|
62
|
-
const canonical = 'pages' in graph ? toProjectGraph(graph) : graph;
|
|
63
|
-
const latest = await operations.graph.getLatest({ projectId });
|
|
64
|
-
if (latest.ok && JSON.stringify(latest.value.graph) === JSON.stringify(canonical))
|
|
65
|
-
return latest;
|
|
66
|
-
return operations.graph.save({ projectId, graph: canonical, message: 'Builder session baseline' });
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Persist "publish the session's latest state" (EC-141): ensure the working
|
|
70
|
-
* graph is the persisted latest revision (as the canonical layouts-only
|
|
71
|
-
* graph), then pin it live via `publishing.publish`. Single-environment
|
|
72
|
-
* (EC-179): a deployment IS one environment, so there is no target environment
|
|
73
|
-
* and no promote.
|
|
74
|
-
*/
|
|
75
|
-
export async function persistPublish(operations, projectId, workingGraph) {
|
|
76
|
-
const baseline = await ensureGraphBaseline(operations, projectId, workingGraph);
|
|
77
|
-
if (!baseline.ok)
|
|
78
|
-
return baseline;
|
|
79
|
-
return operations.publishing.publish({ projectId });
|
|
80
|
-
}
|
|
81
|
-
/** Persist an unpublish: revert the deployment to draft. */
|
|
82
|
-
export async function persistUnpublish(operations, projectId) {
|
|
83
|
-
return operations.publishing.unpublish({ projectId });
|
|
84
|
-
}
|
|
85
|
-
//# sourceMappingURL=graph-commands.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"graph-commands.js","sourceRoot":"","sources":["../../../src/lib/operations/graph-commands.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAmEjD;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAChC,SAAiB,EACjB,MAAqB,EACrB,IAAqB,EACrB,IAA+B;IAE/B,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,MAAM,CAAC;QACZ,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO;gBAAE,OAAO,IAAI,CAAA;YAC9C,OAAO;gBACL,SAAS,EAAE,YAAY;gBACvB,KAAK,EAAE;oBACL,SAAS;oBACT,wDAAwD;oBACxD,KAAK,EAAE,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC;oBACnC,OAAO,EAAE,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM;iBAClD;aACF,CAAA;QACH,CAAC;QAED,KAAK,WAAW;YACd,OAAO;gBACL,SAAS,EAAE,YAAY;gBACvB,uEAAuE;gBACvE,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE;aACjE,CAAA;QAEH,uEAAuE;QACvE,oEAAoE;QACpE,KAAK,QAAQ,CAAC;QACd,KAAK,OAAO,CAAC;QACb,KAAK,UAAU,CAAC;QAChB,KAAK,QAAQ,CAAC;QACd,KAAK,QAAQ,CAAC;QACd,KAAK,WAAW,CAAC;QACjB,KAAK,SAAS,CAAC;QACf,KAAK,MAAM,CAAC;QACZ,KAAK,MAAM,CAAC;QACZ,KAAK,SAAS,CAAC;QACf,KAAK,YAAY,CAAC;QAClB,KAAK,YAAY;YACf,OAAO,IAAI,CAAA;QAEb;YACE,OAAO,IAAI,CAAA;IACf,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,UAA4B,EAC5B,SAAiB,EACjB,KAAkC;IAElC,mEAAmE;IACnE,kEAAkE;IAClE,MAAM,SAAS,GAAG,OAAO,IAAI,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;IAClE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC,CAAA;IAC9D,IAAI,MAAM,CAAC,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;QAAE,OAAO,MAAM,CAAA;IAChG,OAAO,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,0BAA0B,EAAE,CAAC,CAAA;AACpG,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,UAA4B,EAC5B,SAAiB,EACjB,YAAyC;IAEzC,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,UAAU,EAAE,SAAS,EAAE,YAAY,CAAC,CAAA;IAC/E,IAAI,CAAC,QAAQ,CAAC,EAAE;QAAE,OAAO,QAAQ,CAAA;IACjC,OAAO,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,CAAC,CAAA;AACrD,CAAC;AAED,4DAA4D;AAC5D,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,UAA4B,EAC5B,SAAiB;IAEjB,OAAO,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC,CAAA;AACvD,CAAC","sourcesContent":["import type {\n ComponentNode,\n InsertTarget,\n ProjectGraph,\n PropValue,\n} from '@elytracms/core/project-graph'\nimport { toProjectGraph } from '../working-graph'\nimport type { WorkingGraph, WorkingPageSeo } from '../working-graph'\nimport type { OperationResult, OperationsClient } from './operations-package'\n\n/**\n * Builder action → graph operation mapping (EC-141, reshaped by EC-187).\n *\n * The canonical `ProjectGraph` is now LAYOUTS-ONLY, and the page-node graph\n * commands (`graph.insertNode`/`removeNode`/`duplicateNode`/`moveNode`/\n * `reorderNode`/`setNodeProp`/`removeNodeProp`/`setNodeCondition`) were DELETED\n * from the operations layer — a page is a CMS document now, edited through the\n * composition-field path, not mirrored as node ops. So every page-tree edit\n * here returns `null`: the legacy `/builder` page editor is in-memory-only for\n * page edits (it is retired in a later slice).\n *\n * What still persists: `loadGraph` (restoring a saved revision), `undo`, and\n * `redo` each save the whole graph via `graph.save` — but a `graph.save`\n * persists a CANONICAL layouts-only `ProjectGraph`, so the WorkingGraph\n * `present` is converted via `toProjectGraph` before it is sent.\n */\n\n/** The builder store's action union (owned here so the mapping stays React-free). */\nexport type BuilderAction =\n /** `pageId` additionally switches the active page (reference deep links, EC-172). */\n | { type: 'select'; id: string | null; pageId?: string }\n | { type: 'hover'; id: string | null }\n | { type: 'viewport'; viewport: 'desktop' | 'tablet' | 'mobile' }\n | { type: 'undo' }\n | { type: 'redo' }\n | { type: 'insert'; target: InsertTarget; node: ComponentNode; select?: boolean }\n | { type: 'remove'; id: string }\n | { type: 'duplicate'; id: string }\n | { type: 'reorder'; id: string; delta: -1 | 1 }\n | { type: 'move'; id: string; target: InsertTarget }\n /**\n * EC-162 layout gesture: wrap the reference node and the dragged subject in\n * a two-column Grid container as ONE atomic structural edit (one undo step).\n */\n | {\n type: 'wrap'\n referenceId: string\n side: 'left' | 'right'\n subject: { kind: 'node'; nodeId: string } | { kind: 'component'; node: ComponentNode }\n }\n | { type: 'setProp'; id: string; name: string; value: PropValue; coalesceKey?: string }\n | { type: 'removeProp'; id: string; name: string }\n /**\n * EC-171 legacy page SEO (in-memory only): set a working page's `seo` block.\n * Page SEO persists via the `page` CMS document now, never as a node op — so\n * this action does not mirror to a `graph.*` command.\n */\n | { type: 'setPageSeo'; pageId: string; seo: WorkingPageSeo | undefined }\n | { type: 'loadGraph'; graph: ProjectGraph }\n\n/** The slice of builder state the mapping needs (pre-dispatch snapshot). */\nexport interface BuilderSnapshot {\n present: WorkingGraph\n pageId: string\n nodeSeq: number\n}\n\n/** A graph operation invocation, dispatchable via `operations.execute`. */\nexport interface GraphInvocation {\n operation: string\n input: unknown\n}\n\n/**\n * Map a dispatched builder action onto the `graph.*` command that persists it.\n *\n * After EC-187 only the whole-graph operations survive: `loadGraph`/`undo`/\n * `redo` persist a layouts-only `ProjectGraph` via `graph.save`. Every\n * page-tree edit (insert/remove/duplicate/move/reorder/wrap/setProp/\n * removeProp) returns `null` — page-node graph commands are gone;\n * those edits stay in-memory until the page is saved as a CMS document.\n */\nexport function graphInvocationFor(\n projectId: string,\n action: BuilderAction,\n prev: BuilderSnapshot,\n next: { present: WorkingGraph },\n): GraphInvocation | null {\n switch (action.type) {\n case 'undo':\n case 'redo': {\n if (prev.present === next.present) return null\n return {\n operation: 'graph.save',\n input: {\n projectId,\n // graph.save persists the canonical layouts-only graph.\n graph: toProjectGraph(next.present),\n message: action.type === 'undo' ? 'Undo' : 'Redo',\n },\n }\n }\n\n case 'loadGraph':\n return {\n operation: 'graph.save',\n // `loadGraph` carries a canonical (layouts-only) ProjectGraph restore.\n input: { projectId, graph: action.graph, message: 'Load graph' },\n }\n\n // Page-tree edits no longer mirror to node-level graph commands (those\n // operations were deleted) — the page editor is in-memory-only now.\n case 'select':\n case 'hover':\n case 'viewport':\n case 'insert':\n case 'remove':\n case 'duplicate':\n case 'reorder':\n case 'move':\n case 'wrap':\n case 'setProp':\n case 'removeProp':\n case 'setPageSeo':\n return null\n\n default:\n return null\n }\n}\n\n/**\n * Make the persisted latest revision equal `graph` (the session's working\n * graph) so node-level `graph.*` commands apply onto identical state. Saves a\n * baseline revision when the project has no revision yet or the persisted\n * latest diverged from the session (the builder session is the source of\n * truth for the draft timeline — see the builder-store design note).\n */\nexport async function ensureGraphBaseline(\n operations: OperationsClient,\n projectId: string,\n graph: ProjectGraph | WorkingGraph,\n): Promise<OperationResult<unknown>> {\n // A working graph (the live session) is persisted as the canonical\n // layouts-only graph; a canonical graph passes through unchanged.\n const canonical = 'pages' in graph ? toProjectGraph(graph) : graph\n const latest = await operations.graph.getLatest({ projectId })\n if (latest.ok && JSON.stringify(latest.value.graph) === JSON.stringify(canonical)) return latest\n return operations.graph.save({ projectId, graph: canonical, message: 'Builder session baseline' })\n}\n\n/**\n * Persist \"publish the session's latest state\" (EC-141): ensure the working\n * graph is the persisted latest revision (as the canonical layouts-only\n * graph), then pin it live via `publishing.publish`. Single-environment\n * (EC-179): a deployment IS one environment, so there is no target environment\n * and no promote.\n */\nexport async function persistPublish(\n operations: OperationsClient,\n projectId: string,\n workingGraph: ProjectGraph | WorkingGraph,\n): Promise<OperationResult<unknown>> {\n const baseline = await ensureGraphBaseline(operations, projectId, workingGraph)\n if (!baseline.ok) return baseline\n return operations.publishing.publish({ projectId })\n}\n\n/** Persist an unpublish: revert the deployment to draft. */\nexport async function persistUnpublish(\n operations: OperationsClient,\n projectId: string,\n): Promise<OperationResult<unknown>> {\n return operations.publishing.unpublish({ projectId })\n}\n"]}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import type { BuilderAction, BuilderSnapshot } from './graph-commands';
|
|
2
|
-
import type { WorkingGraph } from '../working-graph';
|
|
3
|
-
import type { OperationError, OperationsClient } from './operations-package';
|
|
4
|
-
/**
|
|
5
|
-
* Builder → operations persistence (EC-141). Mirrors every committed builder
|
|
6
|
-
* mutation onto the operations layer as the matching `graph.*` command, in
|
|
7
|
-
* dispatch order, against a guaranteed-identical baseline revision.
|
|
8
|
-
*
|
|
9
|
-
* Failures are *surfaced, never silent, and never block local editing*: a
|
|
10
|
-
* rejected/denied/failed command reaches `onError` (the store renders it) and
|
|
11
|
-
* invalidates the baseline, so the next mutation re-syncs — which re-surfaces
|
|
12
|
-
* a standing denial instead of silently dropping edits.
|
|
13
|
-
*/
|
|
14
|
-
export interface GraphPersister {
|
|
15
|
-
/** Queue the command mirroring a dispatched action (no-op for pure-UI actions). */
|
|
16
|
-
enqueue(action: BuilderAction, prev: BuilderSnapshot, next: {
|
|
17
|
-
present: WorkingGraph;
|
|
18
|
-
}): void;
|
|
19
|
-
/** Await every queued command (test/publish synchronization point). */
|
|
20
|
-
flush(): Promise<void>;
|
|
21
|
-
}
|
|
22
|
-
export interface GraphPersisterOptions {
|
|
23
|
-
projectId: string;
|
|
24
|
-
getOperations: () => Promise<OperationsClient>;
|
|
25
|
-
onError: (error: OperationError) => void;
|
|
26
|
-
}
|
|
27
|
-
export declare function createGraphPersister(options: GraphPersisterOptions): GraphPersister;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { ensureGraphBaseline, graphInvocationFor } from './graph-commands';
|
|
2
|
-
import { createPersistQueue } from './persist-queue';
|
|
3
|
-
export function createGraphPersister(options) {
|
|
4
|
-
const queue = createPersistQueue();
|
|
5
|
-
let baselineReady = false;
|
|
6
|
-
return {
|
|
7
|
-
enqueue(action, prev, next) {
|
|
8
|
-
const invocation = graphInvocationFor(options.projectId, action, prev, next);
|
|
9
|
-
if (!invocation)
|
|
10
|
-
return;
|
|
11
|
-
queue.push(async () => {
|
|
12
|
-
const operations = await options.getOperations();
|
|
13
|
-
// graph.save replaces the whole graph, so it *is* a baseline; the
|
|
14
|
-
// node-level commands need the persisted latest to equal the
|
|
15
|
-
// session's pre-edit graph first.
|
|
16
|
-
if (!baselineReady && invocation.operation !== 'graph.save') {
|
|
17
|
-
const baseline = await ensureGraphBaseline(operations, options.projectId, prev.present);
|
|
18
|
-
if (!baseline.ok) {
|
|
19
|
-
options.onError(baseline.error);
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
const result = await operations.execute(invocation.operation, invocation.input);
|
|
24
|
-
if (!result.ok) {
|
|
25
|
-
baselineReady = false;
|
|
26
|
-
options.onError(result.error);
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
baselineReady = true;
|
|
30
|
-
});
|
|
31
|
-
},
|
|
32
|
-
flush: () => queue.flush(),
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
//# sourceMappingURL=graph-persistence.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"graph-persistence.js","sourceRoot":"","sources":["../../../src/lib/operations/graph-persistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAI1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAyBpD,MAAM,UAAU,oBAAoB,CAAC,OAA8B;IACjE,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAA;IAClC,IAAI,aAAa,GAAG,KAAK,CAAA;IAEzB,OAAO;QACL,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI;YACxB,MAAM,UAAU,GAAG,kBAAkB,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;YAC5E,IAAI,CAAC,UAAU;gBAAE,OAAM;YACvB,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;gBACpB,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,aAAa,EAAE,CAAA;gBAChD,kEAAkE;gBAClE,6DAA6D;gBAC7D,kCAAkC;gBAClC,IAAI,CAAC,aAAa,IAAI,UAAU,CAAC,SAAS,KAAK,YAAY,EAAE,CAAC;oBAC5D,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,UAAU,EAAE,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;oBACvF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;wBACjB,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;wBAC/B,OAAM;oBACR,CAAC;gBACH,CAAC;gBACD,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,EAAE,UAAU,CAAC,KAAK,CAAC,CAAA;gBAC/E,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;oBACf,aAAa,GAAG,KAAK,CAAA;oBACrB,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;oBAC7B,OAAM;gBACR,CAAC;gBACD,aAAa,GAAG,IAAI,CAAA;YACtB,CAAC,CAAC,CAAA;QACJ,CAAC;QACD,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE;KAC3B,CAAA;AACH,CAAC","sourcesContent":["import { ensureGraphBaseline, graphInvocationFor } from './graph-commands'\nimport type { BuilderAction, BuilderSnapshot } from './graph-commands'\nimport type { WorkingGraph } from '../working-graph'\nimport type { OperationError, OperationsClient } from './operations-package'\nimport { createPersistQueue } from './persist-queue'\n\n/**\n * Builder → operations persistence (EC-141). Mirrors every committed builder\n * mutation onto the operations layer as the matching `graph.*` command, in\n * dispatch order, against a guaranteed-identical baseline revision.\n *\n * Failures are *surfaced, never silent, and never block local editing*: a\n * rejected/denied/failed command reaches `onError` (the store renders it) and\n * invalidates the baseline, so the next mutation re-syncs — which re-surfaces\n * a standing denial instead of silently dropping edits.\n */\nexport interface GraphPersister {\n /** Queue the command mirroring a dispatched action (no-op for pure-UI actions). */\n enqueue(action: BuilderAction, prev: BuilderSnapshot, next: { present: WorkingGraph }): void\n /** Await every queued command (test/publish synchronization point). */\n flush(): Promise<void>\n}\n\nexport interface GraphPersisterOptions {\n projectId: string\n getOperations: () => Promise<OperationsClient>\n onError: (error: OperationError) => void\n}\n\nexport function createGraphPersister(options: GraphPersisterOptions): GraphPersister {\n const queue = createPersistQueue()\n let baselineReady = false\n\n return {\n enqueue(action, prev, next) {\n const invocation = graphInvocationFor(options.projectId, action, prev, next)\n if (!invocation) return\n queue.push(async () => {\n const operations = await options.getOperations()\n // graph.save replaces the whole graph, so it *is* a baseline; the\n // node-level commands need the persisted latest to equal the\n // session's pre-edit graph first.\n if (!baselineReady && invocation.operation !== 'graph.save') {\n const baseline = await ensureGraphBaseline(operations, options.projectId, prev.present)\n if (!baseline.ok) {\n options.onError(baseline.error)\n return\n }\n }\n const result = await operations.execute(invocation.operation, invocation.input)\n if (!result.ok) {\n baselineReady = false\n options.onError(result.error)\n return\n }\n baselineReady = true\n })\n },\n flush: () => queue.flush(),\n }\n}\n"]}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Route & redirect surface support (EC-170; made read-only by EC-207 "routes as
|
|
3
|
-
* code"). Routes & redirects are config-sourced — authored in `elytra.config.ts`
|
|
4
|
-
* and read through `resolveDeploymentRoutes`/`resolveDeploymentRedirects`, never
|
|
5
|
-
* the backend. `routing-store.ts` holds the pure template-route helpers;
|
|
6
|
-
* `routing-analysis.ts` holds the engine-derived view models from the
|
|
7
|
-
* `@elytracms/core/cms-core` router.
|
|
8
|
-
*/
|
|
9
|
-
export * from './routing-store';
|
|
10
|
-
export * from './routing-analysis';
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Route & redirect surface support (EC-170; made read-only by EC-207 "routes as
|
|
3
|
-
* code"). Routes & redirects are config-sourced — authored in `elytra.config.ts`
|
|
4
|
-
* and read through `resolveDeploymentRoutes`/`resolveDeploymentRedirects`, never
|
|
5
|
-
* the backend. `routing-store.ts` holds the pure template-route helpers;
|
|
6
|
-
* `routing-analysis.ts` holds the engine-derived view models from the
|
|
7
|
-
* `@elytracms/core/cms-core` router.
|
|
8
|
-
*/
|
|
9
|
-
export * from './routing-store';
|
|
10
|
-
export * from './routing-analysis';
|
|
11
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/routing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,cAAc,iBAAiB,CAAA;AAC/B,cAAc,oBAAoB,CAAA","sourcesContent":["/**\n * Route & redirect surface support (EC-170; made read-only by EC-207 \"routes as\n * code\"). Routes & redirects are config-sourced — authored in `elytra.config.ts`\n * and read through `resolveDeploymentRoutes`/`resolveDeploymentRedirects`, never\n * the backend. `routing-store.ts` holds the pure template-route helpers;\n * `routing-analysis.ts` holds the engine-derived view models from the\n * `@elytracms/core/cms-core` router.\n */\nexport * from './routing-store'\nexport * from './routing-analysis'\n"]}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import type { CmsValidationIssue, RedirectRecord } from '@elytracms/core/cms-core';
|
|
2
|
-
/**
|
|
3
|
-
* Engine-derived view models for the Routes section (EC-170). Everything here
|
|
4
|
-
* is a thin projection over the existing `@elytracms/core/cms-core` router — the UI
|
|
5
|
-
* never reimplements pattern matching, conflict detection, or loop detection.
|
|
6
|
-
*/
|
|
7
|
-
export interface RouteConflict {
|
|
8
|
-
/** The structured `route-conflict` issue from `createRouter`. */
|
|
9
|
-
issue: CmsValidationIssue;
|
|
10
|
-
/** The id of the *other* route in the conflicting pair. */
|
|
11
|
-
otherRouteId: string;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Index the router's `route-conflict` issues by route id, attributing each
|
|
15
|
-
* conflict to BOTH routes in the pair so each affected row can render it
|
|
16
|
-
* inline with a deep link to its counterpart.
|
|
17
|
-
*/
|
|
18
|
-
export declare function conflictsByRoute(issues: readonly CmsValidationIssue[]): Map<string, RouteConflict[]>;
|
|
19
|
-
/** 301/302 label for a redirect record. */
|
|
20
|
-
export declare function statusCodeOf(redirect: Pick<RedirectRecord, 'permanent'>): '301' | '302';
|
|
21
|
-
/** Split a route pattern into segments, flagging `:param` segments. */
|
|
22
|
-
export interface PatternSegmentView {
|
|
23
|
-
text: string;
|
|
24
|
-
param: boolean;
|
|
25
|
-
}
|
|
26
|
-
export declare function patternSegments(pattern: string): PatternSegmentView[];
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Index the router's `route-conflict` issues by route id, attributing each
|
|
3
|
-
* conflict to BOTH routes in the pair so each affected row can render it
|
|
4
|
-
* inline with a deep link to its counterpart.
|
|
5
|
-
*/
|
|
6
|
-
export function conflictsByRoute(issues) {
|
|
7
|
-
const map = new Map();
|
|
8
|
-
const add = (routeId, conflict) => {
|
|
9
|
-
const list = map.get(routeId) ?? [];
|
|
10
|
-
list.push(conflict);
|
|
11
|
-
map.set(routeId, list);
|
|
12
|
-
};
|
|
13
|
-
for (const issue of issues) {
|
|
14
|
-
if (issue.code !== 'route-conflict')
|
|
15
|
-
continue;
|
|
16
|
-
// The engine attaches the issue at path ['routes', <routeId>] and names
|
|
17
|
-
// the partner in meta.conflictsWith.
|
|
18
|
-
const routeId = typeof issue.path[1] === 'string' ? issue.path[1] : undefined;
|
|
19
|
-
const other = typeof issue.meta?.conflictsWith === 'string' ? issue.meta.conflictsWith : undefined;
|
|
20
|
-
if (routeId)
|
|
21
|
-
add(routeId, { issue, otherRouteId: other ?? '' });
|
|
22
|
-
if (other && routeId)
|
|
23
|
-
add(other, { issue, otherRouteId: routeId });
|
|
24
|
-
}
|
|
25
|
-
return map;
|
|
26
|
-
}
|
|
27
|
-
/** 301/302 label for a redirect record. */
|
|
28
|
-
export function statusCodeOf(redirect) {
|
|
29
|
-
return redirect.permanent ? '301' : '302';
|
|
30
|
-
}
|
|
31
|
-
export function patternSegments(pattern) {
|
|
32
|
-
return pattern
|
|
33
|
-
.split('/')
|
|
34
|
-
.filter((segment) => segment.length > 0)
|
|
35
|
-
.map((segment) => segment.startsWith(':') ? { text: segment, param: true } : { text: segment, param: false });
|
|
36
|
-
}
|
|
37
|
-
//# sourceMappingURL=routing-analysis.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"routing-analysis.js","sourceRoot":"","sources":["../../../src/lib/routing/routing-analysis.ts"],"names":[],"mappings":"AAeA;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAqC;IAErC,MAAM,GAAG,GAAG,IAAI,GAAG,EAA2B,CAAA;IAC9C,MAAM,GAAG,GAAG,CAAC,OAAe,EAAE,QAAuB,EAAE,EAAE;QACvD,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;QACnC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACnB,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;IACxB,CAAC,CAAA;IACD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB;YAAE,SAAQ;QAC7C,wEAAwE;QACxE,qCAAqC;QACrC,MAAM,OAAO,GAAG,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QAC7E,MAAM,KAAK,GACT,OAAO,KAAK,CAAC,IAAI,EAAE,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAA;QACtF,IAAI,OAAO;YAAE,GAAG,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,IAAI,EAAE,EAAE,CAAC,CAAA;QAC/D,IAAI,KAAK,IAAI,OAAO;YAAE,GAAG,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,CAAA;IACpE,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,2CAA2C;AAC3C,MAAM,UAAU,YAAY,CAAC,QAA2C;IACtE,OAAO,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAA;AAC3C,CAAC;AAQD,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,OAAO,OAAO;SACX,KAAK,CAAC,GAAG,CAAC;SACV,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;SACvC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CACf,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAC3F,CAAA;AACL,CAAC","sourcesContent":["import type { CmsValidationIssue, RedirectRecord } from '@elytracms/core/cms-core'\n\n/**\n * Engine-derived view models for the Routes section (EC-170). Everything here\n * is a thin projection over the existing `@elytracms/core/cms-core` router — the UI\n * never reimplements pattern matching, conflict detection, or loop detection.\n */\n\nexport interface RouteConflict {\n /** The structured `route-conflict` issue from `createRouter`. */\n issue: CmsValidationIssue\n /** The id of the *other* route in the conflicting pair. */\n otherRouteId: string\n}\n\n/**\n * Index the router's `route-conflict` issues by route id, attributing each\n * conflict to BOTH routes in the pair so each affected row can render it\n * inline with a deep link to its counterpart.\n */\nexport function conflictsByRoute(\n issues: readonly CmsValidationIssue[],\n): Map<string, RouteConflict[]> {\n const map = new Map<string, RouteConflict[]>()\n const add = (routeId: string, conflict: RouteConflict) => {\n const list = map.get(routeId) ?? []\n list.push(conflict)\n map.set(routeId, list)\n }\n for (const issue of issues) {\n if (issue.code !== 'route-conflict') continue\n // The engine attaches the issue at path ['routes', <routeId>] and names\n // the partner in meta.conflictsWith.\n const routeId = typeof issue.path[1] === 'string' ? issue.path[1] : undefined\n const other =\n typeof issue.meta?.conflictsWith === 'string' ? issue.meta.conflictsWith : undefined\n if (routeId) add(routeId, { issue, otherRouteId: other ?? '' })\n if (other && routeId) add(other, { issue, otherRouteId: routeId })\n }\n return map\n}\n\n/** 301/302 label for a redirect record. */\nexport function statusCodeOf(redirect: Pick<RedirectRecord, 'permanent'>): '301' | '302' {\n return redirect.permanent ? '301' : '302'\n}\n\n/** Split a route pattern into segments, flagging `:param` segments. */\nexport interface PatternSegmentView {\n text: string\n param: boolean\n}\n\nexport function patternSegments(pattern: string): PatternSegmentView[] {\n return pattern\n .split('/')\n .filter((segment) => segment.length > 0)\n .map((segment) =>\n segment.startsWith(':') ? { text: segment, param: true } : { text: segment, param: false },\n )\n}\n"]}
|