@cocoar/vue-page-builder 2.19.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/IDP_INTEGRATION.md +350 -0
- package/README.md +498 -169
- package/dist/BuilderElementCodeDialog-DXGNzleE.js +64 -0
- package/dist/BuilderExpressionDialog-yIfwYgXD.js +61 -0
- package/dist/BuilderLogicPanel-C9urz5Cd.js +68 -0
- package/dist/BuilderPageRootCodeDialog-CQsg_ozW.js +61 -0
- package/dist/CoarPageBuilder.vue.d.ts +71 -1
- package/dist/CoarPageBuilder.vue.d.ts.map +1 -1
- package/dist/CoarPageRenderer.vue.d.ts +36 -1
- package/dist/CoarPageRenderer.vue.d.ts.map +1 -1
- package/dist/PageNode.vue.d.ts +9 -1
- package/dist/PageNode.vue.d.ts.map +1 -1
- package/dist/VisualMarkupInspector-CmAOc-CH.js +54 -0
- package/dist/_plugin-vue_export-helper-BTgDAbhb.js +8 -0
- package/dist/actionValues.d.ts +21 -0
- package/dist/actionValues.d.ts.map +1 -0
- package/dist/assets/pageScriptRuntime.worker-Cll8Lm_I.js +25 -0
- package/dist/builder/BuilderCanvas.vue.d.ts +31 -1
- package/dist/builder/BuilderCanvas.vue.d.ts.map +1 -1
- package/dist/builder/BuilderCanvasNode.vue.d.ts.map +1 -1
- package/dist/builder/BuilderCompositionsPanel.vue.d.ts +3 -0
- package/dist/builder/BuilderCompositionsPanel.vue.d.ts.map +1 -0
- package/dist/builder/BuilderElementCodeDialog.vue.d.ts +14 -0
- package/dist/builder/BuilderElementCodeDialog.vue.d.ts.map +1 -0
- package/dist/builder/BuilderExpressionDialog.vue.d.ts +11 -0
- package/dist/builder/BuilderExpressionDialog.vue.d.ts.map +1 -0
- package/dist/builder/BuilderFxButton.vue.d.ts +28 -0
- package/dist/builder/BuilderFxButton.vue.d.ts.map +1 -0
- package/dist/builder/BuilderLogicPanel.vue.d.ts +3 -0
- package/dist/builder/BuilderLogicPanel.vue.d.ts.map +1 -0
- package/dist/builder/BuilderOutline.vue.d.ts.map +1 -1
- package/dist/builder/BuilderOutlineNode.vue.d.ts.map +1 -1
- package/dist/builder/BuilderPageRootCodeDialog.vue.d.ts +13 -0
- package/dist/builder/BuilderPageRootCodeDialog.vue.d.ts.map +1 -0
- package/dist/builder/BuilderPalette.vue.d.ts +3 -0
- package/dist/builder/BuilderPalette.vue.d.ts.map +1 -0
- package/dist/builder/BuilderPropsPanel.vue.d.ts.map +1 -1
- package/dist/builder/BuilderTranslationsPanel.vue.d.ts +6 -0
- package/dist/builder/BuilderTranslationsPanel.vue.d.ts.map +1 -0
- package/dist/builder/boxSides.d.ts +30 -0
- package/dist/builder/boxSides.d.ts.map +1 -0
- package/dist/builder/builderContext.d.ts +46 -4
- package/dist/builder/builderContext.d.ts.map +1 -1
- package/dist/builder/expressionAuthoring.d.ts +7 -0
- package/dist/builder/expressionAuthoring.d.ts.map +1 -0
- package/dist/builder/nodeDefaults.d.ts +10 -5
- package/dist/builder/nodeDefaults.d.ts.map +1 -1
- package/dist/builder/pageCodeAuthoring.d.ts +11 -0
- package/dist/builder/pageCodeAuthoring.d.ts.map +1 -0
- package/dist/builder/props/ActionPropsEditor.vue.d.ts +9 -0
- package/dist/builder/props/ActionPropsEditor.vue.d.ts.map +1 -0
- package/dist/builder/props/BuilderViewportControl.vue.d.ts +23 -0
- package/dist/builder/props/BuilderViewportControl.vue.d.ts.map +1 -0
- package/dist/builder/props/BuilderZoomControl.vue.d.ts +24 -0
- package/dist/builder/props/BuilderZoomControl.vue.d.ts.map +1 -0
- package/dist/builder/props/CompoundLengthProperty.vue.d.ts +20 -0
- package/dist/builder/props/CompoundLengthProperty.vue.d.ts.map +1 -0
- package/dist/builder/props/StyleProps.vue.d.ts +1 -0
- package/dist/builder/props/StyleProps.vue.d.ts.map +1 -1
- package/dist/builder/schemaMigrateV1.d.ts +7 -0
- package/dist/builder/schemaMigrateV1.d.ts.map +1 -1
- package/dist/builder/schemaNormalize.d.ts.map +1 -1
- package/dist/builder/{useSchemaValidation.d.ts → useAuthoringFindings.d.ts} +8 -8
- package/dist/builder/useAuthoringFindings.d.ts.map +1 -0
- package/dist/builder/useBuilderDnd.d.ts +8 -1
- package/dist/builder/useBuilderDnd.d.ts.map +1 -1
- package/dist/builder/useCanvasZoom.d.ts +50 -0
- package/dist/builder/useCanvasZoom.d.ts.map +1 -0
- package/dist/builder/usePageBuilder.d.ts +2 -0
- package/dist/builder/usePageBuilder.d.ts.map +1 -1
- package/dist/builder/usePageCompositions.d.ts +71 -0
- package/dist/builder/usePageCompositions.d.ts.map +1 -0
- package/dist/builderContext-B3rX2dxZ.js +4 -0
- package/dist/compositions.d.ts +79 -0
- package/dist/compositions.d.ts.map +1 -0
- package/dist/conditions.d.ts +8 -0
- package/dist/conditions.d.ts.map +1 -0
- package/dist/context.d.ts +17 -3
- package/dist/context.d.ts.map +1 -1
- package/dist/documentValidation.d.ts +12 -0
- package/dist/documentValidation.d.ts.map +1 -0
- package/dist/elements/builtins.d.ts.map +1 -1
- package/dist/elements/button/ButtonInspector.vue.d.ts.map +1 -1
- package/dist/elements/button/ButtonRenderer.vue.d.ts.map +1 -1
- package/dist/elements/button/index.d.ts +2 -2
- package/dist/elements/button/index.d.ts.map +1 -1
- package/dist/elements/card/CardInspector.vue.d.ts.map +1 -1
- package/dist/elements/card/index.d.ts.map +1 -1
- package/dist/elements/checkbox/CheckboxDefaultInput.vue.d.ts.map +1 -1
- package/dist/elements/checkbox/CheckboxInspector.vue.d.ts.map +1 -1
- package/dist/elements/checkbox/CheckboxRenderer.vue.d.ts.map +1 -1
- package/dist/elements/checkbox/index.d.ts.map +1 -1
- package/dist/elements/date-input/DateInputDefaultInput.vue.d.ts.map +1 -1
- package/dist/elements/date-input/DateInputInspector.vue.d.ts.map +1 -1
- package/dist/elements/date-input/index.d.ts.map +1 -1
- package/dist/elements/datetime-input/DateTimeInputDefaultInput.vue.d.ts.map +1 -1
- package/dist/elements/datetime-input/DateTimeInputInspector.vue.d.ts.map +1 -1
- package/dist/elements/datetime-input/index.d.ts.map +1 -1
- package/dist/elements/feedback/FeedbackInspector.vue.d.ts +8 -0
- package/dist/elements/feedback/FeedbackInspector.vue.d.ts.map +1 -0
- package/dist/elements/feedback/FeedbackPreview.vue.d.ts +7 -0
- package/dist/elements/feedback/FeedbackPreview.vue.d.ts.map +1 -0
- package/dist/elements/{stack/StackInspector.vue.d.ts → feedback/FeedbackRenderer.vue.d.ts} +3 -4
- package/dist/elements/feedback/FeedbackRenderer.vue.d.ts.map +1 -0
- package/dist/elements/feedback/index.d.ts +6 -0
- package/dist/elements/feedback/index.d.ts.map +1 -0
- package/dist/elements/heading/HeadingInspector.vue.d.ts.map +1 -1
- package/dist/elements/heading/index.d.ts.map +1 -1
- package/dist/elements/image/ImageInspector.vue.d.ts.map +1 -1
- package/dist/elements/image/index.d.ts.map +1 -1
- package/dist/elements/link/LinkInspector.vue.d.ts +1 -1
- package/dist/elements/link/LinkInspector.vue.d.ts.map +1 -1
- package/dist/elements/link/index.d.ts +1 -2
- package/dist/elements/link/index.d.ts.map +1 -1
- package/dist/elements/multi-select/MultiSelectDefaultInput.vue.d.ts.map +1 -1
- package/dist/elements/multi-select/MultiSelectInspector.vue.d.ts.map +1 -1
- package/dist/elements/multi-select/index.d.ts.map +1 -1
- package/dist/elements/note/NoteInspector.vue.d.ts.map +1 -1
- package/dist/elements/number-input/NumberInputDefaultInput.vue.d.ts.map +1 -1
- package/dist/elements/number-input/NumberInputInspector.vue.d.ts.map +1 -1
- package/dist/elements/number-input/index.d.ts.map +1 -1
- package/dist/elements/otp-input/OtpInputInspector.vue.d.ts.map +1 -1
- package/dist/elements/otp-input/index.d.ts.map +1 -1
- package/dist/elements/paragraph/index.d.ts.map +1 -1
- package/dist/elements/password-input/PasswordInputInspector.vue.d.ts.map +1 -1
- package/dist/elements/password-input/index.d.ts.map +1 -1
- package/dist/elements/previewUtils.d.ts.map +1 -1
- package/dist/elements/radio-group/RadioGroupDefaultInput.vue.d.ts.map +1 -1
- package/dist/elements/radio-group/RadioGroupInspector.vue.d.ts.map +1 -1
- package/dist/elements/radio-group/index.d.ts.map +1 -1
- package/dist/elements/registry.d.ts +265 -2
- package/dist/elements/registry.d.ts.map +1 -1
- package/dist/elements/repeat/RepeatInspector.vue.d.ts +8 -0
- package/dist/elements/repeat/RepeatInspector.vue.d.ts.map +1 -0
- package/dist/elements/repeat/RepeatRenderer.vue.d.ts +29 -0
- package/dist/elements/repeat/RepeatRenderer.vue.d.ts.map +1 -0
- package/dist/elements/repeat/index.d.ts +10 -0
- package/dist/elements/repeat/index.d.ts.map +1 -0
- package/dist/elements/section/SectionInspector.vue.d.ts.map +1 -1
- package/dist/elements/section/index.d.ts.map +1 -1
- package/dist/elements/select/SelectDefaultInput.vue.d.ts.map +1 -1
- package/dist/elements/select/SelectInspector.vue.d.ts.map +1 -1
- package/dist/elements/select/index.d.ts.map +1 -1
- package/dist/elements/spacer/SpacerInspector.vue.d.ts.map +1 -1
- package/dist/elements/stack/StackRenderer.vue.d.ts.map +1 -1
- package/dist/elements/stack/index.d.ts.map +1 -1
- package/dist/elements/switch/SwitchDefaultInput.vue.d.ts.map +1 -1
- package/dist/elements/switch/SwitchInspector.vue.d.ts.map +1 -1
- package/dist/elements/switch/index.d.ts.map +1 -1
- package/dist/elements/text-input/TextInputInspector.vue.d.ts.map +1 -1
- package/dist/elements/text-input/index.d.ts.map +1 -1
- package/dist/elements/usePageElement.d.ts +6 -2
- package/dist/elements/usePageElement.d.ts.map +1 -1
- package/dist/elements/visual-markup/VisualMarkupInspector.vue.d.ts +10 -0
- package/dist/elements/visual-markup/VisualMarkupInspector.vue.d.ts.map +1 -0
- package/dist/elements/visual-markup/VisualMarkupPreview.vue.d.ts +7 -0
- package/dist/elements/visual-markup/VisualMarkupPreview.vue.d.ts.map +1 -0
- package/dist/elements/visual-markup/VisualMarkupRenderer.vue.d.ts +7 -0
- package/dist/elements/visual-markup/VisualMarkupRenderer.vue.d.ts.map +1 -0
- package/dist/elements/visual-markup/index.d.ts +6 -0
- package/dist/elements/visual-markup/index.d.ts.map +1 -0
- package/dist/elements/visual-markup/visualDocument.d.ts +13 -0
- package/dist/elements/visual-markup/visualDocument.d.ts.map +1 -0
- package/dist/expressionAuthoring-7iAyadA3.js +74 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +32 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8571 -3448
- package/dist/pageCode-echPQdna.js +455 -0
- package/dist/pageCode.d.ts +101 -0
- package/dist/pageCode.d.ts.map +1 -0
- package/dist/pageCodeAuthoring-C8grEAUf.js +123 -0
- package/dist/responsive.d.ts +7 -0
- package/dist/responsive.d.ts.map +1 -0
- package/dist/runtime/PageRuntimeHost.d.ts +57 -0
- package/dist/runtime/PageRuntimeHost.d.ts.map +1 -0
- package/dist/runtime/PageScriptRuntime.d.ts +62 -0
- package/dist/runtime/PageScriptRuntime.d.ts.map +1 -0
- package/dist/runtime/pageScriptRuntime.worker.d.ts +1 -0
- package/dist/runtime/pageScriptRuntime.worker.d.ts.map +1 -0
- package/dist/runtime/runtimeProtocol.d.ts +150 -0
- package/dist/runtime/runtimeProtocol.d.ts.map +1 -0
- package/dist/runtime/usePageCodeRuntime.d.ts +32 -0
- package/dist/runtime/usePageCodeRuntime.d.ts.map +1 -0
- package/dist/runtime-worker.js +240 -0
- package/dist/runtimeBindings.d.ts +32 -0
- package/dist/runtimeBindings.d.ts.map +1 -0
- package/dist/runtimeExpressions.d.ts +16 -0
- package/dist/runtimeExpressions.d.ts.map +1 -0
- package/dist/runtimeProtocol-Bg1C-O0c.js +36 -0
- package/dist/runtimeWorkerEntry.d.ts +2 -0
- package/dist/runtimeWorkerEntry.d.ts.map +1 -0
- package/dist/schema.d.ts +298 -31
- package/dist/schema.d.ts.map +1 -1
- package/dist/styleMapping.d.ts +7 -0
- package/dist/styleMapping.d.ts.map +1 -1
- package/dist/translations.d.ts +8 -0
- package/dist/translations.d.ts.map +1 -0
- package/dist/visualDocument-DKjWBfpW.js +139 -0
- package/package.json +24 -6
- package/dist/builder/useSchemaValidation.d.ts.map +0 -1
- package/dist/elements/stack/StackInspector.vue.d.ts.map +0 -1
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
# IDP integration guide
|
|
2
|
+
|
|
3
|
+
This guide is the integration contract for Page Builder 2.20. It separates
|
|
4
|
+
tenant-owned data from application-owned authority so an IDP can offer visual
|
|
5
|
+
customization without turning a page document into application code.
|
|
6
|
+
|
|
7
|
+
## 1. Install the matching package set
|
|
8
|
+
|
|
9
|
+
Install the Page Builder and its Cocoar peers at the same release version. Pinning
|
|
10
|
+
the set prevents an authoring package from being combined accidentally with an
|
|
11
|
+
older renderer, localization or ScriptEditor runtime:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpm add --save-exact \
|
|
15
|
+
@cocoar/vue-page-builder@2.20.0 \
|
|
16
|
+
@cocoar/vue-ui@2.20.0 \
|
|
17
|
+
@cocoar/vue-localization@2.20.0 \
|
|
18
|
+
@cocoar/vue-script-editor@2.20.0 \
|
|
19
|
+
monaco-editor@^0.55.1
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Prerelease channels
|
|
23
|
+
|
|
24
|
+
Use the `alpha` channel for feature-branch integration tests without merging the
|
|
25
|
+
implementation into `develop`. Alpha packages are hosted by GitHub Packages
|
|
26
|
+
under the physical `@cocoar-dev` scope. Configure the registry and a GitHub token
|
|
27
|
+
with `read:packages` in the consuming project:
|
|
28
|
+
|
|
29
|
+
```ini
|
|
30
|
+
# .npmrc
|
|
31
|
+
@cocoar-dev:registry=https://npm.pkg.github.com
|
|
32
|
+
//npm.pkg.github.com/:_authToken=${GITHUB_PACKAGES_TOKEN}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Install them through pnpm aliases so application imports keep the stable
|
|
36
|
+
`@cocoar/*` names:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pnpm add --save-exact \
|
|
40
|
+
"@cocoar/vue-page-builder@npm:@cocoar-dev/vue-page-builder@alpha" \
|
|
41
|
+
"@cocoar/vue-ui@npm:@cocoar-dev/vue-ui@alpha" \
|
|
42
|
+
"@cocoar/vue-localization@npm:@cocoar-dev/vue-localization@alpha" \
|
|
43
|
+
"@cocoar/vue-script-editor@npm:@cocoar-dev/vue-script-editor@alpha" \
|
|
44
|
+
monaco-editor
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The dependency keys and all source imports remain `@cocoar/*`; only the package
|
|
48
|
+
source in `package.json` points at the temporary GitHub package.
|
|
49
|
+
|
|
50
|
+
The shared `develop` prerelease remains available on the `beta` channel:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pnpm add @cocoar/vue-page-builder@beta
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Import `@cocoar/vue-page-builder/styles` once in the authoring application and
|
|
57
|
+
the application that renders the authentication views.
|
|
58
|
+
|
|
59
|
+
### Register all Monaco workers used by the Builder
|
|
60
|
+
|
|
61
|
+
The Page Builder opens Monaco in JavaScript **and JSON** mode. The consuming
|
|
62
|
+
authoring application therefore has to route both language labels to their
|
|
63
|
+
matching Monaco workers before the first Builder mounts:
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
// src/main.ts (Vite)
|
|
67
|
+
import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
|
|
68
|
+
import TsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker';
|
|
69
|
+
import JsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker';
|
|
70
|
+
|
|
71
|
+
self.MonacoEnvironment = {
|
|
72
|
+
getWorker(_workerId, label) {
|
|
73
|
+
if (label === 'typescript' || label === 'javascript') return new TsWorker();
|
|
74
|
+
if (label === 'json') return new JsonWorker();
|
|
75
|
+
return new EditorWorker();
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Do not route `json` to the generic `EditorWorker`. The JSON language client then
|
|
81
|
+
requests methods that worker cannot provide and logs errors such as
|
|
82
|
+
`Missing requestHandler or method: doValidation`, `findDocumentColors`, or
|
|
83
|
+
`getFoldingRanges`. Script execution is unaffected, but JSON validation,
|
|
84
|
+
folding and color support are unavailable until the correct worker is used.
|
|
85
|
+
|
|
86
|
+
### Theme and host style registration
|
|
87
|
+
|
|
88
|
+
Resolve the application/client theme in the IDP and pass stable primitives to
|
|
89
|
+
the generic UI scope. Runtime and Builder preview intentionally share this one
|
|
90
|
+
implementation:
|
|
91
|
+
|
|
92
|
+
```vue
|
|
93
|
+
<CoarThemeScope :theme="applicationTheme" mode="auto">
|
|
94
|
+
<CoarPageRenderer :schema :config />
|
|
95
|
+
</CoarThemeScope>
|
|
96
|
+
|
|
97
|
+
<CoarPageBuilder
|
|
98
|
+
v-model="schema"
|
|
99
|
+
:config="config"
|
|
100
|
+
:preview-theme="applicationTheme"
|
|
101
|
+
preview-theme-mode="dark"
|
|
102
|
+
/>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`previewTheme` is scoped to the embedded renderer; the Builder toolbar,
|
|
106
|
+
Properties panel, dialogs, and Monaco keep the administration theme.
|
|
107
|
+
|
|
108
|
+
## 2. Persist one versioned document per scope and slot
|
|
109
|
+
|
|
110
|
+
The recommended storage key is:
|
|
111
|
+
|
|
112
|
+
```text
|
|
113
|
+
tenant / application-or-realm / slot / revision
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
The first preset release contains these slots:
|
|
117
|
+
|
|
118
|
+
- `login`
|
|
119
|
+
- `password-forgot`
|
|
120
|
+
- `logout`
|
|
121
|
+
- `consent`
|
|
122
|
+
|
|
123
|
+
The host owns the starting document and the `PageConfig` for each slot; the
|
|
124
|
+
package ships neither. Persist the complete `PageNode` JSON, including its `schemaVersion`. Treat saved
|
|
125
|
+
documents as immutable revisions. Draft, published revision, rollback target,
|
|
126
|
+
ETag and audit metadata belong to the IDP record around that JSON rather than to
|
|
127
|
+
the generic page schema.
|
|
128
|
+
|
|
129
|
+
Recommended lifecycle:
|
|
130
|
+
|
|
131
|
+
```text
|
|
132
|
+
default -> draft -> server validation -> preview -> publish -> rollback/reset
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Never overwrite the last published revision while saving a draft. Use an ETag or
|
|
136
|
+
revision number to reject concurrent saves.
|
|
137
|
+
|
|
138
|
+
## 3. Validate on both boundaries
|
|
139
|
+
|
|
140
|
+
Normalize and validate when loading an old document in the authoring UI:
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
const normalized = normalizePageSchema(storedDocument, config);
|
|
144
|
+
const validation = validatePageDocument(normalized.schema, config);
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Repeat equivalent validation in the trusted publish endpoint. Client validation
|
|
148
|
+
is authoring feedback, not authorization. Reject unsupported schema versions,
|
|
149
|
+
disallowed element types, document-limit violations and invalid host-context
|
|
150
|
+
bindings before a revision becomes active. Anything the tenant must not remove
|
|
151
|
+
— a compliance notice on a consent screen — is checked here too: the library
|
|
152
|
+
has no mechanism that could hold it in the browser.
|
|
153
|
+
|
|
154
|
+
Authentication, consent, ticket ownership, redirect validation and field-level
|
|
155
|
+
authorization always remain authoritative on the server.
|
|
156
|
+
|
|
157
|
+
## 4. Define the application host once
|
|
158
|
+
|
|
159
|
+
`definePageRuntimeHost()` creates an application-owned capability catalogue and
|
|
160
|
+
grant policy. It does not create page state or a Worker by itself. Reuse this
|
|
161
|
+
object for renderer sessions throughout the application.
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
export const idpPageRuntimeHost = definePageRuntimeHost({
|
|
165
|
+
endowments: {
|
|
166
|
+
api: {
|
|
167
|
+
call: withRuntimeEndowmentContext(
|
|
168
|
+
({ signal, tenantId, pageId }, operation, payload) =>
|
|
169
|
+
idpPageApi.call({
|
|
170
|
+
signal,
|
|
171
|
+
tenantId,
|
|
172
|
+
pageId,
|
|
173
|
+
operation: String(operation),
|
|
174
|
+
payload,
|
|
175
|
+
}),
|
|
176
|
+
),
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
grants: ({ pageId, definition }) => {
|
|
180
|
+
if (!pageId.startsWith('auth:')) return [];
|
|
181
|
+
if (!definition.id.startsWith('element-action:')) return [];
|
|
182
|
+
return ['api'];
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Objects not listed in `endowments` cannot be granted. Objects listed but not
|
|
188
|
+
returned by `grants` are not described to that Worker session. Pure compute
|
|
189
|
+
bindings can never receive endowments. Keep the facade narrow: expose named IDP
|
|
190
|
+
operations, not a general-purpose URL fetcher.
|
|
191
|
+
|
|
192
|
+
## 5. Create one runtime session per rendered page
|
|
193
|
+
|
|
194
|
+
```ts
|
|
195
|
+
const {
|
|
196
|
+
pageCodeValues,
|
|
197
|
+
onRuntimeChange,
|
|
198
|
+
runPageAction,
|
|
199
|
+
} = usePageCodeRuntime({
|
|
200
|
+
pageId: computed(() => `auth:${slot.value}`),
|
|
201
|
+
tenantId,
|
|
202
|
+
schema,
|
|
203
|
+
context,
|
|
204
|
+
viewport,
|
|
205
|
+
runtimeHost: idpPageRuntimeHost,
|
|
206
|
+
});
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
```vue
|
|
210
|
+
<CoarPageRenderer
|
|
211
|
+
:schema="schema"
|
|
212
|
+
:config="config"
|
|
213
|
+
:runtime-context="context"
|
|
214
|
+
:viewport-width="viewport.width"
|
|
215
|
+
:page-code-values="pageCodeValues"
|
|
216
|
+
:actions="hostActions"
|
|
217
|
+
:on-action="runPageAction"
|
|
218
|
+
@runtime-change="onRuntimeChange"
|
|
219
|
+
/>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
The explicit `actions` map wins for host actions. The dynamic `onAction`
|
|
223
|
+
dispatcher handles internal Page-Code action ids through `runPageAction`. The
|
|
224
|
+
Auth Customization Lab is the executable reference wiring. Each composable
|
|
225
|
+
instance creates an isolated SES Worker session. Pages never share script
|
|
226
|
+
globals or Page State. Unmounting the owning Vue component disposes the session.
|
|
227
|
+
|
|
228
|
+
## 6. Keep navigation and authentication as host actions
|
|
229
|
+
|
|
230
|
+
Page documents may configure presentation, validation, element actions and
|
|
231
|
+
Page State. They do not create or delete elements at runtime, change an element
|
|
232
|
+
type/name, navigate directly, read cookies, access the DOM or call ambient
|
|
233
|
+
browser APIs.
|
|
234
|
+
|
|
235
|
+
Map stable action ids to trusted application handlers for operations such as:
|
|
236
|
+
|
|
237
|
+
- login submission;
|
|
238
|
+
- forgot-password submission;
|
|
239
|
+
- consent allow/deny;
|
|
240
|
+
- navigation back to login;
|
|
241
|
+
- external provider selection.
|
|
242
|
+
|
|
243
|
+
On errors, keep the renderer mounted and pass field/form errors back to its
|
|
244
|
+
feedback model. Do not discard entered values on HTTP 500, timeout or disconnect.
|
|
245
|
+
|
|
246
|
+
## 7. Localization
|
|
247
|
+
|
|
248
|
+
The page root owns tenant translations. Elements reference keys through
|
|
249
|
+
translation bindings; the Builder's Translations tab edits the catalogue.
|
|
250
|
+
Runtime lookup order is page translation, host localization store, binding
|
|
251
|
+
fallback, then key. Keep security- or protocol-owned messages in the host
|
|
252
|
+
catalogue when tenants must not replace them.
|
|
253
|
+
|
|
254
|
+
## 8. Deployment and production boundary
|
|
255
|
+
|
|
256
|
+
Vite does not relocate `import.meta.url` assets while dependency pre-bundling.
|
|
257
|
+
The PageBuilder therefore publishes the Worker runtime as the isolated
|
|
258
|
+
`runtime-worker` subpath. Keep only this small entry out of the optimizer; the
|
|
259
|
+
PageBuilder, UI, Script Editor and their transitive dependencies remain fully
|
|
260
|
+
optimized:
|
|
261
|
+
|
|
262
|
+
```ts
|
|
263
|
+
// vite.config.ts
|
|
264
|
+
export default defineConfig({
|
|
265
|
+
optimizeDeps: {
|
|
266
|
+
exclude: ['@cocoar/vue-page-builder/runtime-worker'],
|
|
267
|
+
},
|
|
268
|
+
});
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Do not exclude the complete `@cocoar/vue-page-builder` package. That would also
|
|
272
|
+
skip optimization of CommonJS dependencies used by its UI/editor peers. The
|
|
273
|
+
consuming production build emits `pageScriptRuntime.worker-<hash>.js` under its
|
|
274
|
+
own configured `base`.
|
|
275
|
+
|
|
276
|
+
Serve that file as a same-origin module Worker and permit it through
|
|
277
|
+
`worker-src 'self'` (the application may keep `blob:` for unrelated Workers). SES uses
|
|
278
|
+
`Compartment.evaluate()` inside the Worker, so the Worker response must not
|
|
279
|
+
inherit an application CSP that forbids dynamic evaluation. Apply the strict
|
|
280
|
+
`script-src 'self'` policy to the HTML response, not indiscriminately to every
|
|
281
|
+
static asset. If the server requires a CSP header on the Worker response, scope
|
|
282
|
+
`script-src 'self' 'unsafe-eval'` to that response only. Do **not** add
|
|
283
|
+
`unsafe-eval` to the IDP document/application CSP.
|
|
284
|
+
|
|
285
|
+
The packed-consumer CI and release gates verify this from tarballs on Linux and
|
|
286
|
+
Windows with `vite --force`, a production build, a neutral non-root
|
|
287
|
+
`/consumer-app/` base and a browser boot under the strict document CSP.
|
|
288
|
+
|
|
289
|
+
### Decorative visual documents
|
|
290
|
+
|
|
291
|
+
Use the built-in `visual-markup` element only for non-semantic decoration.
|
|
292
|
+
`PageConfig.visualMarkup` is the host-controlled capability boundary for
|
|
293
|
+
approved font data/blob URLs and sanitized CSS custom properties. The page
|
|
294
|
+
author controls the node's allowlisted HTML, inline SVG and local CSS, while
|
|
295
|
+
the renderer supplies an empty iframe sandbox and a restrictive document CSP.
|
|
296
|
+
No JavaScript, form control, navigation or network API is available.
|
|
297
|
+
|
|
298
|
+
Pass the same `PageConfig` to the Builder and Runtime. The Builder's Preview tab
|
|
299
|
+
uses the real renderer; it intentionally does not grant a more permissive
|
|
300
|
+
preview environment. Size the opaque iframe through the outer node style—it
|
|
301
|
+
cannot inspect its content to auto-report height. Invalid or oversized visual
|
|
302
|
+
content is a node-local error: the iframe stays absent while the remaining IDP
|
|
303
|
+
form renders normally. The host's whole-document fallback is reserved for an
|
|
304
|
+
invalid or failed published page, not a rejected decorative node.
|
|
305
|
+
|
|
306
|
+
Before general tenant production rollout, complete the product threat model,
|
|
307
|
+
independent security review, browser/mobile matrix, operational quotas and
|
|
308
|
+
server-side publication checks. A stable library version supplies the technical
|
|
309
|
+
boundary; it does not replace the consuming SaaS product's own security and
|
|
310
|
+
publication review.
|
|
311
|
+
|
|
312
|
+
### Reusable composition repository
|
|
313
|
+
|
|
314
|
+
Reusable subtrees belong to the authoring workflow, not to the IDP request
|
|
315
|
+
runtime. Supply a host-owned `PageCompositionRepository` to `CoarPageBuilder`.
|
|
316
|
+
The Builder stores exact immutable version tokens, materializes the complete
|
|
317
|
+
subtree in the draft, and preserves instance ids/names while applying an update.
|
|
318
|
+
The host repository should enforce tenant ownership and optimistic concurrency
|
|
319
|
+
through `baseVersion` on `publish`.
|
|
320
|
+
|
|
321
|
+
For a SaaS authoring host, expose definitions separately from pages:
|
|
322
|
+
|
|
323
|
+
- **Pages** embed the Builder with `composition-management="consume"` and may
|
|
324
|
+
drag definitions from the **Compositions** palette group, select another
|
|
325
|
+
immutable version, update to latest or detach pinned instances.
|
|
326
|
+
- **Compositions** edit one standalone definition tree and call repository
|
|
327
|
+
`create()` / `publish()` at the host boundary.
|
|
328
|
+
|
|
329
|
+
Use `@open-composition="openComposition"` on `CoarPageBuilder` to connect the
|
|
330
|
+
Properties action to that separate host area. The event carries the exact
|
|
331
|
+
pinned `{ id, version }`; the host should open that version rather than latest.
|
|
332
|
+
The palette drag payload is editor-only. A successful drop is persisted solely
|
|
333
|
+
as the already-defined materialized nodes plus `composition` and
|
|
334
|
+
`compositionOrigins`; no wrapper or composition element type is introduced.
|
|
335
|
+
|
|
336
|
+
Removing a composition instance from Login therefore changes only Login. It
|
|
337
|
+
does not mutate the definition, Logout, or any other consumer. Publishing a new
|
|
338
|
+
definition version also leaves every page pinned until its author updates it.
|
|
339
|
+
|
|
340
|
+
At the server-side publication boundary:
|
|
341
|
+
|
|
342
|
+
1. Load the tenant-owned authoring document.
|
|
343
|
+
2. Run `validatePageCompositionReferences(document, repository)` and reject
|
|
344
|
+
missing versions or cycles.
|
|
345
|
+
3. Run the normal page-document validation and security checks.
|
|
346
|
+
4. Store `compilePageCompositions(document)` as the immutable runtime document.
|
|
347
|
+
|
|
348
|
+
The runtime document contains no composition reference and never loads a
|
|
349
|
+
repository. A missing repository therefore affects authoring/update only, not a
|
|
350
|
+
previously materialized draft or an already published IDP page.
|