@plitzi/sdk-shared 0.36.0 → 0.36.2
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 +12 -0
- package/dist/authoring/builder.d.ts +8 -1
- package/dist/authoring/builder.mjs +8 -5
- package/dist/dataSource/hooks/useRegisterSource.mjs +1 -1
- package/dist/hooks/index.d.ts +2 -1
- package/dist/hooks/index.mjs +2 -1
- package/dist/hooks/useStableValue.d.ts +12 -0
- package/dist/hooks/useStableValue.mjs +9 -0
- package/dist/index.mjs +32 -30
- package/dist/navigation/routes.mjs +1 -1
- package/dist/queries/queryCache.d.ts +39 -2
- package/dist/queries/queryCache.mjs +35 -12
- package/dist/queries/useQuery.d.ts +1 -1
- package/dist/queries/useQuery.mjs +1 -1
- package/dist/schema/index.d.ts +1 -0
- package/dist/schema/index.mjs +3 -2
- package/dist/schema/layoutChain.d.ts +17 -0
- package/dist/schema/layoutChain.mjs +25 -0
- package/dist/store/tracing/tracingCollector.d.ts +2 -0
- package/dist/store/tracing/tracingCollector.mjs +56 -36
- package/dist/types/ElementTypes.d.ts +6 -3
- package/dist/types/StoreTypes.d.ts +4 -0
- package/package.json +19 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { ParamSpec } from './paramSpec';
|
|
2
2
|
import { InteractionCallback, InteractionCallbackContext, InteractionCallbackParam, InteractionCallbackPreviews, InteractionCallbackType } from '../types';
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Converted once per declaration and shared.
|
|
5
|
+
*
|
|
6
|
+
* Declarations are module constants, and every element builds its own `setState` / `toggleState` from the same two
|
|
7
|
+
* on every mount — so converting here each time, a regex per param, was a measurable share of mounting a page.
|
|
8
|
+
* Callers spread what they change, which is why the shared object is read-only.
|
|
9
|
+
*/
|
|
10
|
+
export declare const toBuilderParams: (spec: ParamSpec) => Readonly<Record<string, InteractionCallbackParam>>;
|
|
4
11
|
/** What a declared action carries, whichever kind of action it is. */
|
|
5
12
|
export interface BuiltinActionSpec {
|
|
6
13
|
title: string;
|
|
@@ -18,14 +18,17 @@ var e = {
|
|
|
18
18
|
...r.when ? { when: r.when } : {},
|
|
19
19
|
...r.canBind === void 0 ? {} : { canBind: r.canBind },
|
|
20
20
|
...r.elementType === void 0 ? {} : { elementType: r.elementType }
|
|
21
|
-
}), r =
|
|
21
|
+
}), r = /* @__PURE__ */ new WeakMap(), i = (e) => {
|
|
22
|
+
let t = r.get(e);
|
|
23
|
+
return t || (t = Object.fromEntries(Object.entries(e).map(([e, t]) => [e, n(e, t)])), r.set(e, t)), t;
|
|
24
|
+
}, a = (e, t, n, r = {}) => ({
|
|
22
25
|
action: e,
|
|
23
26
|
title: t.title,
|
|
24
27
|
type: t.type ?? "globalCallback",
|
|
25
28
|
callback: n,
|
|
26
29
|
preview: t.preview ?? {},
|
|
27
|
-
params:
|
|
28
|
-
...
|
|
29
|
-
}),
|
|
30
|
+
params: i(t.params),
|
|
31
|
+
...r
|
|
32
|
+
}), o = (e, t, n = {}) => Object.fromEntries(Object.keys(e).map((r) => [r, a(r, e[r], t[r], n[r] ?? {})]));
|
|
30
33
|
//#endregion
|
|
31
|
-
export {
|
|
34
|
+
export { i as toBuilderParams, a as toInteractionCallback, o as toInteractionCallbacks };
|
|
@@ -15,7 +15,7 @@ var i = ({ id: i = "", source: a, name: o, fields: s = [] }) => {
|
|
|
15
15
|
}
|
|
16
16
|
}), () => l(`sources.${u}`, void 0, { unmount: !0 });
|
|
17
17
|
}, [u, a]), t(() => {
|
|
18
|
-
a && l(`sources.${u}.meta.fields`, s);
|
|
18
|
+
a && l(`sources.${u}.meta.fields`, s, { raw: !0 });
|
|
19
19
|
}, [
|
|
20
20
|
s,
|
|
21
21
|
a,
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { default as useFontHead } from './useFontHead';
|
|
2
2
|
import { default as useNetwork } from './useNetwork';
|
|
3
3
|
import { default as usePlitziServiceContext } from './usePlitziServiceContext';
|
|
4
|
+
import { default as useStableValue } from './useStableValue';
|
|
4
5
|
export * from './useNetwork';
|
|
5
6
|
export * from './usePlitziServiceContext';
|
|
6
|
-
export { useFontHead, useNetwork, usePlitziServiceContext };
|
|
7
|
+
export { useFontHead, useNetwork, usePlitziServiceContext, useStableValue };
|
package/dist/hooks/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import e from "./useFontHead.mjs";
|
|
2
2
|
import t from "./useNetwork.mjs";
|
|
3
3
|
import n, { PlitziServiceContext as r, PlitziServiceProvider as i } from "./usePlitziServiceContext.mjs";
|
|
4
|
-
|
|
4
|
+
import a from "./useStableValue.mjs";
|
|
5
|
+
export { r as PlitziServiceContext, i as PlitziServiceProvider, e as useFontHead, t as useNetwork, n as usePlitziServiceContext, a as useStableValue };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The previous value, as long as the new one has the same content.
|
|
3
|
+
*
|
|
4
|
+
* For values rebuilt on every render that are then published — written to a store, handed down as a prop, compared by
|
|
5
|
+
* reference by whoever reads them. A route's params come back as a new `{}` on every navigation; published as they
|
|
6
|
+
* come, every element subscribed to them rendered again for a value that had not changed.
|
|
7
|
+
*
|
|
8
|
+
* The ref is written during render, and only ever to a value equal in content to what the render was given, so a
|
|
9
|
+
* render React throws away leaves nothing observable behind.
|
|
10
|
+
*/
|
|
11
|
+
declare const useStableValue: <T>(value: T) => T;
|
|
12
|
+
export default useStableValue;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { useRef as e } from "react";
|
|
2
|
+
import t from "@plitzi/plitzi-ui/utils/deepEqual";
|
|
3
|
+
//#region src/hooks/useStableValue.ts
|
|
4
|
+
var n = (n) => {
|
|
5
|
+
let r = e(n);
|
|
6
|
+
return r.current !== n && !t(r.current, n) && (r.current = n), r.current;
|
|
7
|
+
};
|
|
8
|
+
//#endregion
|
|
9
|
+
export { n as default };
|
package/dist/index.mjs
CHANGED
|
@@ -32,33 +32,35 @@ import oe from "./elements/ComponentContext.mjs";
|
|
|
32
32
|
import se from "./hooks/useFontHead.mjs";
|
|
33
33
|
import ce from "./hooks/useNetwork.mjs";
|
|
34
34
|
import le, { PlitziServiceContext as ue, PlitziServiceProvider as de } from "./hooks/usePlitziServiceContext.mjs";
|
|
35
|
-
import
|
|
36
|
-
import
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
39
|
-
import {
|
|
40
|
-
import {
|
|
41
|
-
import Ne from "./
|
|
42
|
-
import
|
|
43
|
-
import {
|
|
44
|
-
import Re from "./
|
|
45
|
-
import ze from "./
|
|
46
|
-
import
|
|
47
|
-
import
|
|
48
|
-
import We from "./network/
|
|
49
|
-
import
|
|
50
|
-
import
|
|
51
|
-
import
|
|
52
|
-
import
|
|
53
|
-
import
|
|
54
|
-
import
|
|
55
|
-
import
|
|
56
|
-
import {
|
|
57
|
-
import _t from "./theme/
|
|
58
|
-
import
|
|
59
|
-
import bt from "./
|
|
60
|
-
import xt, {
|
|
61
|
-
import
|
|
62
|
-
import Tt from "./server/rsc/
|
|
63
|
-
import
|
|
64
|
-
|
|
35
|
+
import fe from "./hooks/useStableValue.mjs";
|
|
36
|
+
import { StyleVariableCategory as pe } from "./types/StyleTypes.mjs";
|
|
37
|
+
import me, { EMPTY_STYLE_SCHEMA as he, StyleBindingsAllowed as ge, baseDefaultValue as _e, inheritableAttributesBase as ve } from "./style/styleConstants.mjs";
|
|
38
|
+
import { fontLinkAssets as ye } from "./style/fontAssets.mjs";
|
|
39
|
+
import { SYSTEM_FONTS as be, availableFonts as xe, familiesInCss as Se, fontFamilyStack as Ce, fontUrlResolver as we, fontsToHead as Te, googleCss2Url as Ee, googleTextSubsetUrl as De, isSafeFontUrl as Oe, primaryFamily as ke } from "./style/fonts.mjs";
|
|
40
|
+
import { FontValidationError as Ae, parseSpaceFont as je } from "./style/fontValidation.mjs";
|
|
41
|
+
import { fallbackForFamily as Me, fontsFromCss as Ne } from "./style/fontsFromCss.mjs";
|
|
42
|
+
import Pe from "./schema/SchemaContext.mjs";
|
|
43
|
+
import { EMPTY_SCHEMA as Fe, VARIABLE_REGEX as Ie } from "./schema/schemaConstants.mjs";
|
|
44
|
+
import { findLayoutCycle as Le, resolveLayoutChain as Re } from "./schema/layoutChain.mjs";
|
|
45
|
+
import { collectServerElements as ze, hasServerElements as Be } from "./schema/serverElements.mjs";
|
|
46
|
+
import Ve from "./network/NetworkContext.mjs";
|
|
47
|
+
import He from "./network/NetworkInternalContext.mjs";
|
|
48
|
+
import { SpaceEvents as Ue, spaceEventSchemas as We, validateSpaceEvent as Ge } from "./network/spaceEvents.mjs";
|
|
49
|
+
import Ke from "./network/graphql/builder/Mutations/index.mjs";
|
|
50
|
+
import qe from "./network/graphql/builder/Queries/index.mjs";
|
|
51
|
+
import Je from "./network/graphql/builder/Subscriptions/index.mjs";
|
|
52
|
+
import Ye from "./network/graphql/sdk/Mutations/index.mjs";
|
|
53
|
+
import Xe from "./network/graphql/sdk/Queries/index.mjs";
|
|
54
|
+
import Ze from "./segments/SegmentsContext.mjs";
|
|
55
|
+
import Qe, { RTEvent as $e, RTEventCloseCode as et, getInstance as tt, isRTEvent as nt, setInstance as rt } from "./websockets/RTCodec.mjs";
|
|
56
|
+
import { THEME_CLASSES as it, THEME_COOKIE_NAME as at, applyThemeClass as ot, isTheme as st, readThemeCookie as ct, themeFromCookies as lt, writeThemeCookie as ut } from "./theme/themeCookie.mjs";
|
|
57
|
+
import dt, { createThemeState as ft, createThemeStore as pt, resolveScheme as mt, setAreaTheme as ht, setMachineScheme as gt, setThemeMode as _t, themeFor as vt } from "./theme/themeStore.mjs";
|
|
58
|
+
import { useThemeStore as yt } from "./theme/ThemeScope.mjs";
|
|
59
|
+
import bt from "./theme/ThemeProvider.mjs";
|
|
60
|
+
import xt, { SPACE_THEME_AREA as St } from "./theme/useTheme.mjs";
|
|
61
|
+
import Ct from "./server/actions/useActionsSync.mjs";
|
|
62
|
+
import wt, { currentRscLocation as Tt, rscDataPath as Et } from "./server/rsc/refreshRsc.mjs";
|
|
63
|
+
import Dt from "./server/rsc/useRscRefresh.mjs";
|
|
64
|
+
import Ot from "./server/rsc/useRscSync.mjs";
|
|
65
|
+
import { runtimeStatePersist as kt } from "./state/runtimeStatePersist.mjs";
|
|
66
|
+
export { d as BODYLESS_METHODS, l as BuilderContext, Ke as BuilderMutations, qe as BuilderQueries, f as CONNECTOR_HTTP_METHODS, oe as ComponentContext, p as DEFAULT_READ_ENDPOINT, ee as DevToolsContext, m as EMPTY_RESPONSE_METHODS, Fe as EMPTY_SCHEMA, he as EMPTY_STYLE_SCHEMA, Ae as FontValidationError, Ve as NetworkContext, He as NetworkInternalContext, I as ParamsFromURL, re as PlitziConsole, ue as PlitziServiceContext, de as PlitziServiceProvider, h as READ_ENDPOINT_NAMES, Qe as RTCodec, $e as RTEvent, et as RTEventCloseCode, St as SPACE_THEME_AREA, be as SYSTEM_FONTS, Pe as SchemaContext, Ye as SdkMutations, Xe as SdkQueries, Ze as SegmentsContext, Je as SpaceEventSubscription, Ue as SpaceEvents, ge as StyleBindingsAllowed, pe as StyleVariableCategory, it as THEME_CLASSES, at as THEME_COOKIE_NAME, bt as ThemeProvider, Ie as VARIABLE_REGEX, g as WRITE_ENDPOINT_NAMES, ot as applyThemeClass, e as authFailureFromResponse, xe as availableFonts, _e as baseDefaultValue, ze as collectServerElements, y as connectorPresets, _ as connectorTokens, u as contexts, i as createAuthFailureLink, ie as createStoreDevToolsLogger, K as createStripTypenameLink, ft as createThemeState, pt as createThemeStore, Tt as currentRscLocation, te as debugCookieName, L as delay, G as disableReactDevTools, b as emptyManifest, R as emptyObject, F as evaluateRuleGroup, Me as fallbackForFamily, Se as familiesInCss, S as fetchManifest, a as filters, Le as findLayoutCycle, Ce as fontFamilyStack, ye as fontLinkAssets, we as fontUrlResolver, Ne as fontsFromCss, Te as fontsToHead, T as formatDate, E as formatDateUTC, D as formatFromNow, O as formatUTCToLocal, C as generateFacade, X as getBindingsDetails, v as getConnectorTokens, z as getDisplayName, k as getDurationMs, tt as getInstance, B as getKeyDecoded, V as getPathsFromObeject, Z as getSourceName, Ee as googleCss2Url, De as googleTextSubsetUrl, Be as hasServerElements, s as hasValidToken, H as hexToRGB, ve as inheritableAttributesBase, A as isDate, U as isInViewport, ne as isInteractionFlow, nt as isRTEvent, Oe as isSafeFontUrl, st as isTheme, P as isUserEdit, j as isValidFormat, W as makeId, t as onAuthFailure, ae as pConsole, M as parseDate, je as parseSpaceFont, ke as primaryFamily, o as processTwig, ct as readThemeCookie, wt as refreshRsc, n as reportAuthFailure, Re as resolveLayoutChain, mt as resolveScheme, $ as resolveVariables, Et as rscDataPath, kt as runtimeStatePersist, r as sameRegistrableDomain, ht as setAreaTheme, rt as setInstance, gt as setMachineScheme, _t as setThemeMode, We as spaceEventSchemas, q as stripTypenameDeep, me as styleConstants, w as syntaxHighlight, c as templateRootNames, vt as themeFor, lt as themeFromCookies, dt as themeStore, N as toUnixSeconds, Ct as useActionsSync, se as useFontHead, ce as useNetwork, le as usePlitziServiceContext, Q as useRegisterSource, Dt as useRscRefresh, Ot as useRscSync, fe as useStableValue, xt as useTheme, yt as useThemeStore, J as utility, Y as utilityOptions, x as validateConnectorManifest, Ge as validateSpaceEvent, ut as writeThemeCookie };
|
|
@@ -24,12 +24,22 @@ export type QueriesState = {
|
|
|
24
24
|
};
|
|
25
25
|
export type QueryObserverOptions<T> = {
|
|
26
26
|
meta: QueryMeta;
|
|
27
|
-
|
|
27
|
+
/** Given the signal of the request it is making, so an answer nobody can still read is not waited for. */
|
|
28
|
+
fetcher: (signal: AbortSignal) => Promise<T>;
|
|
28
29
|
/** How long an answer counts as current, in milliseconds. `0` asks again on every mount. */
|
|
29
30
|
staleTime: number;
|
|
30
31
|
/** An answer this rejects is shown but never trusted: the next observer to mount asks again. */
|
|
31
32
|
isCacheable?: (data: T) => boolean;
|
|
32
33
|
};
|
|
34
|
+
/**
|
|
35
|
+
* What is keeping a query, for the devtools: a query nobody renders is not a leak, it is the grace period doing its
|
|
36
|
+
* job — but that is only obvious if the panel can say so, and offer to end it.
|
|
37
|
+
*/
|
|
38
|
+
export type QueryUsage = {
|
|
39
|
+
observers: number;
|
|
40
|
+
holds: number;
|
|
41
|
+
collectAt?: number;
|
|
42
|
+
};
|
|
33
43
|
/**
|
|
34
44
|
* One path segment per key.
|
|
35
45
|
*
|
|
@@ -65,6 +75,17 @@ export declare class QueryCache {
|
|
|
65
75
|
getEntry(key: string): QueryEntry | undefined;
|
|
66
76
|
/** Whether `key` has been answered in this session — every answer is written with a TTL, even a distrusted one. */
|
|
67
77
|
hasAnswer(key: string): boolean;
|
|
78
|
+
/** Who is keeping `key` alive, and when it would be forgotten if nobody else asked for it. */
|
|
79
|
+
usage(key: string): QueryUsage | undefined;
|
|
80
|
+
/**
|
|
81
|
+
* Forgets `key` now: the answer, the grace period and the request still out for it.
|
|
82
|
+
*
|
|
83
|
+
* The grace period is what keeps an answer around for somebody coming back, and there is no reason to wait it out
|
|
84
|
+
* when a reader knows they will not — a devtools panel clearing what a page stopped using, a flow dropping what a
|
|
85
|
+
* sign-out made meaningless. A query something still renders is left alone: dropping what is on screen leaves it
|
|
86
|
+
* with nothing and nothing to ask again, since the observer that would ask is already attached.
|
|
87
|
+
*/
|
|
88
|
+
remove(key: string): boolean;
|
|
68
89
|
/**
|
|
69
90
|
* Keeps `key` from being collected for as long as the returned function is not called, and for `gcTime` after.
|
|
70
91
|
* The latest reader's `gcTime` is the one kept.
|
|
@@ -93,8 +114,24 @@ export declare class QueryCache {
|
|
|
93
114
|
*
|
|
94
115
|
* Invalidating would not do: a stale query still SHOWS what it holds until the new answer lands, and what it holds
|
|
95
116
|
* belongs to the previous visitor. The epoch makes a request still in flight from before land nowhere.
|
|
117
|
+
*
|
|
118
|
+
* `refetch` is what becomes of the queries still on screen. As somebody else, they are asked again, so the page in
|
|
119
|
+
* front of the new person is theirs. As NOBODY it is a sign-out, and there is no one to ask on behalf of: asking
|
|
120
|
+
* anyway was one refusal per provider still mounted, each reported as a failed session, for a page already on its
|
|
121
|
+
* way to the guest view.
|
|
122
|
+
*/
|
|
123
|
+
reset({ refetch }?: {
|
|
124
|
+
refetch?: boolean;
|
|
125
|
+
}): Promise<void>;
|
|
126
|
+
/**
|
|
127
|
+
* Holding nothing and asking for nothing — the state a query is left in when the answers are forgotten and nobody
|
|
128
|
+
* asks again.
|
|
129
|
+
*
|
|
130
|
+
* Without it the entry is simply gone, and a reader takes that for "about to be asked": it renders as loading for
|
|
131
|
+
* as long as it stays mounted, because the observer that would ask is already attached and nothing re-runs it.
|
|
132
|
+
* Written with no life at all, so the next mount asks.
|
|
96
133
|
*/
|
|
97
|
-
|
|
134
|
+
private markUnasked;
|
|
98
135
|
/**
|
|
99
136
|
* Expiring the path is the invalidation: {@link onExpired} does the rest, for this call and for anybody else who
|
|
100
137
|
* expires a query's path — the dev-tools' "Expire" included. A query that has never answered has no record to
|
|
@@ -25,6 +25,18 @@ var t = 3e5, n = (e) => {
|
|
|
25
25
|
hasAnswer(e) {
|
|
26
26
|
return this.getEntry(e) !== void 0 && this.store.getFreshness(r(e)) !== void 0;
|
|
27
27
|
}
|
|
28
|
+
usage(e) {
|
|
29
|
+
let t = this.runtimes.get(n(e));
|
|
30
|
+
return t && {
|
|
31
|
+
observers: t.observers.size,
|
|
32
|
+
holds: t.holds,
|
|
33
|
+
collectAt: t.collectAt
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
remove(e) {
|
|
37
|
+
let t = this.runtimes.get(n(e));
|
|
38
|
+
return !t || t.observers.size > 0 || t.holds > 0 ? !1 : (this.cancelGc(t), this.collect(t), !0);
|
|
39
|
+
}
|
|
28
40
|
hold(e, n = t) {
|
|
29
41
|
let r = this.ensure(e);
|
|
30
42
|
return r.gcTime = n, r.holds++, this.cancelGc(r), () => {
|
|
@@ -69,12 +81,23 @@ var t = 3e5, n = (e) => {
|
|
|
69
81
|
}) || t.push(this.invalidateOne(n));
|
|
70
82
|
}), Promise.all(t).then(() => void 0);
|
|
71
83
|
}
|
|
72
|
-
reset() {
|
|
73
|
-
this.epochValue++, this.runtimes.forEach((e) => {
|
|
74
|
-
e.version++, e.inFlight = void 0;
|
|
75
|
-
}), this.store.setState("entries", {});
|
|
76
|
-
let
|
|
77
|
-
return this.runtimes.forEach((
|
|
84
|
+
reset({ refetch: e = !0 } = {}) {
|
|
85
|
+
if (this.epochValue++, this.runtimes.forEach((e) => {
|
|
86
|
+
e.version++, e.inFlight = void 0, e.controller?.abort(), e.controller = void 0;
|
|
87
|
+
}), this.store.setState("entries", {}), !e) return this.runtimes.forEach((e) => this.markUnasked(e)), Promise.resolve();
|
|
88
|
+
let t = [];
|
|
89
|
+
return this.runtimes.forEach((e) => t.push(this.fetchActive(e))), Promise.all(t).then(() => void 0);
|
|
90
|
+
}
|
|
91
|
+
markUnasked(e) {
|
|
92
|
+
let t = e.observers.values().next();
|
|
93
|
+
if (t.done) return;
|
|
94
|
+
let n = {
|
|
95
|
+
key: e.key,
|
|
96
|
+
url: t.value.meta.url,
|
|
97
|
+
tags: [...e.tags],
|
|
98
|
+
isFetching: !1
|
|
99
|
+
};
|
|
100
|
+
this.store.setState(r(e.key), n, { ttl: 0 });
|
|
78
101
|
}
|
|
79
102
|
invalidateOne(e) {
|
|
80
103
|
return this.store.expire(r(e.key)).length === 0 && e.version++, this.fetchActive(e);
|
|
@@ -100,7 +123,7 @@ var t = 3e5, n = (e) => {
|
|
|
100
123
|
});
|
|
101
124
|
let c = this.epochValue, l = e.version, u = (r) => {
|
|
102
125
|
if (c !== this.epochValue || this.runtimes.get(n(i)) !== e) return Promise.resolve();
|
|
103
|
-
e.inFlight = void 0;
|
|
126
|
+
e.inFlight = void 0, e.controller = void 0;
|
|
104
127
|
let u = l !== e.version;
|
|
105
128
|
if ("error" in r) {
|
|
106
129
|
let e = this.getEntry(i);
|
|
@@ -123,8 +146,8 @@ var t = 3e5, n = (e) => {
|
|
|
123
146
|
}, { ttl: n ? this.ttlOf(e, t) : 0 });
|
|
124
147
|
}
|
|
125
148
|
return u ? this.fetchActive(e) : Promise.resolve();
|
|
126
|
-
};
|
|
127
|
-
return e.inFlight = t.fetcher().then((e) => u({ data: e }), (e) => u({ error: e })), e.inFlight;
|
|
149
|
+
}, d = new AbortController();
|
|
150
|
+
return e.controller = d, e.inFlight = t.fetcher(d.signal).then((e) => u({ data: e }), (e) => u({ error: e })), e.inFlight;
|
|
128
151
|
}
|
|
129
152
|
ttlOf(e, t) {
|
|
130
153
|
let n = e.observers.size > 0 ? Infinity : t.staleTime;
|
|
@@ -146,7 +169,7 @@ var t = 3e5, n = (e) => {
|
|
|
146
169
|
}), i;
|
|
147
170
|
}
|
|
148
171
|
cancelGc(e) {
|
|
149
|
-
clearTimeout(e.gcTimer), e.gcTimer = void 0;
|
|
172
|
+
clearTimeout(e.gcTimer), e.gcTimer = void 0, e.collectAt = void 0;
|
|
150
173
|
}
|
|
151
174
|
scheduleGc(e) {
|
|
152
175
|
if (!(e.holds > 0 || e.observers.size > 0)) {
|
|
@@ -154,12 +177,12 @@ var t = 3e5, n = (e) => {
|
|
|
154
177
|
this.collect(e);
|
|
155
178
|
return;
|
|
156
179
|
}
|
|
157
|
-
e.gcTimer = setTimeout(() => this.collect(e), e.gcTime);
|
|
180
|
+
e.collectAt = Date.now() + e.gcTime, e.gcTimer = setTimeout(() => this.collect(e), e.gcTime);
|
|
158
181
|
}
|
|
159
182
|
}
|
|
160
183
|
collect(e) {
|
|
161
184
|
let t = n(e.key);
|
|
162
|
-
this.runtimes.get(t) === e && e.holds === 0 && e.observers.size === 0 && (this.runtimes.delete(t), this.store.setState(r(e.key), void 0, { unmount: !0 }));
|
|
185
|
+
this.runtimes.get(t) === e && e.holds === 0 && e.observers.size === 0 && (this.runtimes.delete(t), e.controller?.abort(), this.store.setState(r(e.key), void 0, { unmount: !0 }));
|
|
163
186
|
}
|
|
164
187
|
}, a = new i();
|
|
165
188
|
//#endregion
|
|
@@ -3,7 +3,7 @@ export type UseQueryOptions<T> = {
|
|
|
3
3
|
/** What identifies the answer. Without one the hook is inert: it reads, holds and asks for nothing. */
|
|
4
4
|
key: string | undefined;
|
|
5
5
|
meta: QueryMeta;
|
|
6
|
-
fetcher: () => Promise<T>;
|
|
6
|
+
fetcher: (signal: AbortSignal) => Promise<T>;
|
|
7
7
|
enabled?: boolean;
|
|
8
8
|
/** How long an answer counts as current, in milliseconds. */
|
|
9
9
|
staleTime: number;
|
package/dist/schema/index.d.ts
CHANGED
package/dist/schema/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import e from "./SchemaContext.mjs";
|
|
2
2
|
import { EMPTY_SCHEMA as t, VARIABLE_REGEX as n } from "./schemaConstants.mjs";
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import { findLayoutCycle as r, resolveLayoutChain as i } from "./layoutChain.mjs";
|
|
4
|
+
import { collectServerElements as a, hasServerElements as o } from "./serverElements.mjs";
|
|
5
|
+
export { t as EMPTY_SCHEMA, e as SchemaContext, n as VARIABLE_REGEX, a as collectServerElements, r as findLayoutCycle, o as hasServerElements, i as resolveLayoutChain };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Element } from '../types';
|
|
2
|
+
/** One shell a page is rendered inside: the layoutContainer element, and the container in it that takes the body. */
|
|
3
|
+
export type LayoutLink = {
|
|
4
|
+
layout: string;
|
|
5
|
+
slot: string;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* The shells around a page, innermost first.
|
|
9
|
+
*
|
|
10
|
+
* A page names ONE shell (`layout`) and the container in it its body goes into (`layoutContainer`). That shell may
|
|
11
|
+
* name one of its own the same way — analytics pages share a header and tabs, and that header sits inside the
|
|
12
|
+
* platform's sidebar shell — so the chain is followed until a shell names none. A shell the document does not hold, or
|
|
13
|
+
* one already in the chain, ends it: a cycle is a mistake in the document, and rendering it would never finish.
|
|
14
|
+
*/
|
|
15
|
+
export declare const resolveLayoutChain: (getElement: (id: string) => Element | undefined, layout: string, layoutContainer: string) => LayoutLink[];
|
|
16
|
+
/** The layouts a chain passes through that close it on itself, if any: `layout` → … → `layout`. */
|
|
17
|
+
export declare const findLayoutCycle: (getElement: (id: string) => Element | undefined, layout: string) => string[];
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region src/schema/layoutChain.ts
|
|
2
|
+
var e = (e, t) => {
|
|
3
|
+
let n = e?.attributes[t];
|
|
4
|
+
return typeof n == "string" ? n : "";
|
|
5
|
+
}, t = (t, n, r) => {
|
|
6
|
+
let i = [], a = /* @__PURE__ */ new Set(), o = n, s = r;
|
|
7
|
+
for (; o && !a.has(o) && i.length < 16;) {
|
|
8
|
+
let n = t(o);
|
|
9
|
+
if (n?.definition.type !== "layoutContainer") break;
|
|
10
|
+
a.add(o), i.push({
|
|
11
|
+
layout: o,
|
|
12
|
+
slot: s || o
|
|
13
|
+
}), o = e(n, "layout"), s = e(n, "layoutContainer");
|
|
14
|
+
}
|
|
15
|
+
return i;
|
|
16
|
+
}, n = (t, n) => {
|
|
17
|
+
let r = [], i = n;
|
|
18
|
+
for (; i && r.length <= 16;) {
|
|
19
|
+
if (r.includes(i)) return [...r.slice(r.indexOf(i)), i];
|
|
20
|
+
r.push(i), i = e(t(i), "layout");
|
|
21
|
+
}
|
|
22
|
+
return [];
|
|
23
|
+
};
|
|
24
|
+
//#endregion
|
|
25
|
+
export { n as findLayoutCycle, t as resolveLayoutChain };
|
|
@@ -3,6 +3,8 @@ import { ProfilerOnRenderCallback } from 'react';
|
|
|
3
3
|
declare const tracingCollector: {
|
|
4
4
|
onRender: ProfilerOnRenderCallback;
|
|
5
5
|
linkParent: (id: string, parentId: string | undefined, elementId: string) => void;
|
|
6
|
+
markMounted: (id: string) => void;
|
|
7
|
+
markUnmounted: (id: string) => void;
|
|
6
8
|
recordProps: (id: string, changes: PropChange[]) => void;
|
|
7
9
|
recordStoreChange: (change: {
|
|
8
10
|
path: string | undefined;
|
|
@@ -2,33 +2,39 @@ import { previewValue as e } from "./preview.mjs";
|
|
|
2
2
|
import t from "./tracingStore.mjs";
|
|
3
3
|
import { createRecorder as n } from "@plitzi/nexus";
|
|
4
4
|
//#region src/store/tracing/tracingCollector.ts
|
|
5
|
-
var r = n({ max: 30 }), i = [], a = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Map(), l = !0, u =
|
|
5
|
+
var r = n({ max: 30 }), i = [], a = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Map(), l = !0, u = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map(), f = 0, p = /* @__PURE__ */ new Map(), m = !1, h = !1, g = 0, _ = !1, v = !1, y = typeof requestAnimationFrame == "function" ? (e) => {
|
|
6
6
|
requestAnimationFrame(e);
|
|
7
7
|
} : (e) => {
|
|
8
8
|
setTimeout(e, 16);
|
|
9
|
-
},
|
|
9
|
+
}, b = () => {
|
|
10
10
|
let e = {};
|
|
11
11
|
for (let [t, n] of c) e[t] = {
|
|
12
12
|
parentId: o.get(t),
|
|
13
13
|
baseDuration: n,
|
|
14
|
-
elementId: s.get(t) ?? t
|
|
14
|
+
elementId: s.get(t) ?? t,
|
|
15
|
+
mountedAt: u.get(t),
|
|
16
|
+
unmountedAt: d.get(t)
|
|
15
17
|
};
|
|
16
18
|
return e;
|
|
17
|
-
}, y = () => {
|
|
18
|
-
l && (l = !1, t.setState("tree", v())), t.setState("hydrated", g), t.setState("commits", i);
|
|
19
|
-
}, b = () => {
|
|
20
|
-
g || (g = !0, p && t.setState("hydrated", !0));
|
|
21
19
|
}, x = () => {
|
|
22
|
-
|
|
20
|
+
l && (l = !1, t.setState("tree", b())), t.setState("hydrated", v), t.setState("commits", i);
|
|
21
|
+
}, S = () => {
|
|
22
|
+
v || (v = !0, h && t.setState("hydrated", !0));
|
|
23
|
+
}, C = (e) => {
|
|
24
|
+
o.delete(e), s.delete(e), c.delete(e), u.delete(e), d.delete(e), l = !0;
|
|
25
|
+
}, w = (e) => {
|
|
26
|
+
for (let [t, n] of d) n <= e && C(t);
|
|
27
|
+
}, T = () => {
|
|
28
|
+
if (_ = !1, a.size > 0) {
|
|
23
29
|
let e = [...a.values()].sort((e, t) => e.timestamp - t.timestamp);
|
|
24
|
-
a.clear(), i = [...i, ...e], i.length > 200 && (i = i.slice(i.length - 200));
|
|
30
|
+
a.clear(), i = [...i, ...e], i.length > 200 && (i = i.slice(i.length - 200)), w(i[0].commitId);
|
|
25
31
|
}
|
|
26
|
-
|
|
27
|
-
},
|
|
28
|
-
(!o.has(e) || o.get(e) !== t) && (l = !0), o.size >= 2e4 && !o.has(e) && (o.clear(), s.clear(), c.clear(), l = !0), o.set(e, t), s.set(e, n);
|
|
29
|
-
},
|
|
30
|
-
let t = r.entriesSince(
|
|
31
|
-
|
|
32
|
+
h && x();
|
|
33
|
+
}, E = (e, t, n) => {
|
|
34
|
+
(!o.has(e) || o.get(e) !== t) && (l = !0), o.size >= 2e4 && !o.has(e) && (o.clear(), s.clear(), c.clear(), u.clear(), d.clear(), l = !0), o.set(e, t), s.set(e, n);
|
|
35
|
+
}, D = () => {
|
|
36
|
+
let t = r.entriesSince(f);
|
|
37
|
+
f = r.lastSeq();
|
|
32
38
|
let n = /* @__PURE__ */ new Map();
|
|
33
39
|
for (let e of t) {
|
|
34
40
|
if (e.path === void 0) continue;
|
|
@@ -42,46 +48,60 @@ var r = n({ max: 30 }), i = [], a = /* @__PURE__ */ new Map(), o = /* @__PURE__
|
|
|
42
48
|
path: t,
|
|
43
49
|
preview: `${e(n.prev)} → ${e(n.next)}`
|
|
44
50
|
}));
|
|
45
|
-
},
|
|
46
|
-
onRender: (e, n, r, i,
|
|
47
|
-
|
|
48
|
-
let
|
|
49
|
-
|
|
50
|
-
let v =
|
|
51
|
+
}, O = {
|
|
52
|
+
onRender: (e, n, r, i, d, f) => {
|
|
53
|
+
m || (m = !0, t.setState("enabled", !0));
|
|
54
|
+
let h = !c.has(e);
|
|
55
|
+
c.set(e, i);
|
|
56
|
+
let v = p.get(e);
|
|
57
|
+
p.delete(e);
|
|
58
|
+
let b = {
|
|
51
59
|
id: e,
|
|
52
60
|
elementId: s.get(e) ?? e,
|
|
53
61
|
parentId: o.get(e),
|
|
54
62
|
phase: n,
|
|
55
63
|
actualDuration: r,
|
|
56
64
|
baseDuration: i,
|
|
57
|
-
changedProps:
|
|
58
|
-
},
|
|
59
|
-
|
|
60
|
-
commitId:
|
|
61
|
-
timestamp:
|
|
65
|
+
changedProps: v
|
|
66
|
+
}, x = a.get(f);
|
|
67
|
+
x ? (x.elements.push(b), x.elementCount += 1, x.duration = Math.max(x.duration, r)) : (g += 1, a.set(f, {
|
|
68
|
+
commitId: g,
|
|
69
|
+
timestamp: f,
|
|
62
70
|
duration: r,
|
|
63
71
|
elementCount: 1,
|
|
64
|
-
elements: [
|
|
65
|
-
causes:
|
|
66
|
-
})), h
|
|
72
|
+
elements: [b],
|
|
73
|
+
causes: D()
|
|
74
|
+
})), h && (u.set(e, a.get(f)?.commitId ?? g), l = !0), _ || (_ = !0, y(T));
|
|
75
|
+
},
|
|
76
|
+
linkParent: E,
|
|
77
|
+
markMounted: (e) => {
|
|
78
|
+
d.delete(e) && (l = !0);
|
|
79
|
+
},
|
|
80
|
+
markUnmounted: (e) => {
|
|
81
|
+
if (!c.has(e)) {
|
|
82
|
+
C(e);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
d.set(e, g), l = !0, _ || (_ = !0, y(T));
|
|
67
86
|
},
|
|
68
|
-
linkParent: S,
|
|
69
87
|
recordProps: (e, t) => {
|
|
70
|
-
|
|
88
|
+
p.set(e, t);
|
|
71
89
|
},
|
|
72
90
|
recordStoreChange: (e) => {
|
|
73
91
|
r.record(e);
|
|
74
92
|
},
|
|
75
|
-
setHydrated:
|
|
93
|
+
setHydrated: S,
|
|
76
94
|
start: () => {
|
|
77
|
-
|
|
95
|
+
h = !0, T(), x();
|
|
78
96
|
},
|
|
79
97
|
stop: () => {
|
|
80
|
-
|
|
98
|
+
h = !1;
|
|
81
99
|
},
|
|
82
100
|
clear: () => {
|
|
83
|
-
i = [], a.clear(),
|
|
101
|
+
i = [], a.clear(), f = r.lastSeq(), p.clear(), g = 0;
|
|
102
|
+
for (let e of [...d.keys()]) C(e);
|
|
103
|
+
u.clear(), l = !0, x();
|
|
84
104
|
}
|
|
85
105
|
};
|
|
86
106
|
//#endregion
|
|
87
|
-
export {
|
|
107
|
+
export { O as default };
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { Asset, PluginManifest, PluginSchema } from './PluginTypes';
|
|
2
2
|
import { Element } from './SchemaTypes';
|
|
3
|
-
import { ReactNode } from 'react';
|
|
4
3
|
export type ElementLayoutType = 'layout' | 'segment' | 'element' | 'reference';
|
|
4
|
+
/**
|
|
5
|
+
* Which shell an element is rendered inside, and which of its containers is the slot.
|
|
6
|
+
*
|
|
7
|
+
* Every element of the shell carries it, so it holds nothing that changes with the page: the body itself reaches the
|
|
8
|
+
* slot through `LayoutBody` in `@plitzi/sdk-elements`.
|
|
9
|
+
*/
|
|
5
10
|
export type ElementLayout = {
|
|
6
|
-
bodyChildren: ReactNode;
|
|
7
11
|
containerId: string;
|
|
8
|
-
referenceId: string;
|
|
9
12
|
rootId: string;
|
|
10
13
|
type: ElementLayoutType;
|
|
11
14
|
};
|
|
@@ -250,6 +250,10 @@ export type TracingTreeNode = {
|
|
|
250
250
|
baseDuration: number;
|
|
251
251
|
/** Which element this instance is — see `CommitElementRender.id`. */
|
|
252
252
|
elementId: string;
|
|
253
|
+
/** The first commit it rendered in; absent means it was already there when the timeline started. */
|
|
254
|
+
mountedAt?: number;
|
|
255
|
+
/** The commit that removed it, which it is no longer part of; absent while it is on the page. */
|
|
256
|
+
unmountedAt?: number;
|
|
253
257
|
};
|
|
254
258
|
export type TracingTree = Record<string, TracingTreeNode>;
|
|
255
259
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plitzi/sdk-shared",
|
|
3
|
-
"version": "0.36.
|
|
3
|
+
"version": "0.36.2",
|
|
4
4
|
"license": "AGPL-3.0",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -444,6 +444,10 @@
|
|
|
444
444
|
"types": "./dist/hooks/usePlitziServiceContext.d.ts",
|
|
445
445
|
"import": "./dist/hooks/usePlitziServiceContext.mjs"
|
|
446
446
|
},
|
|
447
|
+
"./hooks/useStableValue": {
|
|
448
|
+
"types": "./dist/hooks/useStableValue.d.ts",
|
|
449
|
+
"import": "./dist/hooks/useStableValue.mjs"
|
|
450
|
+
},
|
|
447
451
|
"./index": {
|
|
448
452
|
"types": "./dist/index.d.ts",
|
|
449
453
|
"import": "./dist/index.mjs"
|
|
@@ -984,6 +988,10 @@
|
|
|
984
988
|
"types": "./dist/schema/index.d.ts",
|
|
985
989
|
"import": "./dist/schema/index.mjs"
|
|
986
990
|
},
|
|
991
|
+
"./schema/layoutChain": {
|
|
992
|
+
"types": "./dist/schema/layoutChain.d.ts",
|
|
993
|
+
"import": "./dist/schema/layoutChain.mjs"
|
|
994
|
+
},
|
|
987
995
|
"./schema/schemaConstants": {
|
|
988
996
|
"types": "./dist/schema/schemaConstants.d.ts",
|
|
989
997
|
"import": "./dist/schema/schemaConstants.mjs"
|
|
@@ -1272,13 +1280,13 @@
|
|
|
1272
1280
|
},
|
|
1273
1281
|
"dependencies": {
|
|
1274
1282
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
1275
|
-
"@plitzi/nexus": "^1.2.
|
|
1283
|
+
"@plitzi/nexus": "^1.2.2",
|
|
1276
1284
|
"@plitzi/plitzi-ui": "^1.6.21",
|
|
1277
1285
|
"date-fns": "^4.4.0",
|
|
1278
1286
|
"date-fns-tz": "^3.2.0",
|
|
1279
1287
|
"graphql-tag": "^2.12.7",
|
|
1280
1288
|
"immer": "^11.1.18",
|
|
1281
|
-
"zod": "^4.6.
|
|
1289
|
+
"zod": "^4.6.5"
|
|
1282
1290
|
},
|
|
1283
1291
|
"peerDependencies": {
|
|
1284
1292
|
"react": "^19",
|
|
@@ -1293,34 +1301,34 @@
|
|
|
1293
1301
|
"@babel/preset-env": "^8.0.5",
|
|
1294
1302
|
"@eslint/js": "^10.0.1",
|
|
1295
1303
|
"@tailwindcss/forms": "^0.5.11",
|
|
1296
|
-
"@testing-library/dom": "^10.4.
|
|
1304
|
+
"@testing-library/dom": "^10.4.2",
|
|
1297
1305
|
"@testing-library/react": "^16.3.3",
|
|
1298
1306
|
"@testing-library/react-hooks": "^8.0.1",
|
|
1299
1307
|
"@testing-library/user-event": "^14.6.7",
|
|
1300
1308
|
"@types/react": "^19.3.0",
|
|
1301
1309
|
"@types/react-dom": "^19.3.0",
|
|
1302
1310
|
"@vitejs/plugin-react": "^6.1.1",
|
|
1303
|
-
"@vitest/coverage-v8": "^5.0.
|
|
1311
|
+
"@vitest/coverage-v8": "^5.0.1",
|
|
1304
1312
|
"babel-minify": "^0.5.2",
|
|
1305
1313
|
"eslint": "^9.39.5",
|
|
1306
1314
|
"eslint-config-airbnb": "^19.0.4",
|
|
1307
1315
|
"eslint-config-prettier": "^10.1.8",
|
|
1308
|
-
"eslint-config-turbo": "^2.10.
|
|
1316
|
+
"eslint-config-turbo": "^2.10.13",
|
|
1309
1317
|
"eslint-import-resolver-alias": "^1.1.2",
|
|
1310
1318
|
"eslint-plugin-cypress": "^7.0.2",
|
|
1311
1319
|
"eslint-plugin-flowtype": "8.0.3",
|
|
1312
1320
|
"eslint-plugin-import": "^2.32.0",
|
|
1313
|
-
"eslint-plugin-jsdoc": "^64.
|
|
1321
|
+
"eslint-plugin-jsdoc": "^64.5.2",
|
|
1314
1322
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
1315
1323
|
"eslint-plugin-prettier": "^5.5.6",
|
|
1316
1324
|
"eslint-plugin-react": "^7.37.5",
|
|
1317
1325
|
"eslint-plugin-react-hooks": "^7.1.1",
|
|
1318
|
-
"eslint-plugin-react-refresh": "^0.5.
|
|
1326
|
+
"eslint-plugin-react-refresh": "^0.5.7",
|
|
1319
1327
|
"eslint-plugin-storybook": "^10.6.0",
|
|
1320
1328
|
"globals": "^17.12.0",
|
|
1321
|
-
"jsdom": "^30.0
|
|
1329
|
+
"jsdom": "^30.1.0",
|
|
1322
1330
|
"postcss": "^8.5.28",
|
|
1323
|
-
"prettier": "^3.9.
|
|
1331
|
+
"prettier": "^3.9.8",
|
|
1324
1332
|
"react": "^19.3.0",
|
|
1325
1333
|
"react-dom": "^19.3.0",
|
|
1326
1334
|
"tailwindcss": "^4.3.3",
|
|
@@ -1330,7 +1338,7 @@
|
|
|
1330
1338
|
"vite": "^8.3.0",
|
|
1331
1339
|
"vite-plugin-dts": "^5.1.0",
|
|
1332
1340
|
"vite-plugin-react": "^4.0.1",
|
|
1333
|
-
"vitest": "^5.0.
|
|
1341
|
+
"vitest": "^5.0.1",
|
|
1334
1342
|
"vitest-fetch-mock": "^0.4.5"
|
|
1335
1343
|
}
|
|
1336
1344
|
}
|