@plitzi/sdk-shared 0.38.10 → 0.38.12

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.
Files changed (39) hide show
  1. package/CHANGELOG.md +279 -0
  2. package/dist/actions/validateDocument.mjs +2 -1
  3. package/dist/authoring/declare.d.ts +152 -2
  4. package/dist/authoring/declare.mjs +95 -2
  5. package/dist/authoring/index.mjs +5 -5
  6. package/dist/dataSource/getBindingsDetails.mjs +20 -20
  7. package/dist/dataSource/hooks/useRegisterSource.mjs +31 -18
  8. package/dist/helpers/generateFacade.mjs +16 -12
  9. package/dist/helpers/index.mjs +2 -2
  10. package/dist/helpers/utils.d.ts +1 -1
  11. package/dist/helpers/utils.mjs +1 -1
  12. package/dist/hooks/index.d.ts +3 -3
  13. package/dist/hooks/index.mjs +2 -2
  14. package/dist/hooks/usePlitzi.d.ts +32 -0
  15. package/dist/hooks/{usePlitziServiceContext.mjs → usePlitzi.mjs} +3 -3
  16. package/dist/index.mjs +3 -3
  17. package/dist/plugins/PluginsContext.d.ts +3 -0
  18. package/dist/plugins/PluginsContext.mjs +4 -0
  19. package/dist/project/paths.d.ts +1 -1
  20. package/dist/realtime/client.d.ts +6 -3
  21. package/dist/realtime/client.mjs +19 -17
  22. package/dist/realtime/index.d.ts +1 -1
  23. package/dist/realtime/index.mjs +4 -4
  24. package/dist/realtime/presence.mjs +1 -1
  25. package/dist/realtime/topics.d.ts +6 -0
  26. package/dist/realtime/topics.mjs +2 -2
  27. package/dist/store/index.d.ts +33 -33
  28. package/dist/style/styleTarget.mjs +28 -27
  29. package/dist/style/useElementSize.d.ts +16 -0
  30. package/dist/style/useElementSize.mjs +20 -0
  31. package/dist/types/ActionTypes.d.ts +19 -3
  32. package/dist/types/DataSourceTypes.d.ts +7 -2
  33. package/dist/types/EventBridgeTypes.d.ts +2 -1
  34. package/dist/types/InteractionTypes.d.ts +42 -4
  35. package/dist/types/RealtimeTypes.d.ts +14 -1
  36. package/dist/types/ServerTypes.d.ts +6 -1
  37. package/dist/websockets/RTCodec.d.ts +6 -1
  38. package/package.json +13 -5
  39. package/dist/hooks/usePlitziServiceContext.d.ts +0 -38
@@ -1,35 +1,36 @@
1
- import { canonicalCondition as e } from "./styleConditions.mjs";
2
- import { isStylePseudo as t } from "./stylePseudos.mjs";
3
- import { isParentAncestor as n } from "./styleStates.mjs";
1
+ import { isRecord as e } from "../helpers/isRecord.mjs";
2
+ import { canonicalCondition as t } from "./styleConditions.mjs";
3
+ import { isStylePseudo as n } from "./stylePseudos.mjs";
4
+ import { isParentAncestor as r } from "./styleStates.mjs";
4
5
  //#region src/style/styleTarget.ts
