@plitzi/sdk-shared 0.38.13 → 0.38.15
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 +247 -0
- package/dist/authoring/declare.d.ts +7 -0
- package/dist/authoring/index.mjs +2 -2
- package/dist/authoring/spaceCallbacks.d.ts +29 -0
- package/dist/authoring/spaceCallbacks.mjs +41 -20
- package/dist/helpers/clipboard.d.ts +10 -0
- package/dist/helpers/clipboard.mjs +17 -0
- package/dist/helpers/enclosingSpace.d.ts +9 -0
- package/dist/helpers/enclosingSpace.mjs +5 -0
- package/dist/helpers/spaceRoot.d.ts +4 -0
- package/dist/helpers/spaceRoot.mjs +4 -0
- package/dist/project/network.d.ts +12 -0
- package/dist/project/network.mjs +4 -0
- package/dist/realtime/topics.mjs +3 -3
- package/dist/store/index.d.ts +33 -33
- package/dist/store/renderSettings.d.ts +1 -0
- package/dist/store/renderSettings.mjs +9 -5
- package/dist/types/ActionTypes.d.ts +38 -0
- package/dist/types/RealtimeTypes.d.ts +12 -0
- package/dist/types/ServerTypes.d.ts +22 -2
- package/dist/types/StoreTypes.d.ts +8 -2
- package/package.json +17 -2
- package/setupTests.ts +6 -5
|
@@ -10,9 +10,10 @@ var n = {
|
|
|
10
10
|
hydrated: !1,
|
|
11
11
|
overQuota: !1,
|
|
12
12
|
testAttributes: !0,
|
|
13
|
-
ownsHead: !0
|
|
13
|
+
ownsHead: !0,
|
|
14
|
+
enclosed: !1
|
|
14
15
|
}, r = () => {
|
|
15
|
-
let [[r, i, a, o, s, c, l, u, d]] = e([
|
|
16
|
+
let [[r, i, a, o, s, c, l, u, d, f]] = e([
|
|
16
17
|
"render.previewMode",
|
|
17
18
|
"render.debugMode",
|
|
18
19
|
"render.renderMode",
|
|
@@ -21,7 +22,8 @@ var n = {
|
|
|
21
22
|
"render.hydrated",
|
|
22
23
|
"render.overQuota",
|
|
23
24
|
"render.testAttributes",
|
|
24
|
-
"render.ownsHead"
|
|
25
|
+
"render.ownsHead",
|
|
26
|
+
"render.enclosed"
|
|
25
27
|
]);
|
|
26
28
|
return t(() => ({
|
|
27
29
|
previewMode: r ?? n.previewMode,
|
|
@@ -32,7 +34,8 @@ var n = {
|
|
|
32
34
|
hydrated: c ?? n.hydrated,
|
|
33
35
|
overQuota: l ?? n.overQuota,
|
|
34
36
|
testAttributes: u ?? n.testAttributes,
|
|
35
|
-
ownsHead: d ?? n.ownsHead
|
|
37
|
+
ownsHead: d ?? n.ownsHead,
|
|
38
|
+
enclosed: f ?? n.enclosed
|
|
36
39
|
}), [
|
|
37
40
|
r,
|
|
38
41
|
i,
|
|
@@ -42,7 +45,8 @@ var n = {
|
|
|
42
45
|
c,
|
|
43
46
|
l,
|
|
44
47
|
u,
|
|
45
|
-
d
|
|
48
|
+
d,
|
|
49
|
+
f
|
|
46
50
|
]);
|
|
47
51
|
}, i = (e) => {
|
|
48
52
|
let n = r();
|
|
@@ -17,6 +17,43 @@ export type ActionField = {
|
|
|
17
17
|
/** Shown in the builder, and read by the MCP agent when it wires a call. */
|
|
18
18
|
label?: string;
|
|
19
19
|
};
|
|
20
|
+
/** What a caller sends for a field of a type: text for `text`, `date` and `file`, anything parseable for `json`. */
|
|
21
|
+
type ActionFieldValue<T extends ActionFieldType> = T extends 'number' ? number : T extends 'boolean' ? boolean : T extends 'json' ? unknown : string;
|
|
22
|
+
/** The input a caller hands an action, from the fields it declares: those `required: true` must be there. */
|
|
23
|
+
export type ActionInputOf<Fields extends Readonly<Record<string, ActionField>>> = {
|
|
24
|
+
-readonly [K in keyof Fields as Fields[K]['required'] extends true ? K : never]: ActionFieldValue<Fields[K]['type']>;
|
|
25
|
+
} & {
|
|
26
|
+
-readonly [K in keyof Fields as Fields[K]['required'] extends true ? never : K]?: ActionFieldValue<Fields[K]['type']>;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* The key a typed action's input and output ride under, in its type only — nothing holds it at run time. Exported so a
|
|
30
|
+
* package that emits declarations can name the type of an action it exports (`export const actions = [defineAction(…)]`):
|
|
31
|
+
* a symbol it cannot import is one its `.d.ts` cannot write (TS4023).
|
|
32
|
+
*/
|
|
33
|
+
export declare const CALL_TYPES: unique symbol;
|
|
34
|
+
/**
|
|
35
|
+
* An action whose `call` way in is known to the types — what it takes and what it answers: what `defineAction` and
|
|
36
|
+
* `taskAction` answer, so a page that runs it (`useServerAction<typeof saveHabit>('save-habit')`) is held to the input
|
|
37
|
+
* it declares and handed the output typed. Nothing of it exists at run time — the action is the same document.
|
|
38
|
+
*/
|
|
39
|
+
export type TypedActionEntry<Input, Output = unknown> = ActionEntry & {
|
|
40
|
+
readonly [CALL_TYPES]?: {
|
|
41
|
+
input: Input;
|
|
42
|
+
output: Output;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
/** The input an action's `call` way in takes, from its type — any object, for an action whose type does not say. */
|
|
46
|
+
export type CallInputOf<Action> = Action extends {
|
|
47
|
+
readonly [CALL_TYPES]?: {
|
|
48
|
+
input: infer Input;
|
|
49
|
+
};
|
|
50
|
+
} ? unknown extends Input ? Record<string, unknown> : Input : Record<string, unknown>;
|
|
51
|
+
/** What an action answers, from its type — `unknown` for one whose type does not say. */
|
|
52
|
+
export type CallOutputOf<Action> = Action extends {
|
|
53
|
+
readonly [CALL_TYPES]?: {
|
|
54
|
+
output: infer Output;
|
|
55
|
+
};
|
|
56
|
+
} ? Output : unknown;
|
|
20
57
|
/**
|
|
21
58
|
* Who may start a run through ONE way in. Resolved against the auth kernel — never re-implemented here.
|
|
22
59
|
*
|
|
@@ -709,3 +746,4 @@ export type ActionJobQueue = {
|
|
|
709
746
|
olderThan?: string;
|
|
710
747
|
}) => Promise<number>;
|
|
711
748
|
};
|
|
749
|
+
export {};
|
|
@@ -22,6 +22,13 @@ export type ChannelDeclaration = {
|
|
|
22
22
|
* a locked board.
|
|
23
23
|
*/
|
|
24
24
|
grant?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Whether the server keeps the latest message of each type on a topic, and hands them to every page that joins: state
|
|
27
|
+
* all the screens share — a dashboard's lists, a board's settings — said once by the server (`ctx.publish`, a flow's
|
|
28
|
+
* `realtime.publish`) and there for a page that opens later, as `<channel>.retained.<type>`. Kept until the next of
|
|
29
|
+
* its type; `null` forgets it. Only on a channel the server alone publishes on (`publish: 'server'`).
|
|
30
|
+
*/
|
|
31
|
+
retain?: boolean;
|
|
25
32
|
/** The largest `data` a page may send, as JSON bytes. 4 KB when absent. */
|
|
26
33
|
maxMessageBytes?: number;
|
|
27
34
|
/** How many messages one connection may send a second. 30 when absent. */
|
|
@@ -55,6 +62,11 @@ export type RealtimeMessage = RealtimeSender & {
|
|
|
55
62
|
* knows it for its own by `from` — its channel's `me`. Without it, a page never hears what it sent.
|
|
56
63
|
*/
|
|
57
64
|
echo?: true;
|
|
65
|
+
/**
|
|
66
|
+
* Kept by the server: on a `retain: true` channel, the latest message of its type — sent as it is said, and again to
|
|
67
|
+
* every page that joins. The newest of a type is the one that holds; `null` data forgets it.
|
|
68
|
+
*/
|
|
69
|
+
retained?: true;
|
|
58
70
|
};
|
|
59
71
|
/** What a page asks of a publish beyond the message itself. */
|
|
60
72
|
export type RealtimePublishOptions = {
|
|
@@ -359,8 +359,15 @@ export type SSRAdapters = {
|
|
|
359
359
|
* dedicated MCP server renders nothing, reads schema and style through its own adapters, and had to hand this
|
|
360
360
|
* one over anyway for the type to be satisfied — an adapter it never called. */
|
|
361
361
|
getOfflineData?: (spaceId: number, environment: string, revision?: number) => Promise<OfflineDataRaw | undefined>;
|
|
362
|
-
/**
|
|
363
|
-
*
|
|
362
|
+
/**
|
|
363
|
+
* Which space, environment and revision a request resolves to. Optional here for the same reason as
|
|
364
|
+
* `getOfflineData`: MCP resolves its space from the request token (`getGrant`), never from the host.
|
|
365
|
+
*
|
|
366
|
+
* Asked on EVERY request, not only a page's: what the page fetches after it — `/_plitzi/space/<hash>.json`, `/_action`,
|
|
367
|
+
* `/fn/…`, `/_realtime` — is resolved again, and carries nothing of the page's address but its host (and the
|
|
368
|
+
* visitor's credentials). So a space is chosen by the host — a domain, a sub-domain (`wildcardSubdomain`) — or by a
|
|
369
|
+
* credential (`authoringPreview`): one chosen by the page's path or query is lost on the requests that follow it.
|
|
370
|
+
*/
|
|
364
371
|
getSpaceDeployment?: (req: SSRRequest) => Promise<SSRSpaceDeployment>;
|
|
365
372
|
/** Resolve the grant the MCP request operates under, from the verified `Authorization` bearer. The consumer
|
|
366
373
|
* owns the JWT secret and the authorization model, so it decides here; the MCP service stays stateless.
|
|
@@ -1033,6 +1040,19 @@ export type SSRServerConfig = {
|
|
|
1033
1040
|
};
|
|
1034
1041
|
/** Realtime channels the spaces declare — see {@link SSRRealtimeConfig}. On, in memory, when absent. */
|
|
1035
1042
|
realtime?: SSRRealtimeConfig;
|
|
1043
|
+
/**
|
|
1044
|
+
* The writes a page on another site may cause here. None, by default: a browser's POST, PUT, PATCH or DELETE that it
|
|
1045
|
+
* says another site caused (`Sec-Fetch-Site: cross-site`, or a foreign `Origin`) is refused 403 `reason: 'foreign'` —
|
|
1046
|
+
* a session cookie or none, because a server holding credentials of its own, or a tool nobody signs in to, acts for
|
|
1047
|
+
* whoever reaches it. A request with `Authorization`, and one that is not a browser's (a webhook, a script), are never
|
|
1048
|
+
* asked. With `auth`, the deployment's `identity.platformOrigins` count as its own too.
|
|
1049
|
+
*/
|
|
1050
|
+
crossSiteWrites?: {
|
|
1051
|
+
/** Origins whose pages may write here, exactly as a browser sends them — `https://app.example.com`. */
|
|
1052
|
+
origins?: string[];
|
|
1053
|
+
/** Paths any site may post to: a form other sites embed by design. */
|
|
1054
|
+
paths?: (path: string) => boolean;
|
|
1055
|
+
};
|
|
1036
1056
|
/** Connector manifest and credential lookups — see {@link ConnectorLookupsConfig}. They serve the RSC read path
|
|
1037
1057
|
* and the `/_action` write endpoint alike; without them neither can reach a connector. */
|
|
1038
1058
|
connectors?: ConnectorLookupsConfig;
|
|
@@ -152,12 +152,18 @@ export type RenderSettings = {
|
|
|
152
152
|
/**
|
|
153
153
|
* Whether the page may write the document's head — its SEO title and description. On, as a page's own document is.
|
|
154
154
|
*
|
|
155
|
-
* Off where the page is drawn in a
|
|
156
|
-
* manager writes the head of the document its code runs in, which there is the editor's — and the builder is itself
|
|
155
|
+
* Off where the page is drawn in a host whose document is not the page's: the builder's canvas, a space drawn inside
|
|
156
|
+
* another one. A head manager writes the head of the document its code runs in, which there is the editor's — and the builder is itself
|
|
157
157
|
* mounted in a page that manages that head, so a second manager under it rewrote the host's tags and took the
|
|
158
158
|
* builder's own stylesheet away the moment a preview showed a page with SEO.
|
|
159
159
|
*/
|
|
160
160
|
ownsHead?: boolean;
|
|
161
|
+
/**
|
|
162
|
+
* Whether this space is drawn inside another one — the `plitziSdk` element, a plugin rendering a space. The
|
|
163
|
+
* document is then the outer space's: this one wears its theme on its own root, keeps its stylesheet to that root,
|
|
164
|
+
* and starts in the outer space's theme when its own is left to the machine.
|
|
165
|
+
*/
|
|
166
|
+
enclosed?: boolean;
|
|
161
167
|
};
|
|
162
168
|
/** Absent `endpoint` is the whole feature switch: a render with no server tier leaves every `serverAction` step
|
|
163
169
|
* inert instead of letting each click discover a 404. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plitzi/sdk-shared",
|
|
3
|
-
"version": "0.38.
|
|
3
|
+
"version": "0.38.15",
|
|
4
4
|
"license": "AGPL-3.0",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -322,10 +322,18 @@
|
|
|
322
322
|
"types": "./dist/helpers/canonicalJson.d.ts",
|
|
323
323
|
"import": "./dist/helpers/canonicalJson.mjs"
|
|
324
324
|
},
|
|
325
|
+
"./helpers/clipboard": {
|
|
326
|
+
"types": "./dist/helpers/clipboard.d.ts",
|
|
327
|
+
"import": "./dist/helpers/clipboard.mjs"
|
|
328
|
+
},
|
|
325
329
|
"./helpers/cookies": {
|
|
326
330
|
"types": "./dist/helpers/cookies.d.ts",
|
|
327
331
|
"import": "./dist/helpers/cookies.mjs"
|
|
328
332
|
},
|
|
333
|
+
"./helpers/enclosingSpace": {
|
|
334
|
+
"types": "./dist/helpers/enclosingSpace.d.ts",
|
|
335
|
+
"import": "./dist/helpers/enclosingSpace.mjs"
|
|
336
|
+
},
|
|
329
337
|
"./helpers/eventTarget": {
|
|
330
338
|
"types": "./dist/helpers/eventTarget.d.ts",
|
|
331
339
|
"import": "./dist/helpers/eventTarget.mjs"
|
|
@@ -386,6 +394,10 @@
|
|
|
386
394
|
"types": "./dist/helpers/sharedContext.d.ts",
|
|
387
395
|
"import": "./dist/helpers/sharedContext.mjs"
|
|
388
396
|
},
|
|
397
|
+
"./helpers/spaceRoot": {
|
|
398
|
+
"types": "./dist/helpers/spaceRoot.d.ts",
|
|
399
|
+
"import": "./dist/helpers/spaceRoot.mjs"
|
|
400
|
+
},
|
|
389
401
|
"./helpers/stripTypename": {
|
|
390
402
|
"types": "./dist/helpers/stripTypename.d.ts",
|
|
391
403
|
"import": "./dist/helpers/stripTypename.mjs"
|
|
@@ -1115,6 +1127,10 @@
|
|
|
1115
1127
|
"types": "./dist/project/layout.d.ts",
|
|
1116
1128
|
"import": "./dist/project/layout.mjs"
|
|
1117
1129
|
},
|
|
1130
|
+
"./project/network": {
|
|
1131
|
+
"types": "./dist/project/network.d.ts",
|
|
1132
|
+
"import": "./dist/project/network.mjs"
|
|
1133
|
+
},
|
|
1118
1134
|
"./project/paths": {
|
|
1119
1135
|
"types": "./dist/project/paths.d.ts",
|
|
1120
1136
|
"import": "./dist/project/paths.mjs"
|
|
@@ -1618,7 +1634,6 @@
|
|
|
1618
1634
|
"react": "^19.3.0",
|
|
1619
1635
|
"react-dom": "^19.3.0",
|
|
1620
1636
|
"tailwindcss": "^4.3.3",
|
|
1621
|
-
"terser": "^5.51.2",
|
|
1622
1637
|
"typescript": "^6.0.3",
|
|
1623
1638
|
"typescript-eslint": "^8.71.0",
|
|
1624
1639
|
"vite": "^8.3.2",
|
package/setupTests.ts
CHANGED
|
@@ -9,13 +9,14 @@ import createFetchMock from 'vitest-fetch-mock';
|
|
|
9
9
|
const fetchMocker = createFetchMock(vi);
|
|
10
10
|
fetchMocker.enableMocks();
|
|
11
11
|
|
|
12
|
+
// A class, as the browser's is: what calls it calls it with `new`, which an arrow function refuses.
|
|
12
13
|
vi.stubGlobal(
|
|
13
14
|
'ResizeObserver',
|
|
14
|
-
|
|
15
|
-
observe
|
|
16
|
-
unobserve
|
|
17
|
-
disconnect
|
|
18
|
-
}
|
|
15
|
+
class {
|
|
16
|
+
observe = vi.fn();
|
|
17
|
+
unobserve = vi.fn();
|
|
18
|
+
disconnect = vi.fn();
|
|
19
|
+
}
|
|
19
20
|
);
|
|
20
21
|
|
|
21
22
|
// Only where there is a window: a file that opts into `@vitest-environment node` (one running a bundler) has none.
|