@epoch32/visage 0.0.0 → 1.1.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/dist/api/client.d.ts +5 -0
- package/dist/api/file-router.d.ts +29 -0
- package/dist/api/handler.d.ts +15 -0
- package/dist/api/index.d.ts +12 -0
- package/dist/{src/api → api}/index.js +87 -2
- package/dist/api/middleware.d.ts +11 -0
- package/dist/api/pragma.d.ts +21 -0
- package/dist/api/procedure.d.ts +66 -0
- package/dist/api/types.d.ts +181 -0
- package/dist/charts/Area.d.ts +18 -0
- package/dist/charts/Axis.d.ts +21 -0
- package/dist/charts/Bar.d.ts +10 -0
- package/dist/charts/CartesianGrid.d.ts +10 -0
- package/dist/charts/Chart.d.ts +16 -0
- package/dist/charts/Cursor.d.ts +8 -0
- package/dist/charts/Legend.d.ts +9 -0
- package/dist/charts/Line.d.ts +18 -0
- package/dist/charts/Pie.d.ts +12 -0
- package/dist/charts/Tooltip.d.ts +12 -0
- package/dist/charts/context.d.ts +20 -0
- package/dist/charts/index.d.ts +14 -0
- package/dist/{src/charts → charts}/index.js +87 -2
- package/dist/charts/path.d.ts +27 -0
- package/dist/charts/scale.d.ts +23 -0
- package/dist/charts/types.d.ts +43 -0
- package/dist/devtools/DomTab.d.ts +6 -0
- package/dist/devtools/GraphInspector.d.ts +11 -0
- package/dist/devtools/GraphTab.d.ts +10 -0
- package/dist/devtools/QueryTab.d.ts +10 -0
- package/dist/devtools/RpcTab.d.ts +10 -0
- package/dist/devtools/SignalsTab.d.ts +10 -0
- package/dist/devtools/component.d.ts +2 -0
- package/dist/devtools/highlighter.d.ts +2 -0
- package/dist/devtools/hub.d.ts +41 -0
- package/dist/devtools/index.d.ts +9 -0
- package/dist/{src/devtools → devtools}/index.js +87 -2
- package/dist/devtools/styles.d.ts +1 -0
- package/dist/devtools/types.d.ts +44 -0
- package/dist/dom/async.d.ts +41 -0
- package/dist/dom/control-flow.d.ts +53 -0
- package/dist/dom/index.d.ts +3 -0
- package/dist/{src/dom → dom}/index.js +87 -2
- package/dist/dom/lazy.d.ts +30 -0
- package/dist/dom/render.d.ts +23 -0
- package/dist/dom/resource.d.ts +34 -0
- package/dist/form/form.d.ts +41 -0
- package/dist/form/index.d.ts +2 -0
- package/dist/{src/form → form}/index.js +87 -2
- package/dist/form/schema.d.ts +96 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +3571 -1293
- package/dist/jsx-dev-runtime/index.d.ts +1 -0
- package/dist/jsx-runtime/index.d.ts +8 -0
- package/dist/{src/jsx-runtime → jsx-runtime}/index.js +87 -2
- package/dist/query/create-mutation.d.ts +3 -0
- package/dist/query/create-query.d.ts +4 -0
- package/dist/query/focus-manager.d.ts +14 -0
- package/dist/query/index.d.ts +9 -0
- package/dist/{src/query → query}/index.js +87 -2
- package/dist/query/mutation-cache.d.ts +24 -0
- package/dist/query/online-manager.d.ts +14 -0
- package/dist/query/query-cache.d.ts +69 -0
- package/dist/query/query-client.d.ts +46 -0
- package/dist/query/types.d.ts +131 -0
- package/dist/query/utils.d.ts +16 -0
- package/dist/router/index.d.ts +1 -0
- package/dist/{src/router → router}/index.js +87 -2
- package/dist/router/router.d.ts +91 -0
- package/dist/rpc/client.d.ts +2 -0
- package/dist/rpc/error.d.ts +16 -0
- package/dist/rpc/index.d.ts +7 -0
- package/dist/{src/rpc → rpc}/index.js +87 -2
- package/dist/rpc/procedure.d.ts +8 -0
- package/dist/rpc/router.d.ts +19 -0
- package/dist/rpc/server.d.ts +3 -0
- package/dist/rpc/types.d.ts +200 -0
- package/dist/server/hydrate.d.ts +5 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/{src/server → server}/index.js +87 -2
- package/dist/server/render-to-stream.d.ts +9 -0
- package/dist/server/render-to-string.d.ts +6 -0
- package/dist/signals/computed.d.ts +61 -0
- package/dist/signals/context.d.ts +44 -0
- package/dist/signals/effect.d.ts +56 -0
- package/dist/signals/index.d.ts +8 -0
- package/dist/{src/signals → signals}/index.js +87 -2
- package/dist/signals/scope.d.ts +61 -0
- package/dist/signals/signal.d.ts +40 -0
- package/dist/signals/store.d.ts +45 -0
- package/dist/signals/system.d.ts +56 -0
- package/dist/signals/types.d.ts +58 -0
- package/dist/style/component.d.ts +49 -0
- package/dist/style/create-style.d.ts +63 -0
- package/dist/style/cx.d.ts +18 -0
- package/dist/style/hash.d.ts +8 -0
- package/dist/style/index.d.ts +8 -0
- package/dist/{src/style → style}/index.js +87 -2
- package/dist/style/layout.d.ts +129 -0
- package/dist/style/manager.d.ts +31 -0
- package/dist/style/parser.d.ts +12 -0
- package/dist/style/scale.d.ts +82 -0
- package/dist/template/index.d.ts +1 -0
- package/dist/{src/template → template}/index.js +87 -2
- package/dist/template/template.d.ts +8 -0
- package/dist/ui/accordion.d.ts +81 -0
- package/dist/ui/command-dialog.d.ts +10 -0
- package/dist/ui/command.d.ts +103 -0
- package/dist/ui/data-table.d.ts +38 -0
- package/dist/ui/dialog.d.ts +102 -0
- package/dist/ui/dropdown-menu.d.ts +92 -0
- package/dist/ui/icon.d.ts +18 -0
- package/dist/ui/index.d.ts +14 -0
- package/dist/{src/ui → ui}/index.js +87 -2
- package/dist/ui/layout.d.ts +1 -0
- package/dist/ui/popover.d.ts +68 -0
- package/dist/ui/switch.d.ts +31 -0
- package/dist/ui/tabs.d.ts +71 -0
- package/dist/ui/toast.d.ts +91 -0
- package/dist/ui/tooltip.d.ts +64 -0
- package/dist/ui/utils.d.ts +21 -0
- package/dist/virtual/index.d.ts +2 -0
- package/dist/{src/virtual → virtual}/index.js +87 -2
- package/dist/virtual/virtual-list.d.ts +21 -0
- package/dist/virtual/virtualizer.d.ts +31 -0
- package/dist/vite/hmr.d.ts +7 -0
- package/dist/vite/index.d.ts +3 -0
- package/dist/vite/index.js +296 -15
- package/dist/vite/lucide.d.ts +27 -0
- package/dist/vite/plugin.d.ts +3 -0
- package/dist/vite/rpc-middleware.d.ts +5 -0
- package/dist/vite/types.d.ts +59 -0
- package/package.json +40 -40
- package/src/signals/index.ts +1 -0
- package/src/signals/signal.ts +110 -2
- package/src/signals/types.ts +9 -0
- package/src/vite/plugin.ts +4 -0
- package/dist/bundle.dev.js +0 -4875
- package/dist/src/index.js +0 -11826
- package/dist/src/vite/index.js +0 -984
|
@@ -848,10 +848,12 @@ class Signal {
|
|
|
848
848
|
_value;
|
|
849
849
|
_subscribers = new Set;
|
|
850
850
|
_equals;
|
|
851
|
+
_onSet;
|
|
851
852
|
version = 0;
|
|
852
|
-
constructor(initialValue, equals) {
|
|
853
|
+
constructor(initialValue, equals, onSet) {
|
|
853
854
|
this._value = initialValue;
|
|
854
855
|
this._equals = equals ?? Object.is;
|
|
856
|
+
this._onSet = onSet;
|
|
855
857
|
}
|
|
856
858
|
get() {
|
|
857
859
|
if (currentSubscriber !== null && currentSubscriber.state !== 3 /* DISPOSED */) {
|
|
@@ -876,6 +878,9 @@ class Signal {
|
|
|
876
878
|
}
|
|
877
879
|
this._value = newValue;
|
|
878
880
|
this.version++;
|
|
881
|
+
if (this._onSet) {
|
|
882
|
+
this._onSet(newValue);
|
|
883
|
+
}
|
|
879
884
|
batch(() => {
|
|
880
885
|
this.notify();
|
|
881
886
|
});
|
|
@@ -901,11 +906,91 @@ class Signal {
|
|
|
901
906
|
}
|
|
902
907
|
}
|
|
903
908
|
}
|
|
909
|
+
function resolveStorage(storageOption) {
|
|
910
|
+
if (storageOption && typeof storageOption === "object") {
|
|
911
|
+
return storageOption;
|
|
912
|
+
}
|
|
913
|
+
if (storageOption === "session") {
|
|
914
|
+
try {
|
|
915
|
+
if (typeof sessionStorage !== "undefined")
|
|
916
|
+
return sessionStorage;
|
|
917
|
+
} catch {}
|
|
918
|
+
try {
|
|
919
|
+
if (typeof window !== "undefined" && window.sessionStorage) {
|
|
920
|
+
return window.sessionStorage;
|
|
921
|
+
}
|
|
922
|
+
} catch {}
|
|
923
|
+
try {
|
|
924
|
+
if (typeof globalThis !== "undefined" && globalThis.sessionStorage) {
|
|
925
|
+
return globalThis.sessionStorage;
|
|
926
|
+
}
|
|
927
|
+
} catch {}
|
|
928
|
+
return null;
|
|
929
|
+
}
|
|
930
|
+
try {
|
|
931
|
+
if (typeof localStorage !== "undefined")
|
|
932
|
+
return localStorage;
|
|
933
|
+
} catch {}
|
|
934
|
+
try {
|
|
935
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
936
|
+
return window.localStorage;
|
|
937
|
+
}
|
|
938
|
+
} catch {}
|
|
939
|
+
try {
|
|
940
|
+
if (typeof globalThis !== "undefined" && globalThis.localStorage) {
|
|
941
|
+
return globalThis.localStorage;
|
|
942
|
+
}
|
|
943
|
+
} catch {}
|
|
944
|
+
return null;
|
|
945
|
+
}
|
|
904
946
|
function signal(initialValue, optionsOrEquals) {
|
|
905
947
|
const equals = typeof optionsOrEquals === "function" ? optionsOrEquals : optionsOrEquals?.equals;
|
|
906
948
|
const isInternal = typeof optionsOrEquals === "object" ? optionsOrEquals?.internal : false;
|
|
907
949
|
const customName = typeof optionsOrEquals === "object" ? optionsOrEquals?.name : undefined;
|
|
908
|
-
const
|
|
950
|
+
const persistOption = typeof optionsOrEquals === "object" ? optionsOrEquals?.persist : undefined;
|
|
951
|
+
const persistConfig = persistOption ? typeof persistOption === "string" ? { key: persistOption } : persistOption : undefined;
|
|
952
|
+
let effectiveInitial = initialValue;
|
|
953
|
+
const storage = persistConfig ? resolveStorage(persistConfig.storage) : null;
|
|
954
|
+
const serialize = persistConfig?.serialize ?? JSON.stringify;
|
|
955
|
+
const deserialize = persistConfig?.deserialize ?? JSON.parse;
|
|
956
|
+
if (persistConfig && storage) {
|
|
957
|
+
try {
|
|
958
|
+
const stored = storage.getItem(persistConfig.key);
|
|
959
|
+
if (stored !== null) {
|
|
960
|
+
effectiveInitial = deserialize(stored);
|
|
961
|
+
}
|
|
962
|
+
} catch {}
|
|
963
|
+
}
|
|
964
|
+
let isSyncing = false;
|
|
965
|
+
const onSet = persistConfig && storage ? (val) => {
|
|
966
|
+
if (isSyncing)
|
|
967
|
+
return;
|
|
968
|
+
try {
|
|
969
|
+
storage.setItem(persistConfig.key, serialize(val));
|
|
970
|
+
} catch {}
|
|
971
|
+
} : undefined;
|
|
972
|
+
const s = new Signal(effectiveInitial, equals, onSet);
|
|
973
|
+
if (persistConfig && storage && (persistConfig.syncTabs ?? true) && typeof window !== "undefined" && typeof window.addEventListener === "function") {
|
|
974
|
+
const onStorage = (e) => {
|
|
975
|
+
if (e.key === persistConfig.key) {
|
|
976
|
+
try {
|
|
977
|
+
const nextVal = e.newValue !== null ? deserialize(e.newValue) : initialValue;
|
|
978
|
+
isSyncing = true;
|
|
979
|
+
try {
|
|
980
|
+
s.set(nextVal);
|
|
981
|
+
} finally {
|
|
982
|
+
isSyncing = false;
|
|
983
|
+
}
|
|
984
|
+
} catch {}
|
|
985
|
+
}
|
|
986
|
+
};
|
|
987
|
+
window.addEventListener("storage", onStorage);
|
|
988
|
+
if (currentScope) {
|
|
989
|
+
currentScope.addCleanup(() => {
|
|
990
|
+
window.removeEventListener("storage", onStorage);
|
|
991
|
+
});
|
|
992
|
+
}
|
|
993
|
+
}
|
|
909
994
|
const accessor = (...args) => {
|
|
910
995
|
if (args.length === 0) {
|
|
911
996
|
return s.get();
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { type Child } from "../dom";
|
|
2
|
+
import { type ReadonlySignal } from "../signals";
|
|
3
|
+
export interface LocationState {
|
|
4
|
+
pathname: ReadonlySignal<string>;
|
|
5
|
+
search: ReadonlySignal<string>;
|
|
6
|
+
hash: ReadonlySignal<string>;
|
|
7
|
+
}
|
|
8
|
+
export interface RouterContextValue {
|
|
9
|
+
location: LocationState;
|
|
10
|
+
navigate: (to: string, options?: {
|
|
11
|
+
replace?: boolean;
|
|
12
|
+
}) => void;
|
|
13
|
+
params: ReadonlySignal<Record<string, string>>;
|
|
14
|
+
base: string;
|
|
15
|
+
matchedRoute: ReadonlySignal<MatchedRoute | null>;
|
|
16
|
+
routes: RouteDefinition[];
|
|
17
|
+
registerRoute: (route: RouteDefinition) => void;
|
|
18
|
+
}
|
|
19
|
+
export interface MatchedRoute {
|
|
20
|
+
path: string;
|
|
21
|
+
params: Record<string, string>;
|
|
22
|
+
component?: (props?: any) => Child;
|
|
23
|
+
children?: Child;
|
|
24
|
+
}
|
|
25
|
+
export interface RouteDefinition {
|
|
26
|
+
path: string;
|
|
27
|
+
component?: (props?: any) => Child;
|
|
28
|
+
children?: Child;
|
|
29
|
+
matcher: RegExp;
|
|
30
|
+
paramNames: string[];
|
|
31
|
+
}
|
|
32
|
+
export interface RouterProps {
|
|
33
|
+
base?: string;
|
|
34
|
+
mode?: "history" | "hash";
|
|
35
|
+
children: Child;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Root Router provider managing browser location state and URL synchronization
|
|
39
|
+
*/
|
|
40
|
+
export declare function Router(props: RouterProps): Child;
|
|
41
|
+
export interface RouteProps {
|
|
42
|
+
path: string;
|
|
43
|
+
component?: (props: any) => Child;
|
|
44
|
+
children?: Child;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Route declaration registering URL path pattern and view component
|
|
48
|
+
*/
|
|
49
|
+
export declare function Route(props: RouteProps): Child;
|
|
50
|
+
export interface RoutesProps {
|
|
51
|
+
children: Child;
|
|
52
|
+
fallback?: Child;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Routes outlet matching the current URL to registered Route definitions
|
|
56
|
+
*/
|
|
57
|
+
export declare function Routes(props: RoutesProps): Child;
|
|
58
|
+
export interface LinkProps {
|
|
59
|
+
href: string;
|
|
60
|
+
class?: string | (() => string);
|
|
61
|
+
activeClass?: string;
|
|
62
|
+
replace?: boolean;
|
|
63
|
+
children: Child;
|
|
64
|
+
[key: string]: any;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Accessible client-side navigation Link with active state highlighting
|
|
68
|
+
*/
|
|
69
|
+
export declare function Link(props: LinkProps): Child;
|
|
70
|
+
/**
|
|
71
|
+
* Access the active router location state signals
|
|
72
|
+
*/
|
|
73
|
+
export declare function useLocation(): LocationState;
|
|
74
|
+
/**
|
|
75
|
+
* Access the imperative navigate function
|
|
76
|
+
*/
|
|
77
|
+
export declare function useNavigate(): (to: string, options?: {
|
|
78
|
+
replace?: boolean;
|
|
79
|
+
}) => void;
|
|
80
|
+
/**
|
|
81
|
+
* Access reactive URL parameter signals
|
|
82
|
+
*/
|
|
83
|
+
export declare function useParams<T extends Record<string, string> = Record<string, string>>(): () => T;
|
|
84
|
+
/**
|
|
85
|
+
* Access and manipulate URL query search parameters reactively
|
|
86
|
+
*/
|
|
87
|
+
export declare function useSearchParams(): [
|
|
88
|
+
() => URLSearchParams,
|
|
89
|
+
(params: Record<string, string> | URLSearchParams) => void
|
|
90
|
+
];
|
|
91
|
+
export { lazy } from "../dom";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ValidationIssue } from "../form/schema";
|
|
2
|
+
import type { RPCErrorCode } from "./types";
|
|
3
|
+
export declare const ERROR_CODE_TO_STATUS: Record<RPCErrorCode, number>;
|
|
4
|
+
export declare const STATUS_TO_ERROR_CODE: Record<number, RPCErrorCode>;
|
|
5
|
+
export declare class RPCError extends Error {
|
|
6
|
+
readonly code: RPCErrorCode;
|
|
7
|
+
readonly status: number;
|
|
8
|
+
readonly issues?: ValidationIssue[];
|
|
9
|
+
constructor(codeOrStatusOrOptions: RPCErrorCode | number | {
|
|
10
|
+
code: RPCErrorCode;
|
|
11
|
+
message?: string;
|
|
12
|
+
issues?: ValidationIssue[];
|
|
13
|
+
cause?: unknown;
|
|
14
|
+
}, message?: string);
|
|
15
|
+
get statusCode(): number;
|
|
16
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { Schema, type SchemaLike, type StandardSchemaV1, type ValidationIssue, type ValidationResult, v, validateWithSchema } from "../form/schema";
|
|
2
|
+
export { createClient } from "./client";
|
|
3
|
+
export { ERROR_CODE_TO_STATUS, RPCError, STATUS_TO_ERROR_CODE } from "./error";
|
|
4
|
+
export { createProcedure, executeProcedure } from "./procedure";
|
|
5
|
+
export { createRouter, mutation, query, RouterImpl, subscription } from "./router";
|
|
6
|
+
export { createFetchHandler } from "./server";
|
|
7
|
+
export type { ClientMutationMethod, ClientOptions, ClientProcedure, ClientQueryMethod, ClientRouter, ClientSubscriptionMethod, CORSOptions, FetchHandlerOptions, InferProcedureInput, InferProcedureOutput, MiddlewareFn, Procedure, ProcedureOptions, ProcedureRecord, ProcedureType, Router, Router as RPCRouter, RPCErrorCode, RPCResponse, RPCResponseError, RPCResponseSuccess, SubscriptionCallbacks, SubscriptionHandle } from "./types";
|
|
@@ -1058,10 +1058,12 @@ class Signal {
|
|
|
1058
1058
|
_value;
|
|
1059
1059
|
_subscribers = new Set;
|
|
1060
1060
|
_equals;
|
|
1061
|
+
_onSet;
|
|
1061
1062
|
version = 0;
|
|
1062
|
-
constructor(initialValue, equals) {
|
|
1063
|
+
constructor(initialValue, equals, onSet) {
|
|
1063
1064
|
this._value = initialValue;
|
|
1064
1065
|
this._equals = equals ?? Object.is;
|
|
1066
|
+
this._onSet = onSet;
|
|
1065
1067
|
}
|
|
1066
1068
|
get() {
|
|
1067
1069
|
if (currentSubscriber !== null && currentSubscriber.state !== 3 /* DISPOSED */) {
|
|
@@ -1086,6 +1088,9 @@ class Signal {
|
|
|
1086
1088
|
}
|
|
1087
1089
|
this._value = newValue;
|
|
1088
1090
|
this.version++;
|
|
1091
|
+
if (this._onSet) {
|
|
1092
|
+
this._onSet(newValue);
|
|
1093
|
+
}
|
|
1089
1094
|
batch(() => {
|
|
1090
1095
|
this.notify();
|
|
1091
1096
|
});
|
|
@@ -1111,11 +1116,91 @@ class Signal {
|
|
|
1111
1116
|
}
|
|
1112
1117
|
}
|
|
1113
1118
|
}
|
|
1119
|
+
function resolveStorage(storageOption) {
|
|
1120
|
+
if (storageOption && typeof storageOption === "object") {
|
|
1121
|
+
return storageOption;
|
|
1122
|
+
}
|
|
1123
|
+
if (storageOption === "session") {
|
|
1124
|
+
try {
|
|
1125
|
+
if (typeof sessionStorage !== "undefined")
|
|
1126
|
+
return sessionStorage;
|
|
1127
|
+
} catch {}
|
|
1128
|
+
try {
|
|
1129
|
+
if (typeof window !== "undefined" && window.sessionStorage) {
|
|
1130
|
+
return window.sessionStorage;
|
|
1131
|
+
}
|
|
1132
|
+
} catch {}
|
|
1133
|
+
try {
|
|
1134
|
+
if (typeof globalThis !== "undefined" && globalThis.sessionStorage) {
|
|
1135
|
+
return globalThis.sessionStorage;
|
|
1136
|
+
}
|
|
1137
|
+
} catch {}
|
|
1138
|
+
return null;
|
|
1139
|
+
}
|
|
1140
|
+
try {
|
|
1141
|
+
if (typeof localStorage !== "undefined")
|
|
1142
|
+
return localStorage;
|
|
1143
|
+
} catch {}
|
|
1144
|
+
try {
|
|
1145
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
1146
|
+
return window.localStorage;
|
|
1147
|
+
}
|
|
1148
|
+
} catch {}
|
|
1149
|
+
try {
|
|
1150
|
+
if (typeof globalThis !== "undefined" && globalThis.localStorage) {
|
|
1151
|
+
return globalThis.localStorage;
|
|
1152
|
+
}
|
|
1153
|
+
} catch {}
|
|
1154
|
+
return null;
|
|
1155
|
+
}
|
|
1114
1156
|
function signal(initialValue, optionsOrEquals) {
|
|
1115
1157
|
const equals = typeof optionsOrEquals === "function" ? optionsOrEquals : optionsOrEquals?.equals;
|
|
1116
1158
|
const isInternal = typeof optionsOrEquals === "object" ? optionsOrEquals?.internal : false;
|
|
1117
1159
|
const customName = typeof optionsOrEquals === "object" ? optionsOrEquals?.name : undefined;
|
|
1118
|
-
const
|
|
1160
|
+
const persistOption = typeof optionsOrEquals === "object" ? optionsOrEquals?.persist : undefined;
|
|
1161
|
+
const persistConfig = persistOption ? typeof persistOption === "string" ? { key: persistOption } : persistOption : undefined;
|
|
1162
|
+
let effectiveInitial = initialValue;
|
|
1163
|
+
const storage = persistConfig ? resolveStorage(persistConfig.storage) : null;
|
|
1164
|
+
const serialize = persistConfig?.serialize ?? JSON.stringify;
|
|
1165
|
+
const deserialize = persistConfig?.deserialize ?? JSON.parse;
|
|
1166
|
+
if (persistConfig && storage) {
|
|
1167
|
+
try {
|
|
1168
|
+
const stored = storage.getItem(persistConfig.key);
|
|
1169
|
+
if (stored !== null) {
|
|
1170
|
+
effectiveInitial = deserialize(stored);
|
|
1171
|
+
}
|
|
1172
|
+
} catch {}
|
|
1173
|
+
}
|
|
1174
|
+
let isSyncing = false;
|
|
1175
|
+
const onSet = persistConfig && storage ? (val) => {
|
|
1176
|
+
if (isSyncing)
|
|
1177
|
+
return;
|
|
1178
|
+
try {
|
|
1179
|
+
storage.setItem(persistConfig.key, serialize(val));
|
|
1180
|
+
} catch {}
|
|
1181
|
+
} : undefined;
|
|
1182
|
+
const s = new Signal(effectiveInitial, equals, onSet);
|
|
1183
|
+
if (persistConfig && storage && (persistConfig.syncTabs ?? true) && typeof window !== "undefined" && typeof window.addEventListener === "function") {
|
|
1184
|
+
const onStorage = (e) => {
|
|
1185
|
+
if (e.key === persistConfig.key) {
|
|
1186
|
+
try {
|
|
1187
|
+
const nextVal = e.newValue !== null ? deserialize(e.newValue) : initialValue;
|
|
1188
|
+
isSyncing = true;
|
|
1189
|
+
try {
|
|
1190
|
+
s.set(nextVal);
|
|
1191
|
+
} finally {
|
|
1192
|
+
isSyncing = false;
|
|
1193
|
+
}
|
|
1194
|
+
} catch {}
|
|
1195
|
+
}
|
|
1196
|
+
};
|
|
1197
|
+
window.addEventListener("storage", onStorage);
|
|
1198
|
+
if (currentScope) {
|
|
1199
|
+
currentScope.addCleanup(() => {
|
|
1200
|
+
window.removeEventListener("storage", onStorage);
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1119
1204
|
const accessor = (...args) => {
|
|
1120
1205
|
if (args.length === 0) {
|
|
1121
1206
|
return s.get();
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { MiddlewareFn, Procedure, ProcedureOptions, ProcedureType } from "./types";
|
|
2
|
+
export declare function createProcedure<TType extends ProcedureType, TInput = any, TOutput = any, TContext = any>(type: TType, options: ProcedureOptions<TInput, TOutput, TContext>, middlewares?: MiddlewareFn<any, any>[]): Procedure<TType, TInput, TOutput, TContext>;
|
|
3
|
+
export declare function executeProcedure(procedure: Procedure<any, any, any, any>, opts: {
|
|
4
|
+
rawInput: unknown;
|
|
5
|
+
ctx: any;
|
|
6
|
+
req: Request;
|
|
7
|
+
signal: AbortSignal;
|
|
8
|
+
}): Promise<any>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { MiddlewareFn, Procedure, ProcedureOptions, ProcedureRecord, Router } from "./types";
|
|
2
|
+
export declare class RouterImpl<TRecord extends ProcedureRecord = ProcedureRecord, TContext = any> implements Router<TRecord, TContext> {
|
|
3
|
+
_def: {
|
|
4
|
+
record: TRecord;
|
|
5
|
+
middlewares: MiddlewareFn<any, any>[];
|
|
6
|
+
};
|
|
7
|
+
constructor(record?: TRecord, middlewares?: MiddlewareFn<any, any>[]);
|
|
8
|
+
query(name: string, options: any): any;
|
|
9
|
+
mutation(name: string, options: any): any;
|
|
10
|
+
subscription(name: string, options: any): any;
|
|
11
|
+
use<TNewContext = TContext>(middleware: MiddlewareFn<TContext, TNewContext>): Router<TRecord, TNewContext>;
|
|
12
|
+
merge<TPrefix extends string, TSubRecord extends ProcedureRecord>(prefix: TPrefix, router: Router<TSubRecord, TContext>): Router<TRecord & {
|
|
13
|
+
[K in TPrefix]: Router<TSubRecord, TContext>;
|
|
14
|
+
}, TContext>;
|
|
15
|
+
}
|
|
16
|
+
export declare function createRouter<TRecord extends ProcedureRecord = Record<string, never>, TContext = any>(record?: TRecord): Router<TRecord, TContext>;
|
|
17
|
+
export declare function query<TInput = any, TOutput = any, TContext = any>(options: ProcedureOptions<TInput, TOutput, TContext>): Procedure<"query", TInput, TOutput, TContext>;
|
|
18
|
+
export declare function mutation<TInput = any, TOutput = any, TContext = any>(options: ProcedureOptions<TInput, TOutput, TContext>): Procedure<"mutation", TInput, TOutput, TContext>;
|
|
19
|
+
export declare function subscription<TInput = any, TOutput = any, TContext = any>(options: ProcedureOptions<TInput, TOutput, TContext>): Procedure<"subscription", TInput, TOutput, TContext>;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { FetchHandlerOptions, Router } from "./types";
|
|
2
|
+
export declare function matchesRulePattern(pattern: string, urlPath: string, procedurePath: string): boolean;
|
|
3
|
+
export declare function createFetchHandler<TRouter extends Router<any, any>, TContext = any>(options: FetchHandlerOptions<TRouter, TContext>): (request: Request, ...extra: any[]) => Promise<Response>;
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import type { InferSchemaType, SchemaLike, ValidationIssue } from "../form/schema";
|
|
2
|
+
import type { CreateQueryOptions, MutationOptions, MutationResult, QueryResult } from "../query/types";
|
|
3
|
+
export type RPCErrorCode = "BAD_REQUEST" | "UNAUTHORIZED" | "FORBIDDEN" | "NOT_FOUND" | "METHOD_NOT_ALLOWED" | "TIMEOUT" | "CONFLICT" | "UNPROCESSABLE_CONTENT" | "INTERNAL_SERVER_ERROR";
|
|
4
|
+
export type ProcedureType = "query" | "mutation" | "subscription";
|
|
5
|
+
export type MiddlewareFn<TContext = any, TNewContext = TContext> = (opts: {
|
|
6
|
+
ctx: TContext;
|
|
7
|
+
req: Request;
|
|
8
|
+
signal: AbortSignal;
|
|
9
|
+
next: (opts?: {
|
|
10
|
+
ctx?: TNewContext;
|
|
11
|
+
}) => Promise<any>;
|
|
12
|
+
}) => Promise<any>;
|
|
13
|
+
export interface ProcedureOptionsWithInput<TSchema extends SchemaLike<any>, TOutput = any, TContext = any> {
|
|
14
|
+
input: TSchema;
|
|
15
|
+
output?: SchemaLike<TOutput>;
|
|
16
|
+
resolve: (opts: {
|
|
17
|
+
input: InferSchemaType<TSchema>;
|
|
18
|
+
ctx: TContext;
|
|
19
|
+
req: Request;
|
|
20
|
+
signal: AbortSignal;
|
|
21
|
+
}) => Promise<TOutput> | TOutput | AsyncIterable<TOutput>;
|
|
22
|
+
}
|
|
23
|
+
export interface ProcedureOptionsWithoutInput<TOutput = any, TContext = any> {
|
|
24
|
+
input?: undefined;
|
|
25
|
+
output?: SchemaLike<TOutput>;
|
|
26
|
+
resolve: (opts: {
|
|
27
|
+
input: void;
|
|
28
|
+
ctx: TContext;
|
|
29
|
+
req: Request;
|
|
30
|
+
signal: AbortSignal;
|
|
31
|
+
}) => Promise<TOutput> | TOutput | AsyncIterable<TOutput>;
|
|
32
|
+
}
|
|
33
|
+
export type ProcedureOptions<TInput = any, TOutput = any, TContext = any> = {
|
|
34
|
+
input?: SchemaLike<TInput>;
|
|
35
|
+
output?: SchemaLike<TOutput>;
|
|
36
|
+
resolve: (opts: {
|
|
37
|
+
input: TInput;
|
|
38
|
+
ctx: TContext;
|
|
39
|
+
req: Request;
|
|
40
|
+
signal: AbortSignal;
|
|
41
|
+
}) => Promise<TOutput> | TOutput | AsyncIterable<TOutput>;
|
|
42
|
+
};
|
|
43
|
+
export interface Procedure<TType extends ProcedureType = ProcedureType, TInput = any, TOutput = any, TContext = any> {
|
|
44
|
+
type: TType;
|
|
45
|
+
inputSchema?: SchemaLike<TInput>;
|
|
46
|
+
outputSchema?: SchemaLike<TOutput>;
|
|
47
|
+
middlewares: MiddlewareFn<any, any>[];
|
|
48
|
+
resolve: (opts: {
|
|
49
|
+
input: TInput;
|
|
50
|
+
ctx: TContext;
|
|
51
|
+
req: Request;
|
|
52
|
+
signal: AbortSignal;
|
|
53
|
+
}) => Promise<TOutput> | TOutput | AsyncIterable<TOutput>;
|
|
54
|
+
}
|
|
55
|
+
export type ProcedureRecord = Record<string, Procedure<any, any, any, any> | Router<any, any>>;
|
|
56
|
+
export interface Router<TRecord extends ProcedureRecord = ProcedureRecord, TContext = any> {
|
|
57
|
+
_def: {
|
|
58
|
+
record: TRecord;
|
|
59
|
+
middlewares: MiddlewareFn<any, any>[];
|
|
60
|
+
};
|
|
61
|
+
query<TName extends string, TSchema extends SchemaLike<any>, TOutput = any>(name: TName, options: ProcedureOptionsWithInput<TSchema, TOutput, TContext>): Router<TRecord & {
|
|
62
|
+
[K in TName]: Procedure<"query", InferSchemaType<TSchema>, TOutput, TContext>;
|
|
63
|
+
}, TContext>;
|
|
64
|
+
query<TName extends string, TOutput = any>(name: TName, options: ProcedureOptionsWithoutInput<TOutput, TContext>): Router<TRecord & {
|
|
65
|
+
[K in TName]: Procedure<"query", void, TOutput, TContext>;
|
|
66
|
+
}, TContext>;
|
|
67
|
+
mutation<TName extends string, TSchema extends SchemaLike<any>, TOutput = any>(name: TName, options: ProcedureOptionsWithInput<TSchema, TOutput, TContext>): Router<TRecord & {
|
|
68
|
+
[K in TName]: Procedure<"mutation", InferSchemaType<TSchema>, TOutput, TContext>;
|
|
69
|
+
}, TContext>;
|
|
70
|
+
mutation<TName extends string, TOutput = any>(name: TName, options: ProcedureOptionsWithoutInput<TOutput, TContext>): Router<TRecord & {
|
|
71
|
+
[K in TName]: Procedure<"mutation", void, TOutput, TContext>;
|
|
72
|
+
}, TContext>;
|
|
73
|
+
subscription<TName extends string, TSchema extends SchemaLike<any>, TOutput = any>(name: TName, options: ProcedureOptionsWithInput<TSchema, TOutput, TContext>): Router<TRecord & {
|
|
74
|
+
[K in TName]: Procedure<"subscription", InferSchemaType<TSchema>, TOutput, TContext>;
|
|
75
|
+
}, TContext>;
|
|
76
|
+
subscription<TName extends string, TOutput = any>(name: TName, options: ProcedureOptionsWithoutInput<TOutput, TContext>): Router<TRecord & {
|
|
77
|
+
[K in TName]: Procedure<"subscription", void, TOutput, TContext>;
|
|
78
|
+
}, TContext>;
|
|
79
|
+
use<TNewContext = TContext>(middleware: MiddlewareFn<TContext, TNewContext>): Router<TRecord, TNewContext>;
|
|
80
|
+
merge<TPrefix extends string, TSubRecord extends ProcedureRecord>(prefix: TPrefix, router: Router<TSubRecord, TContext>): Router<TRecord & {
|
|
81
|
+
[K in TPrefix]: Router<TSubRecord, TContext>;
|
|
82
|
+
}, TContext>;
|
|
83
|
+
}
|
|
84
|
+
export interface CORSOptions {
|
|
85
|
+
origin?: string | string[] | ((origin: string) => boolean | string);
|
|
86
|
+
methods?: string[];
|
|
87
|
+
allowedHeaders?: string[];
|
|
88
|
+
exposedHeaders?: string[];
|
|
89
|
+
credentials?: boolean;
|
|
90
|
+
maxAge?: number;
|
|
91
|
+
}
|
|
92
|
+
export type DynamicHeadersFn = (req: Request, ctx: any) => Promise<Record<string, string>> | Record<string, string>;
|
|
93
|
+
export type HeadersConfig = Record<string, string> | DynamicHeadersFn;
|
|
94
|
+
export interface RouteRule {
|
|
95
|
+
/**
|
|
96
|
+
* Response headers to attach to all matching requests.
|
|
97
|
+
*/
|
|
98
|
+
headers?: HeadersConfig;
|
|
99
|
+
/**
|
|
100
|
+
* Required request headers. If any are missing, automatically rejects with HTTP 401 Unauthorized.
|
|
101
|
+
*/
|
|
102
|
+
requireHeaders?: string[];
|
|
103
|
+
/**
|
|
104
|
+
* Required query parameters. If missing on GET requests, rejects with HTTP 400 Bad Request.
|
|
105
|
+
*/
|
|
106
|
+
requireParams?: string[];
|
|
107
|
+
/**
|
|
108
|
+
* Custom guard function for matching requests. Return false or throw RPCError to reject.
|
|
109
|
+
*/
|
|
110
|
+
guard?: (opts: {
|
|
111
|
+
req: Request;
|
|
112
|
+
ctx: any;
|
|
113
|
+
path: string;
|
|
114
|
+
}) => Promise<boolean | void> | boolean | void;
|
|
115
|
+
}
|
|
116
|
+
export interface FetchHandlerOptions<TRouter extends Router<any, any> = Router<any, any>, TContext = any> {
|
|
117
|
+
router: TRouter;
|
|
118
|
+
endpoint?: string;
|
|
119
|
+
createContext?: (opts: {
|
|
120
|
+
req: Request;
|
|
121
|
+
extra: any[];
|
|
122
|
+
}) => Promise<TContext> | TContext;
|
|
123
|
+
onError?: (opts: {
|
|
124
|
+
error: any;
|
|
125
|
+
path?: string;
|
|
126
|
+
req: Request;
|
|
127
|
+
}) => void;
|
|
128
|
+
cors?: boolean | CORSOptions;
|
|
129
|
+
securityHeaders?: boolean | Record<string, string>;
|
|
130
|
+
/**
|
|
131
|
+
* Declarative pattern rules matching URL paths or procedure names (e.g. "*", "/api/*", "admin.*").
|
|
132
|
+
* Supports wildcard matching with '*'.
|
|
133
|
+
*/
|
|
134
|
+
rules?: Record<string, RouteRule> | Array<{
|
|
135
|
+
match: string;
|
|
136
|
+
} & RouteRule>;
|
|
137
|
+
}
|
|
138
|
+
export type ClientHeadersRule = Record<string, string> | (() => Promise<Record<string, string>> | Record<string, string>);
|
|
139
|
+
export interface ClientOptions {
|
|
140
|
+
baseUrl: string;
|
|
141
|
+
fetch?: typeof fetch;
|
|
142
|
+
headers?: Record<string, string> | Record<string, ClientHeadersRule> | (() => Promise<Record<string, string>> | Record<string, string>);
|
|
143
|
+
}
|
|
144
|
+
export interface SubscriptionCallbacks<TData = any> {
|
|
145
|
+
onData: (data: TData) => void;
|
|
146
|
+
onError?: (error: any) => void;
|
|
147
|
+
onComplete?: () => void;
|
|
148
|
+
}
|
|
149
|
+
export interface SubscriptionHandle {
|
|
150
|
+
unsubscribe: () => void;
|
|
151
|
+
}
|
|
152
|
+
export type InferProcedureInput<P> = P extends Procedure<any, infer TInput, any, any> ? TInput : void;
|
|
153
|
+
export type InferProcedureOutput<P> = P extends Procedure<any, any, infer TOutput, any> ? TOutput : unknown;
|
|
154
|
+
export type ClientQueryMethod<P> = InferProcedureInput<P> extends void | undefined ? (input?: void, options?: {
|
|
155
|
+
signal?: AbortSignal;
|
|
156
|
+
headers?: Record<string, string>;
|
|
157
|
+
}) => Promise<InferProcedureOutput<P>> : (input: InferProcedureInput<P>, options?: {
|
|
158
|
+
signal?: AbortSignal;
|
|
159
|
+
headers?: Record<string, string>;
|
|
160
|
+
}) => Promise<InferProcedureOutput<P>>;
|
|
161
|
+
export type ClientMutationMethod<P> = InferProcedureInput<P> extends void | undefined ? (input?: void, options?: {
|
|
162
|
+
signal?: AbortSignal;
|
|
163
|
+
headers?: Record<string, string>;
|
|
164
|
+
}) => Promise<InferProcedureOutput<P>> : (input: InferProcedureInput<P>, options?: {
|
|
165
|
+
signal?: AbortSignal;
|
|
166
|
+
headers?: Record<string, string>;
|
|
167
|
+
}) => Promise<InferProcedureOutput<P>>;
|
|
168
|
+
export type ClientSubscriptionMethod<P> = InferProcedureInput<P> extends void | undefined ? (input: void | undefined, callbacks: SubscriptionCallbacks<InferProcedureOutput<P>>) => SubscriptionHandle : (input: InferProcedureInput<P>, callbacks: SubscriptionCallbacks<InferProcedureOutput<P>>) => SubscriptionHandle;
|
|
169
|
+
export type ClientProcedure<P> = P extends Procedure<"query", infer TInput, infer TOutput, any> ? {
|
|
170
|
+
query: ClientQueryMethod<P>;
|
|
171
|
+
createQuery: (input?: TInput | (() => TInput), extra?: Partial<CreateQueryOptions<TOutput, any, TOutput, any>>) => QueryResult<TOutput, any>;
|
|
172
|
+
useQuery: (input?: TInput | (() => TInput), extra?: Partial<CreateQueryOptions<TOutput, any, TOutput, any>>) => QueryResult<TOutput, any>;
|
|
173
|
+
queryKey: (input?: TInput) => unknown[];
|
|
174
|
+
queryOptions: (input?: TInput, extra?: Partial<CreateQueryOptions<TOutput, any, TOutput, any>>) => CreateQueryOptions<TOutput, any, TOutput, any>;
|
|
175
|
+
} : P extends Procedure<"mutation", infer TInput, infer TOutput, any> ? {
|
|
176
|
+
mutate: ClientMutationMethod<P>;
|
|
177
|
+
createMutation: (extra?: Partial<MutationOptions<TOutput, any, TInput, any>>) => MutationResult<TOutput, any, TInput, any>;
|
|
178
|
+
useMutation: (extra?: Partial<MutationOptions<TOutput, any, TInput, any>>) => MutationResult<TOutput, any, TInput, any>;
|
|
179
|
+
mutationKey: () => unknown[];
|
|
180
|
+
mutationOptions: (extra?: Partial<MutationOptions<TOutput, any, TInput, any>>) => MutationOptions<TOutput, any, TInput, any>;
|
|
181
|
+
} : P extends Procedure<"subscription", any, any, any> ? {
|
|
182
|
+
subscribe: ClientSubscriptionMethod<P>;
|
|
183
|
+
} : never;
|
|
184
|
+
export type ClientRouter<R> = R extends Router<infer TRecord, any> ? {
|
|
185
|
+
[K in keyof TRecord]: TRecord[K] extends Procedure<any, any, any, any> ? ClientProcedure<TRecord[K]> : TRecord[K] extends Router<any, any> ? ClientRouter<TRecord[K]> : never;
|
|
186
|
+
} : never;
|
|
187
|
+
export interface RPCResponseSuccess<T = any> {
|
|
188
|
+
result: {
|
|
189
|
+
data: T;
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
export interface RPCResponseError {
|
|
193
|
+
error: {
|
|
194
|
+
code: RPCErrorCode;
|
|
195
|
+
message: string;
|
|
196
|
+
issues?: ValidationIssue[];
|
|
197
|
+
data?: any;
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
export type RPCResponse<T = any> = RPCResponseSuccess<T> | RPCResponseError;
|