5
- var r = (e) => {
6
+ var i = (e) => {
6
7
  let t = [];
7
8
  return e.styleAncestor ? t.push("ancestors", e.styleAncestor) : e.styleCondition && t.push("conditions", e.styleCondition), e.styleVariant && t.push("variants", e.styleVariant), e.stylePseudo && t.push("pseudos", e.stylePseudo), t.push(...e.styleState ? ["states", e.styleState] : ["default"]), t;
8
- }, i = (r) => {
9
- if (r.styleAncestor && r.styleCondition) return "an ancestor condition cannot also be under a condition";
10
- if (r.styleAncestor && r.stylePseudo) return "a pseudo-element has no ancestor conditions of its own";
11
- if (r.styleCondition && r.styleVariant) return "a condition holds the class’s own rules, not its variants’";
12
- if (r.styleCondition && e(r.styleCondition) !== r.styleCondition) return `"${r.styleCondition}" is not a condition`;
13
- if (r.stylePseudo && !t(r.stylePseudo)) return `"${String(r.stylePseudo)}" is not a pseudo-element`;
14
- if (r.styleAncestor && n(r.styleAncestor) && r.styleVariant) return "the element around it is named by its state, never by a variant";
15
- }, a = (e) => typeof e == "object" && !!e && !Array.isArray(e), o = (e, t) => {
16
- let n = e;
17
- for (let e of t) {
18
- if (!a(n) || !Object.hasOwn(n, e)) return;
19
- n = n[e];
9
+ }, a = (e) => {
10
+ if (e.styleAncestor && e.styleCondition) return "an ancestor condition cannot also be under a condition";
11
+ if (e.styleAncestor && e.stylePseudo) return "a pseudo-element has no ancestor conditions of its own";
12
+ if (e.styleCondition && e.styleVariant) return "a condition holds the class’s own rules, not its variants’";
13
+ if (e.styleCondition && t(e.styleCondition) !== e.styleCondition) return `"${e.styleCondition}" is not a condition`;
14
+ if (e.stylePseudo && !n(e.stylePseudo)) return `"${String(e.stylePseudo)}" is not a pseudo-element`;
15
+ if (e.styleAncestor && r(e.styleAncestor) && e.styleVariant) return "the element around it is named by its state, never by a variant";
16
+ }, o = (t, n) => {
17
+ let r = t;
18
+ for (let t of n) {
19
+ if (!e(r) || !Object.hasOwn(r, t)) return;
20
+ r = r[t];
20
21
  }
21
- return n;
22
- }, s = (e, t, n) => {
23
- let r = e;
24
- t.slice(0, -1).forEach((e) => {
25
- let t = r[e], n = a(t) ? t : {};
26
- r[e] = n, r = n;
22
+ return r;
23
+ }, s = (t, n, r) => {
24
+ let i = t;
25
+ n.slice(0, -1).forEach((t) => {
26
+ let n = i[t], r = e(n) ? n : {};
27
+ i[t] = r, i = r;
27
28
  });
28
- let i = t.at(-1);
29
- i !== void 0 && (r[i] = n);
30
- }, c = (e) => a(e) && Object.values(e).every((e) => typeof e == "string" || typeof e == "number"), l = (e, t) => {
31
- let n = o(e, r(t));
29
+ let a = n.at(-1);
30
+ a !== void 0 && (i[a] = r);
31
+ }, c = (t) => e(t) && Object.values(t).every((e) => typeof e == "string" || typeof e == "number"), l = (e, t) => {
32
+ let n = o(e, i(t));
32
33
  return c(n) ? n : void 0;
33
34
  };
34
35
  //#endregion
35
- export { c as isStyleRules, s as setAtKeys, r as styleTargetKeys, i as styleTargetProblem, l as styleTargetRules, o as valueAtKeys };
36
+ export { c as isStyleRules, s as setAtKeys, i as styleTargetKeys, a as styleTargetProblem, l as styleTargetRules, o as valueAtKeys };
@@ -0,0 +1,16 @@
1
+ import { RefObject } from 'react';
2
+ export type ElementSize = {
3
+ width: number;
4
+ height: number;
5
+ };
6
+ /**
7
+ * The size an element is drawn at — a plugin's own box, which a sidebar, a panel or a split screen makes narrower than
8
+ * the window — kept up to date as it changes. What `useDisplayMode` cannot say: a tablet held upright is `mobile` by
9
+ * the window's breakpoints, and a week of seven columns still fits the 744 px the plugin has.
10
+ *
11
+ * `undefined` until it is measured: on the server, and in the browser's first render, so the page the server sent and
12
+ * the one that hydrates it are the same. Decide from a fallback until then — the breakpoint's guess:
13
+ * `const days = (size?.width ?? (useDisplayMode() === 'mobile' ? 390 : 1024)) >= 640 ? 7 : 3`.
14
+ */
15
+ declare const useElementSize: (ref: RefObject<HTMLElement | null>) => ElementSize | undefined;
16
+ export default useElementSize;
@@ -0,0 +1,20 @@
1
+ import { useEffect as e, useState as t } from "react";
2
+ //#region src/style/useElementSize.ts
3
+ var n = (n) => {
4
+ let [r, i] = t(void 0);
5
+ return e(() => {
6
+ let e = n.current;
7
+ if (!e || typeof ResizeObserver > "u") return;
8
+ let t = (e, t) => i((n) => n?.width === e && n.height === t ? n : {
9
+ width: e,
10
+ height: t
11
+ }), r = e.getBoundingClientRect();
12
+ t(r.width, r.height);
13
+ let a = new ResizeObserver((e) => {
14
+ e.slice(-1).forEach((e) => t(e.contentRect.width, e.contentRect.height));
15
+ });
16
+ return a.observe(e), () => a.disconnect();
17
+ }, [n]), r;
18
+ };
19
+ //#endregion
20
+ export { n as default };
@@ -70,10 +70,11 @@ export type ActionWebhookVerification = {
70
70
  * The ways into an action, as the `action` of a trigger STEP rather than a list beside the flow.
71
71
  *
72
72
  * `call` — a client flow through the action endpoint. `webhook` — an inbound request, public by construction.
73
- * `schedule` — a cron tick. `render` — a `runtime: 'server'` element naming this action. `custom` — a trigger the
74
- * deployment mounted itself.
73
+ * `schedule` — a cron tick. `later` — a run another one set to start N seconds from then (`ctx.later`, `flow.later`):
74
+ * a turn that runs out, a bot's move, a hold that lapses. `render` — a `runtime: 'server'` element naming this action.
75
+ * `custom` — a trigger the deployment mounted itself.
75
76
  */
76
- export type ActionTriggerType = 'call' | 'webhook' | 'schedule' | 'render' | 'custom';
77
+ export type ActionTriggerType = 'call' | 'webhook' | 'schedule' | 'later' | 'render' | 'custom';
77
78
  /**
78
79
  * What a trigger step carries, in its `params`.
79
80
  *
@@ -551,6 +552,11 @@ export type ActionJobInput = {
551
552
  maxAttempts: number;
552
553
  /** Fires that went by unclaimed before this one. Shown to an operator; never acted on. */
553
554
  missed?: number;
555
+ /**
556
+ * What a run set to run later (`trigger: 'later'`) was named by: setting it again under the same name replaces the
557
+ * one still waiting, and cancelling it by name drops it.
558
+ */
559
+ key?: string;
554
560
  };
555
561
  /** One unit of work the queue is holding, as an operator sees it. */
556
562
  export type ActionJob = ActionJobInput & {
@@ -692,4 +698,14 @@ export type ActionJobQueue = {
692
698
  requeue: (spaceIds: number[], jobId: string) => Promise<boolean>;
693
699
  /** An operator stopping a job: dropped if it is waiting, aborted at its next step if it is running. */
694
700
  cancel: (spaceIds: number[], jobId: string) => Promise<boolean>;
701
+ /**
702
+ * Drops the space's jobs waiting under `key` (`cancelled`), and answers how many. With `olderThan`, only the ones
703
+ * enqueued before that job — created earlier, or at the same instant with a smaller id — so of two set at once the
704
+ * newer is the one left, on every replica. A running one is left: it is usually the run that set the next.
705
+ */
706
+ cancelPending: (params: {
707
+ spaceId: number;
708
+ key: string;
709
+ olderThan?: string;
710
+ }) => Promise<number>;
695
711
  };
@@ -20,13 +20,18 @@ export type DataSourceUtilityParams<TParams = string | boolean | number> = Recor
20
20
  }>;
21
21
  export type DataSourceUtilityParamsValue<T = string | boolean | number> = Record<keyof DataSourceUtility<T>['params'], T>;
22
22
  export type DataSourceUtilityParamType = 'text' | 'select' | 'textarea' | 'checkbox' | 'codemirror-text';
23
- export type DataSourceUtility<TSource = any, TSourceReturn = string | boolean | number, TParams = string | boolean | number> = {
23
+ /**
24
+ * A step a binding's value goes through on its way to an attribute. It receives whatever the binding resolved to — or
25
+ * the step before it answered — and a value it has no use for goes on untouched, so both ends are `unknown` unless one
26
+ * says more.
27
+ */
28
+ export type DataSourceUtility<TSource = unknown, TSourceReturn = unknown, TParams = string | boolean | number> = {
24
29
  action: string;
25
30
  title: string;
26
31
  type: 'utility' | 'unknown';
27
32
  params: DataSourceUtilityParams<TParams>;
28
33
  preview: Record<string, string>;
29
- callback: (source: TSource, params: DataSourceUtilityParamsValue<TParams>, element: Partial<Element>, dataSources?: Record<string, any>) => TSourceReturn;
34
+ callback: (source: TSource, params: DataSourceUtilityParamsValue<TParams>, element: Partial<Element>, dataSources?: Record<string, unknown>) => TSourceReturn;
30
35
  };
31
36
  export type SourceField = {
32
37
  path: string;
@@ -1,4 +1,5 @@
1
- export type EventBridgeContextValue<T = any> = {
1
+ /** What sdk-event-bridge's context holds: its bridge, whose class is that package's own. */
2
+ export type EventBridgeContextValue<T> = {
2
3
  eventBridge: T;
3
4
  };
4
5
  export type EventBridgeModule = 'main' | 'builder' | 'snippet' | 'interaction' | 'element';
@@ -30,17 +30,28 @@ export type InteractionCallbackParam<T extends Record<string, unknown> = Record<
30
30
  * space's credentials of that kind to pick from, rather than a text box somebody has to type an identifier into.
31
31
  */
32
32
  credentialProvider?: SpaceCredentialProvider;
33
- } & ({
33
+ /**
34
+ * A space's task refuses to run without it — empty, or only spaces — saying so with the param's `label`, before its
35
+ * code runs: what a task otherwise checked by hand in its first lines.
36
+ */
37
+ required?: boolean;
38
+ } &
39
+ /** Handed to a task as text, whatever was written or bound — a number as its digits — at most `maxLength` long. */
40
+ ({
34
41
  type: 'text';
35
42
  defaultValue?: string | number;
43
+ maxLength?: number;
36
44
  }
37
- /** Written as text — a number or a template — and handed to the callback as a number. */
45
+ /** Written as text — a number or a template — and handed to the callback as a number, within `min` and `max`. */
38
46
  | {
39
47
  type: 'number';
40
48
  defaultValue?: number;
49
+ min?: number;
50
+ max?: number;
41
51
  } | {
42
52
  type: 'textarea';
43
53
  defaultValue?: string | number;
54
+ maxLength?: number;
44
55
  } | {
45
56
  type: 'codemirror-text';
46
57
  defaultValue?: string;
@@ -133,8 +144,35 @@ export type Subscriptor<T extends Record<string, unknown> = Record<string, unkno
133
144
  id: string;
134
145
  triggers: Record<string, Trigger<T>>;
135
146
  };
136
- export type InteractionsContextValue<TManager = any> = {
137
- interactionsManager: TManager;
147
+ /**
148
+ * The interactions manager as everything outside sdk-interactions reaches it — through its context. Declared here, where
149
+ * every package can name it, and implemented by sdk-interactions' `InteractionsManager`, which the compiler holds to it.
150
+ *
151
+ * Methods, not function-valued fields: a manager's children are managers of its own class, which only this way can
152
+ * stand for the interface.
153
+ */
154
+ export interface InteractionsManagerApi {
155
+ /** The page's id and its route and query params: what a flow reads as `navigation`. */
156
+ interactionsData: Record<string, string | number | boolean>;
157
+ /**
158
+ * Fires `eventName` on the element `subscriptorId`: the flows it starts, with `params` for them to read — what each
159
+ * answered, or nothing when there is no element to fire on.
160
+ */
161
+ interactionTrigger(subscriptorId: string | undefined, eventName: string, params?: Record<string, unknown>): Promise<unknown[]> | undefined;
162
+ subscribe<TParams extends Record<string, unknown> = Record<string, unknown>>(id: string, interactions?: Record<string, ElementInteraction>, triggers?: Record<string, InteractionCallback<TParams>>, callbacks?: Record<string, InteractionCallback<TParams>>, getAdditionalParams?: Subscriptor<TParams>['getAdditionalParams']): boolean;
163
+ update<TParams extends Record<string, unknown> = Record<string, unknown>>(id: string, interactions?: Record<string, ElementInteraction>, triggers?: Record<string, InteractionCallback<TParams>>, callbacks?: Record<string, InteractionCallback<TParams>>, getAdditionalParams?: Subscriptor<TParams>['getAdditionalParams']): boolean;
164
+ unsubscribe(id: string): boolean;
165
+ getSubscriptor(subscriptorId: string): Subscriptor | undefined;
166
+ /** Every callback an element answers, by element and action — the step picker's list. */
167
+ getCallbacksAvailables(): Record<string, Record<string, InteractionCallback>>;
168
+ /** A manager for a replica — a list's row — whose route and query params are its own. */
169
+ createChildManager(routeParams?: Record<string, string>, queryParams?: Record<string, string>): InteractionsManagerApi;
170
+ removeChildManager(childManager: InteractionsManagerApi): void;
171
+ /** Called with the time of each change to what is subscribed; answers how to stop. */
172
+ onUpdate(listener: (timestamp: number) => void): () => void;
173
+ }
174
+ export type InteractionsContextValue = {
175
+ interactionsManager: InteractionsManagerApi;
138
176
  useInteractions: <T extends Record<string, unknown> = Record<string, unknown>>(props: {
139
177
  id?: string;
140
178
  interactions?: Record<string, ElementInteraction>;
@@ -50,9 +50,22 @@ export type RealtimeMessage = RealtimeSender & {
50
50
  data: unknown;
51
51
  /** Server time, in milliseconds. */
52
52
  at: number;
53
+ /**
54
+ * The sender asked to hear it too ({@link RealtimePublishOptions}): it reaches the page that sent it as well, which
55
+ * knows it for its own by `from` — its channel's `me`. Without it, a page never hears what it sent.
56
+ */
57
+ echo?: true;
58
+ };
59
+ /** What a page asks of a publish beyond the message itself. */
60
+ export type RealtimePublishOptions = {
61
+ /**
62
+ * Hear it too, once the server took it — a reaction, a chat line: what the sender shows the moment it sends. Off by
63
+ * default, so what moves at the speed of a cursor is not drawn twice.
64
+ */
65
+ echo?: boolean;
53
66
  };
54
67
  /** What a page sends to publish: the secret its connection was given, and the message. */
55
- export type RealtimePublishRequest = {
68
+ export type RealtimePublishRequest = RealtimePublishOptions & {
56
69
  token: string;
57
70
  topic: string;
58
71
  type: string;
@@ -1185,7 +1185,12 @@ export type SSRContext = {
1185
1185
  rscParams?: Record<string, string>;
1186
1186
  };
1187
1187
  export type SSRServer = {
1188
- listen: (port: number, host?: string) => void;
1188
+ /**
1189
+ * Binds the port. Resolves once it takes connections — in a fleet, once the first worker does — so what says "ready"
1190
+ * (a log line, a file a tool reads, a test's first request) says it after, never before. A port it could not take
1191
+ * ends the process, or goes to `onListenError`: the promise is then never resolved.
1192
+ */
1193
+ listen: (port: number, host?: string) => Promise<void>;
1189
1194
  close: () => Promise<void>;
1190
1195
  readonly cache: CacheManager | null;
1191
1196
  readonly plugins: PluginRegistry;
@@ -112,7 +112,12 @@ export type RTMessageManagedServer = {
112
112
  type: RTEvent.COLLABORATOR_DISCONNECTED;
113
113
  payload: SubscriptionCollaborator;
114
114
  };
115
- export type RTCallback = (...args: any[]) => void;
115
+ /** What a message of one event carries, as the server sends it. */
116
+ export type RTPayload<E extends RTEvent> = Extract<RTMessageManagedServer, {
117
+ type: E;
118
+ }>['payload'];
119
+ /** A listener for one realtime event, handed what that event carries. */
120
+ export type RTCallback<E extends RTEvent = RTEvent> = (payload: RTPayload<E>) => void;
116
121
  export type RTMessage<T = unknown> = {
117
122
  type: RTEvent;
118
123
  payload: T;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plitzi/sdk-shared",
3
- "version": "0.38.10",
3
+ "version": "0.38.12",
4
4
  "license": "AGPL-3.0",
5
5
  "files": [
6
6
  "dist",
@@ -571,9 +571,9 @@
571
571
  "types": "./dist/hooks/useNetwork.d.ts",
572
572
  "import": "./dist/hooks/useNetwork.mjs"
573
573
  },
574
- "./hooks/usePlitziServiceContext": {
575
- "types": "./dist/hooks/usePlitziServiceContext.d.ts",
576
- "import": "./dist/hooks/usePlitziServiceContext.mjs"
574
+ "./hooks/usePlitzi": {
575
+ "types": "./dist/hooks/usePlitzi.d.ts",
576
+ "import": "./dist/hooks/usePlitzi.mjs"
577
577
  },
578
578
  "./hooks/useStableValue": {
579
579
  "types": "./dist/hooks/useStableValue.d.ts",
@@ -1099,6 +1099,10 @@
1099
1099
  "types": "./dist/network/spaceEvents.d.ts",
1100
1100
  "import": "./dist/network/spaceEvents.mjs"
1101
1101
  },
1102
+ "./plugins/PluginsContext": {
1103
+ "types": "./dist/plugins/PluginsContext.d.ts",
1104
+ "import": "./dist/plugins/PluginsContext.mjs"
1105
+ },
1102
1106
  "./plugins/bundle": {
1103
1107
  "types": "./dist/plugins/bundle.d.ts",
1104
1108
  "import": "./dist/plugins/bundle.mjs"
@@ -1431,6 +1435,10 @@
1431
1435
  "types": "./dist/style/useDisplayMode.d.ts",
1432
1436
  "import": "./dist/style/useDisplayMode.mjs"
1433
1437
  },
1438
+ "./style/useElementSize": {
1439
+ "types": "./dist/style/useElementSize.d.ts",
1440
+ "import": "./dist/style/useElementSize.mjs"
1441
+ },
1434
1442
  "./theme": {
1435
1443
  "types": "./dist/theme/index.d.ts",
1436
1444
  "import": "./dist/theme/index.mjs"
@@ -1576,7 +1584,7 @@
1576
1584
  },
1577
1585
  "dependencies": {
1578
1586
  "@plitzi/nexus": "^1.4.0",
1579
- "@plitzi/plitzi-ui": "^1.6.32",
1587
+ "@plitzi/plitzi-ui": "^1.6.33",
1580
1588
  "date-fns": "^4.4.0",
1581
1589
  "immer": "^11.1.21",
1582
1590
  "zod": "^4.6.5"
@@ -1,38 +0,0 @@
1
- import { BuilderContextValue } from '../builder';
2
- import { NetworkContextValue } from '../network';
3
- import { ComponentContextValue, EventBridgeContextValue, InteractionsContextValue, PluginsContextValue, ColorScheme } from '../types';
4
- import { Context, ReactNode, RefObject } from 'react';
5
- export type PlitziServiceContextValue<TEventBridge = any, TInteractions = any> = {
6
- settings: {
7
- isHydrating?: boolean;
8
- previewMode?: boolean;
9
- environment?: string;
10
- [key: string]: unknown;
11
- /** Already resolved: an element paints in one of two schemes and has no use for the word `system`. */
12
- theme: ColorScheme;
13
- };
14
- root: {
15
- baseElementId: string;
16
- };
17
- utils: {
18
- getWindow: () => Window | null;
19
- rootRef: RefObject<HTMLElement | null>;
20
- };
21
- customContexts: Record<string, Context<any>>;
22
- contexts: {
23
- ComponentContext: Context<ComponentContextValue>;
24
- EventBridgeContext: Context<EventBridgeContextValue<TEventBridge>>;
25
- PluginsContext: Context<PluginsContextValue>;
26
- InteractionsContext: Context<InteractionsContextValue<TInteractions>>;
27
- NetworkContext: Context<NetworkContextValue>;
28
- BuilderContext?: Context<BuilderContextValue>;
29
- };
30
- };
31
- declare const PlitziServiceContext: Context<PlitziServiceContextValue<any, any>>;
32
- declare const usePlitziServiceContext: <TEventBridge = any, TInteractions = any>() => PlitziServiceContextValue<TEventBridge, TInteractions>;
33
- declare const PlitziServiceProvider: (props: {
34
- children?: ReactNode;
35
- value: PlitziServiceContextValue;
36
- }) => import('react').JSX.Element;
37
- export { PlitziServiceProvider, PlitziServiceContext };
38
- export default usePlitziServiceContext;