@plitzi/sdk-server 0.33.1 → 0.34.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/CHANGELOG.md +53 -0
- package/README.md +283 -8
- package/dist/actions.d.ts +62 -0
- package/dist/actions.js +12 -0
- package/dist/adapters/cloudAdapters.d.ts +72 -0
- package/dist/adapters/cloudAdapters.js +303 -0
- package/dist/adapters/space/index.d.ts +93 -0
- package/dist/adapters/space/index.js +122 -0
- package/dist/adapters/space/resolvers.d.ts +69 -0
- package/dist/adapters/space/resolvers.js +79 -0
- package/dist/adapters/space/space.test.d.ts +1 -0
- package/dist/adapters/space/types.d.ts +64 -0
- package/dist/adapters/space/types.js +41 -0
- package/dist/auth.d.ts +50 -0
- package/dist/auth.js +19 -0
- package/dist/core/auth/api.d.ts +400 -11
- package/dist/core/auth/api.js +1044 -50
- package/dist/core/auth/createAuth.d.ts +135 -30
- package/dist/core/auth/createAuth.js +96 -24
- package/dist/core/auth/credentials.d.ts +9 -3
- package/dist/core/auth/credentials.js +10 -4
- package/dist/core/auth/csrf.d.ts +89 -0
- package/dist/core/auth/csrf.js +234 -0
- package/dist/core/auth/csrf.test.d.ts +1 -0
- package/dist/core/auth/identity.d.ts +6 -0
- package/dist/core/auth/identity.js +37 -8
- package/dist/core/auth/lifecycle.test.d.ts +1 -0
- package/dist/core/auth/oauth/index.d.ts +8 -0
- package/dist/core/auth/oauth/index.js +13 -15
- package/dist/core/auth/passwords.d.ts +15 -0
- package/dist/core/auth/passwords.js +32 -0
- package/dist/core/auth/redirects.d.ts +18 -0
- package/dist/core/auth/redirects.js +31 -0
- package/dist/core/auth/redirects.test.d.ts +1 -0
- package/dist/core/auth/routes.d.ts +4 -2
- package/dist/core/auth/routes.js +234 -9
- package/dist/core/auth/session.d.ts +11 -0
- package/dist/core/auth/session.js +1 -1
- package/dist/core/auth/spaceTokens.d.ts +38 -2
- package/dist/core/auth/spaceTokens.js +54 -2
- package/dist/core/auth/throttle.d.ts +5 -0
- package/dist/core/auth/throttle.js +81 -0
- package/dist/core/auth/throttle.test.d.ts +1 -0
- package/dist/core/auth/tokens.d.ts +83 -12
- package/dist/core/auth/tokens.js +51 -9
- package/dist/core/auth/totp.d.ts +48 -0
- package/dist/core/auth/totp.js +118 -0
- package/dist/core/auth/totp.test.d.ts +1 -0
- package/dist/core/createServer.d.ts +0 -6
- package/dist/core/createServer.js +35 -3
- package/dist/core/fontStore.d.ts +33 -0
- package/dist/core/fontStore.js +53 -0
- package/dist/core/fontStore.test.d.ts +1 -0
- package/dist/core/handlers/authMiddleware.js +1 -1
- package/dist/core/handlers/authRouteHandlers.d.ts +9 -1
- package/dist/core/handlers/authRouteHandlers.js +4 -3
- package/dist/core/handlers/csrfMiddleware.d.ts +20 -0
- package/dist/core/handlers/csrfMiddleware.js +32 -0
- package/dist/core/handlers/oauthRouteHandlers.d.ts +46 -0
- package/dist/core/handlers/oauthRouteHandlers.js +159 -0
- package/dist/core/handlers/socialRouteHandlers.d.ts +40 -0
- package/dist/core/handlers/socialRouteHandlers.js +129 -0
- package/dist/core/handlers/socialRouteHandlers.test.d.ts +1 -0
- package/dist/core/handlers/types.d.ts +22 -5
- package/dist/core/health.d.ts +11 -1
- package/dist/core/health.js +27 -3
- package/dist/core/http/dispatcher.d.ts +1 -1
- package/dist/core/http/dispatcher.js +20 -1
- package/dist/core/http/stages/authApi.js +1 -1
- package/dist/core/http/stages/fontAssets.d.ts +9 -0
- package/dist/core/http/stages/fontAssets.js +27 -0
- package/dist/core/http/stages/oauth.d.ts +19 -0
- package/dist/core/http/stages/oauth.js +118 -0
- package/dist/core/http/types.d.ts +12 -0
- package/dist/core/oauth/authorize.d.ts +22 -0
- package/dist/core/oauth/authorize.js +254 -0
- package/dist/core/oauth/authorize.test.d.ts +1 -0
- package/dist/core/oauth/challenge.d.ts +11 -0
- package/dist/core/oauth/challenge.js +33 -0
- package/dist/core/oauth/consentPage.d.ts +12 -0
- package/dist/core/oauth/consentPage.js +131 -0
- package/dist/core/oauth/metadata.d.ts +41 -0
- package/dist/core/oauth/metadata.js +71 -0
- package/dist/core/oauth/params.d.ts +5 -0
- package/dist/core/oauth/params.js +5 -0
- package/dist/core/oauth/pkce.d.ts +6 -0
- package/dist/core/oauth/pkce.js +15 -0
- package/dist/core/oauth/records.d.ts +72 -0
- package/dist/core/oauth/records.js +49 -0
- package/dist/core/oauth/register.d.ts +5 -0
- package/dist/core/oauth/register.js +55 -0
- package/dist/core/oauth/respond.d.ts +21 -0
- package/dist/core/oauth/respond.js +59 -0
- package/dist/core/oauth/token.d.ts +14 -0
- package/dist/core/oauth/token.js +130 -0
- package/dist/core/previewToken.d.ts +20 -0
- package/dist/core/previewToken.js +29 -1
- package/dist/core/server/pageServer.js +4 -1
- package/dist/core/services/action.d.ts +6 -4
- package/dist/core/services/action.js +103 -10
- package/dist/core/services/registry.js +2 -0
- package/dist/core/services/resolve.d.ts +8 -0
- package/dist/core/services/resolve.js +12 -1
- package/dist/core/staticFiles.js +1 -2
- package/dist/handlers.d.ts +7 -1
- package/dist/handlers.js +4 -1
- package/dist/helpers/buildResponseHelpers.d.ts +8 -0
- package/dist/helpers/buildResponseHelpers.js +9 -1
- package/dist/helpers/buildServerInfo.d.ts +8 -3
- package/dist/helpers/buildServerInfo.js +18 -14
- package/dist/helpers/cache/keys.d.ts +13 -0
- package/dist/helpers/cache/keys.js +12 -1
- package/dist/helpers/onAbort.d.ts +12 -0
- package/dist/helpers/onAbort.js +22 -0
- package/dist/helpers/onAbort.test.d.ts +1 -0
- package/dist/helpers/outboundGuard.d.ts +27 -0
- package/dist/helpers/outboundGuard.js +49 -0
- package/dist/helpers/outboundGuard.test.d.ts +1 -0
- package/dist/helpers/serverLog.d.ts +6 -3
- package/dist/helpers/serverLog.js +20 -3
- package/dist/index.d.ts +6 -0
- package/dist/index.js +9 -4
- package/dist/kernel.d.ts +5 -22
- package/dist/kernel.js +1 -14
- package/dist/modules/actions/{handler.js → connectorWrite.js} +5 -2
- package/dist/modules/actions/connectorWrite.test.d.ts +1 -0
- package/dist/modules/actions/index.d.ts +40 -0
- package/dist/modules/actions/index.js +46 -0
- package/dist/modules/actions/moduleFor.d.ts +3 -0
- package/dist/modules/actions/moduleFor.js +35 -0
- package/dist/modules/actions/moduleFor.test.d.ts +1 -0
- package/dist/modules/actions/runtime/check.d.ts +24 -0
- package/dist/modules/actions/runtime/check.js +111 -0
- package/dist/modules/actions/runtime/check.test.d.ts +1 -0
- package/dist/modules/actions/runtime/errors.d.ts +11 -0
- package/dist/modules/actions/runtime/errors.js +17 -0
- package/dist/modules/actions/runtime/guards.d.ts +126 -0
- package/dist/modules/actions/runtime/guards.js +246 -0
- package/dist/modules/actions/runtime/guards.test.d.ts +1 -0
- package/dist/modules/actions/runtime/kvStore.d.ts +27 -0
- package/dist/modules/actions/runtime/kvStore.js +41 -0
- package/dist/modules/actions/runtime/kvStore.test.d.ts +1 -0
- package/dist/modules/actions/runtime/limits.d.ts +11 -0
- package/dist/modules/actions/runtime/limits.js +35 -0
- package/dist/modules/actions/runtime/memoryKv.d.ts +2 -0
- package/dist/modules/actions/runtime/memoryKv.js +77 -0
- package/dist/modules/actions/runtime/namespaceKv.d.ts +9 -0
- package/dist/modules/actions/runtime/namespaceKv.js +19 -0
- package/dist/modules/actions/runtime/precheck.d.ts +27 -0
- package/dist/modules/actions/runtime/precheck.js +45 -0
- package/dist/modules/actions/runtime/renderResolver.d.ts +15 -0
- package/dist/modules/actions/runtime/renderResolver.js +130 -0
- package/dist/modules/actions/runtime/renderResolver.test.d.ts +1 -0
- package/dist/modules/actions/runtime/renderShare.d.ts +29 -0
- package/dist/modules/actions/runtime/renderShare.js +36 -0
- package/dist/modules/actions/runtime/renderShare.test.d.ts +1 -0
- package/dist/modules/actions/runtime/report.d.ts +14 -0
- package/dist/modules/actions/runtime/report.js +22 -0
- package/dist/modules/actions/runtime/runAction.d.ts +12 -0
- package/dist/modules/actions/runtime/runAction.js +405 -0
- package/dist/modules/actions/runtime/runAction.test.d.ts +1 -0
- package/dist/modules/actions/runtime/runLogger.d.ts +31 -0
- package/dist/modules/actions/runtime/runLogger.js +66 -0
- package/dist/modules/actions/runtime/runLogger.test.d.ts +1 -0
- package/dist/modules/actions/runtime/schedule.d.ts +35 -0
- package/dist/modules/actions/runtime/schedule.js +76 -0
- package/dist/modules/actions/runtime/schedule.test.d.ts +1 -0
- package/dist/modules/actions/runtime/scope.d.ts +40 -0
- package/dist/modules/actions/runtime/scope.js +103 -0
- package/dist/modules/actions/runtime/triggers.d.ts +12 -0
- package/dist/modules/actions/runtime/triggers.js +14 -0
- package/dist/modules/actions/taskCatalog.d.ts +26 -0
- package/dist/modules/actions/taskCatalog.js +24 -0
- package/dist/modules/actions/taskCatalog.test.d.ts +1 -0
- package/dist/modules/actions/tasks/auth.d.ts +2 -0
- package/dist/modules/actions/tasks/auth.js +40 -0
- package/dist/modules/actions/tasks/builtins.d.ts +8 -0
- package/dist/modules/actions/tasks/builtins.js +24 -0
- package/dist/modules/actions/tasks/connector.d.ts +2 -0
- package/dist/modules/actions/tasks/connector.js +141 -0
- package/dist/modules/actions/tasks/db.d.ts +2 -0
- package/dist/modules/actions/tasks/db.js +59 -0
- package/dist/modules/actions/tasks/db.test.d.ts +1 -0
- package/dist/modules/actions/tasks/flow.d.ts +3 -0
- package/dist/modules/actions/tasks/flow.js +109 -0
- package/dist/modules/actions/tasks/helpers.d.ts +16 -0
- package/dist/modules/actions/tasks/helpers.js +30 -0
- package/dist/modules/actions/tasks/http.d.ts +2 -0
- package/dist/modules/actions/tasks/http.js +111 -0
- package/dist/modules/actions/tasks/http.test.d.ts +1 -0
- package/dist/modules/actions/tasks/kv.d.ts +2 -0
- package/dist/modules/actions/tasks/kv.js +102 -0
- package/dist/modules/actions/tasks/kv.test.d.ts +1 -0
- package/dist/modules/actions/tasks/registry.d.ts +10 -0
- package/dist/modules/actions/tasks/registry.js +36 -0
- package/dist/modules/actions/tasks/transform.d.ts +2 -0
- package/dist/modules/actions/tasks/transform.js +34 -0
- package/dist/modules/actions/transport/callHandler.d.ts +24 -0
- package/dist/modules/actions/transport/callHandler.js +233 -0
- package/dist/modules/actions/transport/callHandler.test.d.ts +1 -0
- package/dist/modules/actions/transport/cancelHandler.d.ts +23 -0
- package/dist/modules/actions/transport/cancelHandler.js +23 -0
- package/dist/modules/actions/transport/catalogHandler.d.ts +18 -0
- package/dist/modules/actions/transport/catalogHandler.js +21 -0
- package/dist/modules/actions/transport/stream.d.ts +23 -0
- package/dist/modules/actions/transport/stream.js +100 -0
- package/dist/modules/actions/transport/verifySignature.d.ts +16 -0
- package/dist/modules/actions/transport/verifySignature.js +72 -0
- package/dist/modules/actions/transport/webhookHandler.d.ts +25 -0
- package/dist/modules/actions/transport/webhookHandler.js +206 -0
- package/dist/modules/actions/transport/webhookHandler.test.d.ts +1 -0
- package/dist/modules/actions/types.d.ts +234 -0
- package/dist/modules/connectors/engine.js +4 -1
- package/dist/modules/connectors/resolver.d.ts +10 -2
- package/dist/modules/connectors/resolver.js +8 -3
- package/dist/modules/mysql/accounts.d.ts +5 -0
- package/dist/modules/mysql/accounts.js +365 -0
- package/dist/modules/mysql/accounts.test.d.ts +1 -0
- package/dist/modules/mysql/admin.d.ts +58 -0
- package/dist/modules/mysql/admin.js +133 -0
- package/dist/modules/mysql/config.d.ts +82 -0
- package/dist/modules/mysql/config.js +30 -0
- package/dist/modules/mysql/identities.d.ts +35 -0
- package/dist/modules/mysql/identities.js +43 -0
- package/dist/modules/mysql/index.d.ts +67 -0
- package/dist/modules/mysql/index.js +62 -0
- package/dist/modules/mysql/pool.d.ts +3 -0
- package/dist/modules/mysql/pool.js +88 -0
- package/dist/modules/mysql/query.d.ts +12 -0
- package/dist/modules/mysql/query.js +21 -0
- package/dist/modules/mysql/schema.d.ts +43 -0
- package/dist/modules/mysql/schema.js +340 -0
- package/dist/modules/mysql/schema.test.d.ts +1 -0
- package/dist/modules/mysql/sessions.d.ts +33 -0
- package/dist/modules/mysql/sessions.js +46 -0
- package/dist/modules/mysql/spaceTokens.d.ts +11 -0
- package/dist/modules/mysql/spaceTokens.js +59 -0
- package/dist/modules/mysql/store.integration.test.d.ts +1 -0
- package/dist/modules/rsc/connectorRscData.d.ts +25 -0
- package/dist/modules/rsc/connectorRscData.js +51 -0
- package/dist/modules/rsc/connectorRscData.test.d.ts +1 -0
- package/dist/modules/rsc/handler.js +16 -3
- package/dist/modules/rsc/matchRscPage.d.ts +14 -0
- package/dist/modules/rsc/matchRscPage.js +26 -0
- package/dist/modules/rsc/resolveRscData.d.ts +14 -1
- package/dist/modules/rsc/resolveRscData.js +23 -34
- package/dist/modules/ssr/Component.d.ts +6 -2
- package/dist/modules/ssr/Component.js +3 -1
- package/dist/modules/ssr/draftSession.test.d.ts +1 -0
- package/dist/modules/ssr/handler.js +15 -2
- package/dist/modules/ssr/loadPluginComponents.js +22 -5
- package/dist/modules/ssr/prepareRender.js +87 -8
- package/dist/modules/ssr/prepareRender.test.d.ts +1 -0
- package/dist/modules/ssr/preview.d.ts +21 -8
- package/dist/modules/ssr/preview.js +38 -14
- package/dist/modules/ssr/registerExternalPlugins.js +2 -2
- package/dist/modules/ssr/resolvePageSeo.d.ts +18 -0
- package/dist/modules/ssr/resolvePageSeo.js +26 -0
- package/dist/modules/ssr/resolvePageSeo.test.d.ts +1 -0
- package/dist/modules/ssr/template.test.d.ts +1 -0
- package/dist/modules/ssr/views/template.ejs +71 -5
- package/dist/mysql.d.ts +26 -0
- package/dist/mysql.js +4 -0
- package/dist/oauth.d.ts +24 -0
- package/dist/oauth.js +10 -0
- package/dist/plugins/compile.d.ts +1 -0
- package/dist/plugins/compile.js +37 -3
- package/dist/plugins/manager.d.ts +40 -0
- package/dist/plugins/manager.js +113 -13
- package/dist/plugins/manager.test.d.ts +1 -0
- package/package.json +43 -14
- package/skills/plitzi-authoring/SKILL.md +252 -0
- /package/dist/{modules/actions/handler.test.d.ts → adapters/cloudAdapters.test.d.ts} +0 -0
- /package/dist/modules/actions/{handler.d.ts → connectorWrite.d.ts} +0 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: plitzi-authoring
|
|
3
|
+
description: >-
|
|
4
|
+
Write a Plitzi space or a publishable template in TypeScript — pages, elements, CSS, data bindings and flows —
|
|
5
|
+
instead of hand-writing schema JSON. Use whenever the task is to create, extend or re-theme a space: adding a
|
|
6
|
+
page or a section, styling one, binding an element to server data, wiring what happens on click, authoring a
|
|
7
|
+
template to host, or turning an exported JSON into something maintainable.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Authoring Plitzi spaces
|
|
11
|
+
|
|
12
|
+
A Plitzi space is two documents — a schema and a style — of deeply cross-referenced ids. **Do not write them by
|
|
13
|
+
hand.** Every id, class name, parent/root link, breakpoint map and interaction chain is derived from a much
|
|
14
|
+
smaller declaration, and the surface that derives them also refuses a declaration that would not render.
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import { authorSpace, container, heading, text } from '@plitzi/sdk-authoring';
|
|
18
|
+
|
|
19
|
+
const { schema, style, warnings } = authorSpace({
|
|
20
|
+
name: 'My space',
|
|
21
|
+
permanentUrl: 'my-space',
|
|
22
|
+
classes: { page: { desktop: { display: 'flex', 'flex-direction': 'column', padding: '96px 24px', gap: '16px' } } },
|
|
23
|
+
pages: [
|
|
24
|
+
{ name: 'Home', slug: '', class: 'page', body: [heading('Hello', { subType: 'h1' }), text('A paragraph.')] }
|
|
25
|
+
]
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Serve it with the adapters the page server already takes:
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
createServer({ port: 3001, adapters: createJsonAdapters({ offlineData: { schema, style } }) });
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
One package, and it installs nothing: `@plitzi/sdk-authoring` has an empty dependency tree, no React and nothing
|
|
36
|
+
that touches a browser, so a seed, a migration, a build script or a project that only publishes templates depends
|
|
37
|
+
on it alone.
|
|
38
|
+
|
|
39
|
+
## The types are the reference
|
|
40
|
+
|
|
41
|
+
Every factory, spec field and step builder carries its documentation in the published `.d.ts`. Read it rather
|
|
42
|
+
than guessing — `node_modules/@plitzi/sdk-authoring/dist/index.d.ts` is the whole surface in one file. Attribute
|
|
43
|
+
types come from each element's own component, so an editor completes them and a wrong value is a compile error.
|
|
44
|
+
|
|
45
|
+
## Elements
|
|
46
|
+
|
|
47
|
+
One factory per element, named after it. Attributes and the authoring fields go in ONE flat object:
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
heading({ content: 'Fieldnotes', subType: 'h2', class: 'title' })
|
|
51
|
+
image({ src: '/fox.jpg', alt: 'A fox', css: { 'aspect-ratio': '3/2' } })
|
|
52
|
+
container({ class: 'card', children: [ … ] })
|
|
53
|
+
text('Wildlife, close up') // a string is the content
|
|
54
|
+
container([hero, grid]) // an array is the children
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
| Authoring field | What it does |
|
|
58
|
+
| --- | --- |
|
|
59
|
+
| `id` | the ONE name this element answers to — its key in the document, a binding's source, a step's target. **Name anything something else refers to**: a derived `<type>-<n>` is positional |
|
|
60
|
+
| `class` | a shared class: a name from the space's `classes`, or a `styles()` declaration. Exclusive with `css` |
|
|
61
|
+
| `css` | rules of this element's own: one set, or one per breakpoint (`{ desktop, tablet, mobile }`) |
|
|
62
|
+
| `variant` | a style variant of the element's own vocabulary |
|
|
63
|
+
| `slots` | a class for one of the element's OTHER selectors — a form control's `input`, `label`, `error` |
|
|
64
|
+
| `bind` | where a value comes from |
|
|
65
|
+
| `visible` | show it only while this source is true; `!source` for the inverse |
|
|
66
|
+
| `flows` | what happens on click, on submit, on load |
|
|
67
|
+
| `runtime` | `'server'` resolves this element's data on the server |
|
|
68
|
+
| `children` | the tree |
|
|
69
|
+
| `meta` | `meta.label` is the element's name in the builder's tree |
|
|
70
|
+
|
|
71
|
+
Anything else in the object is an **attribute**. `label` belongs to the attribute (a link and a form control both
|
|
72
|
+
have one); the builder's name for the element is `meta.label`.
|
|
73
|
+
|
|
74
|
+
A type this SDK does not ship — a plugin, one the deployment brings — is authored the same way:
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
const speciesStatus = defineElement<{ status?: string }>({ type: 'speciesStatus', content: { … } });
|
|
78
|
+
element<{ status?: string }>('speciesStatus', { status: 'vulnerable' }); // or one at a time
|
|
79
|
+
elementsFromManifest(manifest); // or a whole plugin manifest
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Style
|
|
83
|
+
|
|
84
|
+
Write CSS the way you write CSS, shorthands included — they are expanded before they reach the document, because
|
|
85
|
+
Plitzi's style editor reads a closed list of longhand properties:
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
css({ padding: '96px 24px', border: '1px solid var(--line)', 'border-radius': '12px' })
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
You rarely call `css` yourself: `authorSpace` runs every rule set through it. What you get is the refusal — a
|
|
92
|
+
property outside the vocabulary is an error naming the correct key (`paddingTop` → `padding-top`).
|
|
93
|
+
|
|
94
|
+
- `column(gap, extra?)`, `row(gap, extra?)`, `grid(columns, gap, extra?)` for the three layouts every space repeats.
|
|
95
|
+
- Per element TYPE defaults go in `elements: { heading: { base: …, variants: { … } } }`.
|
|
96
|
+
|
|
97
|
+
**Share a rule as a class, never as a spread.** Writing a rule set once in a `const` and spreading it into each
|
|
98
|
+
element's `css` shares the source and duplicates the document — one selector per element, so re-theming the card
|
|
99
|
+
in the builder re-themes one card. `styles()` declares the class where it is used and writes it once:
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
const card = styles('card', { padding: '24px', 'border-radius': '12px', 'background-color': 'var(--surface)' });
|
|
103
|
+
|
|
104
|
+
container({ class: card, children: [ … ] });
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Accepted anywhere a class name is — `class`, a `slot`, a page's `class` — and collected from wherever the tree
|
|
108
|
+
names it. One name declared twice with rules that disagree is refused. `classes` at the top of the space is the
|
|
109
|
+
same mechanism for what describes the space rather than one section of it.
|
|
110
|
+
|
|
111
|
+
An element has exactly ONE base selector, so a variant is its own class over a shared plain object
|
|
112
|
+
(`styles('button-primary', { ...base, … })`), never two classes layered on top of each other.
|
|
113
|
+
|
|
114
|
+
## Data
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
heading({ bind: { content: 'posts.title' } }) // short form: attributes
|
|
118
|
+
paragraph({ visible: 'posts.hasPosts' }) // on screen only while this is true
|
|
119
|
+
paragraph({ visible: '!posts.hasPosts' }) // …and its inverse
|
|
120
|
+
container({ bind: [{ to: 'content', source: 'x.y', transformers: [ … ] }] }) // full form
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**A source names the id you gave the element** — `'posts.title'`, `'postList.item.cover'` — and the prefix is
|
|
124
|
+
filled in. Only half of a source name is yours: the other half is the kind of source the ELEMENT publishes, and it
|
|
125
|
+
is not always the word you can see (a `form` publishes under `apiContainer`). The four globals — `variables`,
|
|
126
|
+
`navigation`, `auth`, `state` — are named as themselves. A full name still works and is checked the same way: a
|
|
127
|
+
prefix that does not match the element, or a name nothing answers to, is refused when the space is authored. It
|
|
128
|
+
is the quietest failure a space can carry.
|
|
129
|
+
|
|
130
|
+
Server-resolved sections are an `apiContainer` with `runtime: 'server'` naming a connector or an action, and a
|
|
131
|
+
space that has any needs `rsc: { enabled: true }`.
|
|
132
|
+
|
|
133
|
+
**Never ask the data for a field's opposite.** Both sides of one question are `visible: 'x'` and `visible: '!x'` —
|
|
134
|
+
not an `x` and a `notX` beside it in the server's answer. The `!` is the `not` transformer, which reads a boolean
|
|
135
|
+
that travelled as text (`"false"`, `"0"`) and treats an empty array as false; an empty object is true. Only for a
|
|
136
|
+
real inverse — a three-state condition (`Boolean(post) && !canEdit`) still belongs where the data is made.
|
|
137
|
+
|
|
138
|
+
## Flows
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
button({
|
|
142
|
+
id: 'cta',
|
|
143
|
+
content: 'Get a quote',
|
|
144
|
+
flows: [[
|
|
145
|
+
onClick(),
|
|
146
|
+
named('quote', runServerAction({ actionId: 'shipping-quote', input: '{"city":"Berlin"}', mode: 'await' })),
|
|
147
|
+
setState({ key: 'quote', type: 'text', value: '{{quote.output.summary}}' })
|
|
148
|
+
]]
|
|
149
|
+
})
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Use the step builders — they answer the three things that go wrong silently:
|
|
153
|
+
|
|
154
|
+
- **Where a step runs.** A global callback registers under its source MODULE (`state`, `auth`, `actions`), an
|
|
155
|
+
element callback under an element's id, a utility under nothing. The builders fill it in; a trigger and an
|
|
156
|
+
untargeted `updateElement` are filled with the element the flow was declared on.
|
|
157
|
+
- **Which `setState`.** `setState(…)` writes `runtime.state.<key>`; `updateElement(…)` changes one element's own
|
|
158
|
+
attribute or state. Different params, different node kind. Each has a flip-it counterpart storing the opposite
|
|
159
|
+
of what is there, which is how expand/collapse is ONE step on ONE trigger: `toggleState({ key })` for app state,
|
|
160
|
+
and `toggleElement({ category: 'state', key: 'visibility' }, 'panel')` to show/hide an element (the second
|
|
161
|
+
argument is the element it acts on; omitted, it acts on the one the flow is declared on). Never two branches
|
|
162
|
+
under opposite `when` guards — those read the state as it was when the flow STARTED, so they run a click behind.
|
|
163
|
+
- **What it takes.** Params are typed from the same declaration the builder's own panel is drawn from.
|
|
164
|
+
|
|
165
|
+
`named(id, step)` is how a later step reads an earlier one — the flow scope is keyed by node id, so
|
|
166
|
+
`{{quote.output.summary}}` resolves only when that step is called `quote`. `mode: 'await'` is what puts a run's
|
|
167
|
+
answer in the scope at all, and it is the default.
|
|
168
|
+
|
|
169
|
+
**Pass `input` as an object, not as a line of JSON text.** Both are accepted, and the text form fails silently: an
|
|
170
|
+
interpolated value carrying a quotation mark or a newline — a post body, a comment — makes it unparseable, and
|
|
171
|
+
unparseable input posts `{}` rather than refusing.
|
|
172
|
+
|
|
173
|
+
A flow is a list and never a tree, so "only if" is expressed on the step:
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
whenSucceeded('quote', navigate({ urlType: 'internal', url: '{{quote.output.url}}' })),
|
|
177
|
+
whenFailed('quote', setState({ key: 'notice', type: 'text', value: '{{quote.reason}}' })),
|
|
178
|
+
when({ field: 'state.count', operator: '>', value: 3 }, addNotification({ content: 'Enough' }))
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
`whenFailed` matches every outcome that is not `completed` — a run also comes back `skipped` or `aborted`, and
|
|
182
|
+
matching only `failed` is how those two end up doing nothing.
|
|
183
|
+
|
|
184
|
+
## What gets refused
|
|
185
|
+
|
|
186
|
+
`authorSpace` throws rather than hand back a space that would not render:
|
|
187
|
+
|
|
188
|
+
- a CSS property the style editor could not read back
|
|
189
|
+
- a `class` or a `slot` naming a class the space does not declare (the error names the one you probably meant)
|
|
190
|
+
- an element asking for a shared class AND rules of its own — an element has one base selector
|
|
191
|
+
- one class name declared twice with rules that disagree
|
|
192
|
+
- a binding source naming an element nothing answers to, or one whose prefix is not what that element publishes
|
|
193
|
+
- a name that shadows a global data source (`variables`, `navigation`, `auth`, `state`)
|
|
194
|
+
- a step target naming an element that is not there
|
|
195
|
+
- two elements answering to one name, a broken flow chain, an orphan, a cycle
|
|
196
|
+
- a global callback on the wrong module — or on none — and a utility given one. A global callback registers under
|
|
197
|
+
its SOURCE MODULE (`auth`, `state`, `actions`), and the pair is what the runtime resolves a step by, so naming
|
|
198
|
+
either half wrong is a control that does nothing at all with no error anywhere. An action no built-in source
|
|
199
|
+
declares comes back in `warnings` instead of throwing, because a plugin may register a module of its own.
|
|
200
|
+
|
|
201
|
+
Those last checks need the vocabulary, which only the composed package has. Import `authorSpace` from
|
|
202
|
+
`@plitzi/sdk-authoring` — not straight from `@plitzi/sdk-schema` — and you get them.
|
|
203
|
+
|
|
204
|
+
For documents you did not author here — an export from the builder, a JSON edited by hand — run the same gate
|
|
205
|
+
before serving it:
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
const { valid, errors, warnings } = validateSpace({ schema, style });
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Templates
|
|
212
|
+
|
|
213
|
+
A template is not a space: it is ONE subtree, the style that dresses it and a name, published as a JSON someone
|
|
214
|
+
fetches by URL and drags onto a canvas you will never see.
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
import { authorTemplate } from '@plitzi/sdk-authoring';
|
|
218
|
+
|
|
219
|
+
const { template, warnings } = authorTemplate({
|
|
220
|
+
name: 'Pricing card',
|
|
221
|
+
description: 'A price, a list of features and a call to action.',
|
|
222
|
+
classes: { card: { padding: '24px', 'border-radius': '12px', 'background-color': 'var(--surface)' } },
|
|
223
|
+
root: container({ class: 'card', children: [heading('$19', { subType: 'h3' }), button({ content: 'Start' })] })
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
await writeFile('pricing-card.json', JSON.stringify(template, null, 2));
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Host that file and add it to a space's resources as an `application/json` — nothing else is required of you.
|
|
230
|
+
|
|
231
|
+
Everything a space is held to still applies, and two more things apply because a template LEAVES its space:
|
|
232
|
+
|
|
233
|
+
- **Everything it names, it carries.** A class declared in the space it was cut from does not travel; the element
|
|
234
|
+
keeps the class name, finds no rules wherever it is dropped, and renders unstyled. Declare in `classes` (or with
|
|
235
|
+
`styles()`) every rule the subtree names — `validateTemplate` warns about a name the manifest does not carry.
|
|
236
|
+
- **A binding may not point outside the subtree.** A source names an element by id, so binding to a provider
|
|
237
|
+
that stayed behind is dead on arrival — refused. Bring the provider (the `apiContainer`, the `form`) into the
|
|
238
|
+
template, or bind to one of the globals: `variables`, `navigation`, `auth`, `state`.
|
|
239
|
+
|
|
240
|
+
`validateTemplate(template)` runs the same gate over a manifest you did not author here — one exported by the
|
|
241
|
+
builder, or edited by hand — before you publish it.
|
|
242
|
+
|
|
243
|
+
## Rules
|
|
244
|
+
|
|
245
|
+
1. **Never hand-write `flat`, element ids, `styleSelectors`, `beforeNode`/`afterNode`/`flowId`.** They are derived.
|
|
246
|
+
Writing them is how a space half-renders with nothing reporting why.
|
|
247
|
+
2. **Name what is referred to.** `id` on any element a binding, a step or a pager addresses.
|
|
248
|
+
3. **Read the error.** Every refusal above names the element, the class or the property at fault; it is a bug in
|
|
249
|
+
the declaration, not a reason to work around the check.
|
|
250
|
+
4. **Ids are stable.** They are hashes of the path that produced them, so re-authoring an unchanged space writes
|
|
251
|
+
byte-identical documents — a seed can re-run and a diff stays readable.
|
|
252
|
+
5. **`warnings` is returned, not printed.** Read it if the space is generated in a build.
|
|
File without changes
|
|
File without changes
|