@kontsedal/olas-core 0.0.1-rc.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/LICENSE +21 -0
- package/README.md +64 -0
- package/dist/index.cjs +363 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +178 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +178 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +339 -0
- package/dist/index.mjs.map +1 -0
- package/dist/root-BImHnGj1.mjs +3270 -0
- package/dist/root-BImHnGj1.mjs.map +1 -0
- package/dist/root-Bazp5_Ik.cjs +3347 -0
- package/dist/root-Bazp5_Ik.cjs.map +1 -0
- package/dist/testing.cjs +81 -0
- package/dist/testing.cjs.map +1 -0
- package/dist/testing.d.cts +56 -0
- package/dist/testing.d.cts.map +1 -0
- package/dist/testing.d.mts +56 -0
- package/dist/testing.d.mts.map +1 -0
- package/dist/testing.mjs +78 -0
- package/dist/testing.mjs.map +1 -0
- package/dist/types-CAMgqCMz.d.mts +816 -0
- package/dist/types-CAMgqCMz.d.mts.map +1 -0
- package/dist/types-emq_lZd7.d.cts +816 -0
- package/dist/types-emq_lZd7.d.cts.map +1 -0
- package/package.json +47 -0
- package/src/__dev__.d.ts +8 -0
- package/src/controller/define.ts +50 -0
- package/src/controller/index.ts +12 -0
- package/src/controller/instance.ts +499 -0
- package/src/controller/root.ts +160 -0
- package/src/controller/types.ts +195 -0
- package/src/devtools.ts +0 -0
- package/src/emitter.ts +79 -0
- package/src/errors.ts +49 -0
- package/src/forms/field.ts +303 -0
- package/src/forms/form-types.ts +130 -0
- package/src/forms/form.ts +640 -0
- package/src/forms/index.ts +2 -0
- package/src/forms/types.ts +1 -0
- package/src/forms/validators.ts +70 -0
- package/src/index.ts +89 -0
- package/src/query/client.ts +934 -0
- package/src/query/define.ts +154 -0
- package/src/query/entry.ts +322 -0
- package/src/query/focus-online.ts +73 -0
- package/src/query/index.ts +3 -0
- package/src/query/infinite.ts +462 -0
- package/src/query/keys.ts +33 -0
- package/src/query/local.ts +113 -0
- package/src/query/mutation.ts +384 -0
- package/src/query/plugin.ts +135 -0
- package/src/query/types.ts +168 -0
- package/src/query/use.ts +321 -0
- package/src/scope.ts +42 -0
- package/src/selection.ts +146 -0
- package/src/signals/index.ts +3 -0
- package/src/signals/readonly.ts +22 -0
- package/src/signals/runtime.ts +115 -0
- package/src/signals/types.ts +31 -0
- package/src/testing.ts +142 -0
- package/src/timing/debounced.ts +32 -0
- package/src/timing/index.ts +2 -0
- package/src/timing/throttled.ts +46 -0
- package/src/utils.ts +13 -0
package/dist/testing.cjs
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_root = require("./root-Bazp5_Ik.cjs");
|
|
3
|
+
//#region src/testing.ts
|
|
4
|
+
/**
|
|
5
|
+
* Construct an isolated root wrapping a single controller. The returned object
|
|
6
|
+
* is the controller's api plus the standard Root lifecycle controls
|
|
7
|
+
* (`dispose`, `suspend`, `resume`, `__debug`).
|
|
8
|
+
*
|
|
9
|
+
* Equivalent to defining a tiny root wrapper, but ergonomic in tests.
|
|
10
|
+
*/
|
|
11
|
+
function createTestController(def, options) {
|
|
12
|
+
return require_root.createRootWithProps(def, options.props, {
|
|
13
|
+
deps: options.deps,
|
|
14
|
+
onError: options.onError
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Shape-correct fake `Field<T>` for UI tests. Pass an initial value plus any
|
|
19
|
+
* overrides for the read-only signals. The returned object satisfies `Field<T>`
|
|
20
|
+
* so it can be passed straight into `useField(...)` or any component that
|
|
21
|
+
* accepts a real field. See spec §20.10.
|
|
22
|
+
*/
|
|
23
|
+
function fakeField(initial, overrides) {
|
|
24
|
+
const value$ = require_root.signal(initial);
|
|
25
|
+
const errors$ = require_root.signal(overrides?.errors ?? []);
|
|
26
|
+
const touched$ = require_root.signal(overrides?.touched ?? false);
|
|
27
|
+
const dirty$ = require_root.signal(overrides?.isDirty ?? false);
|
|
28
|
+
const validating$ = require_root.signal(overrides?.isValidating ?? false);
|
|
29
|
+
const isValid$ = overrides?.isValid !== void 0 ? require_root.signal(overrides.isValid) : require_root.computed(() => errors$.value.length === 0 && !validating$.value);
|
|
30
|
+
let currentInitial = initial;
|
|
31
|
+
return {
|
|
32
|
+
get value() {
|
|
33
|
+
return value$.value;
|
|
34
|
+
},
|
|
35
|
+
peek: () => value$.peek(),
|
|
36
|
+
subscribe: (handler) => value$.subscribe(handler),
|
|
37
|
+
errors: errors$,
|
|
38
|
+
isValid: isValid$,
|
|
39
|
+
isDirty: dirty$,
|
|
40
|
+
touched: touched$,
|
|
41
|
+
isValidating: validating$,
|
|
42
|
+
set: overrides?.set ?? ((next) => value$.set(next)),
|
|
43
|
+
setAsInitial: overrides?.setAsInitial ?? ((next) => {
|
|
44
|
+
currentInitial = next;
|
|
45
|
+
value$.set(next);
|
|
46
|
+
dirty$.set(false);
|
|
47
|
+
}),
|
|
48
|
+
reset: overrides?.reset ?? (() => value$.set(currentInitial)),
|
|
49
|
+
markTouched: overrides?.markTouched ?? (() => touched$.set(true)),
|
|
50
|
+
revalidate: overrides?.revalidate ?? (async () => errors$.peek().length === 0),
|
|
51
|
+
dispose: overrides?.dispose ?? (() => {})
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Shape-correct fake `AsyncState<T>` for UI tests. Pass overrides for any of
|
|
56
|
+
* the signal-backed properties; everything else falls back to inert defaults.
|
|
57
|
+
* The returned object satisfies `AsyncState<T>` so it can stand in for a real
|
|
58
|
+
* query subscription in component tests. See spec §20.10.
|
|
59
|
+
*/
|
|
60
|
+
function fakeAsyncState(overrides) {
|
|
61
|
+
const data$ = require_root.signal(overrides?.data);
|
|
62
|
+
return {
|
|
63
|
+
data: data$,
|
|
64
|
+
error: require_root.signal(overrides?.error),
|
|
65
|
+
status: require_root.signal(overrides?.status ?? (overrides?.data !== void 0 ? "success" : "idle")),
|
|
66
|
+
isLoading: require_root.signal(overrides?.isLoading ?? false),
|
|
67
|
+
isFetching: require_root.signal(overrides?.isFetching ?? false),
|
|
68
|
+
isStale: require_root.signal(overrides?.isStale ?? false),
|
|
69
|
+
lastUpdatedAt: require_root.signal(overrides?.lastUpdatedAt),
|
|
70
|
+
hasPendingMutations: require_root.signal(overrides?.hasPendingMutations ?? false),
|
|
71
|
+
refetch: overrides?.refetch ?? (async () => data$.peek()),
|
|
72
|
+
reset: overrides?.reset ?? (() => {}),
|
|
73
|
+
firstValue: overrides?.firstValue ?? (async () => data$.peek())
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//#endregion
|
|
77
|
+
exports.createTestController = createTestController;
|
|
78
|
+
exports.fakeAsyncState = fakeAsyncState;
|
|
79
|
+
exports.fakeField = fakeField;
|
|
80
|
+
|
|
81
|
+
//# sourceMappingURL=testing.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.cjs","names":["createRootWithProps","signal","computed"],"sources":["../src/testing.ts"],"sourcesContent":["import { createRootWithProps } from './controller/root'\nimport type { ControllerDef, Field, Root, RootOptions } from './controller/types'\nimport type { AsyncState, AsyncStatus } from './query/types'\nimport { computed, type ReadSignal, type Signal, signal } from './signals'\n\n/**\n * Construct an isolated root wrapping a single controller. The returned object\n * is the controller's api plus the standard Root lifecycle controls\n * (`dispose`, `suspend`, `resume`, `__debug`).\n *\n * Equivalent to defining a tiny root wrapper, but ergonomic in tests.\n */\nexport function createTestController<\n Props,\n Api,\n TDeps extends Record<string, unknown> = Record<string, unknown>,\n>(\n def: ControllerDef<Props, Api>,\n options: {\n deps: TDeps\n props: Props\n onError?: RootOptions<TDeps>['onError']\n },\n): Root<Api> {\n return createRootWithProps<Props, Api, TDeps>(def, options.props, {\n deps: options.deps,\n onError: options.onError,\n })\n}\n\n/**\n * Shape-correct fake `Field<T>` for UI tests. Pass an initial value plus any\n * overrides for the read-only signals. The returned object satisfies `Field<T>`\n * so it can be passed straight into `useField(...)` or any component that\n * accepts a real field. See spec §20.10.\n */\nexport function fakeField<T>(\n initial: T,\n overrides?: Partial<{\n errors: string[]\n isValid: boolean\n isDirty: boolean\n touched: boolean\n isValidating: boolean\n set: (value: T) => void\n setAsInitial: (value: T) => void\n reset: () => void\n markTouched: () => void\n revalidate: () => Promise<boolean>\n dispose: () => void\n }>,\n): Field<T> {\n const value$: Signal<T> = signal(initial)\n const errors$: Signal<string[]> = signal(overrides?.errors ?? [])\n const touched$: Signal<boolean> = signal(overrides?.touched ?? false)\n const dirty$: Signal<boolean> = signal(overrides?.isDirty ?? false)\n const validating$: Signal<boolean> = signal(overrides?.isValidating ?? false)\n const isValid$: ReadSignal<boolean> =\n overrides?.isValid !== undefined\n ? signal(overrides.isValid)\n : computed(() => errors$.value.length === 0 && !validating$.value)\n\n let currentInitial = initial\n const set = overrides?.set ?? ((next: T) => value$.set(next))\n const setAsInitial =\n overrides?.setAsInitial ??\n ((next: T) => {\n currentInitial = next\n value$.set(next)\n dirty$.set(false)\n })\n const fake: Field<T> = {\n get value() {\n return value$.value\n },\n peek: () => value$.peek(),\n subscribe: (handler) => value$.subscribe(handler),\n errors: errors$,\n isValid: isValid$,\n isDirty: dirty$,\n touched: touched$,\n isValidating: validating$,\n set,\n setAsInitial,\n reset: overrides?.reset ?? (() => value$.set(currentInitial)),\n markTouched: overrides?.markTouched ?? (() => touched$.set(true)),\n revalidate: overrides?.revalidate ?? (async () => errors$.peek().length === 0),\n dispose: overrides?.dispose ?? (() => {}),\n }\n return fake\n}\n\n/**\n * Shape-correct fake `AsyncState<T>` for UI tests. Pass overrides for any of\n * the signal-backed properties; everything else falls back to inert defaults.\n * The returned object satisfies `AsyncState<T>` so it can stand in for a real\n * query subscription in component tests. See spec §20.10.\n */\nexport function fakeAsyncState<T>(\n overrides?: Partial<{\n data: T | undefined\n error: unknown | undefined\n status: AsyncStatus\n isLoading: boolean\n isFetching: boolean\n isStale: boolean\n lastUpdatedAt: number | undefined\n hasPendingMutations: boolean\n refetch: () => Promise<T>\n reset: () => void\n firstValue: () => Promise<T>\n }>,\n): AsyncState<T> {\n const data$: ReadSignal<T | undefined> = signal(overrides?.data)\n const error$: ReadSignal<unknown | undefined> = signal(overrides?.error)\n const status$: ReadSignal<AsyncStatus> = signal(\n overrides?.status ?? (overrides?.data !== undefined ? 'success' : 'idle'),\n )\n const isLoading$: ReadSignal<boolean> = signal(overrides?.isLoading ?? false)\n const isFetching$: ReadSignal<boolean> = signal(overrides?.isFetching ?? false)\n const isStale$: ReadSignal<boolean> = signal(overrides?.isStale ?? false)\n const lastUpdatedAt$: ReadSignal<number | undefined> = signal(overrides?.lastUpdatedAt)\n const hasPendingMutations$: ReadSignal<boolean> = signal(overrides?.hasPendingMutations ?? false)\n\n const refetch = overrides?.refetch ?? (async () => data$.peek() as T)\n const reset = overrides?.reset ?? (() => {})\n const firstValue = overrides?.firstValue ?? (async () => data$.peek() as T)\n\n return {\n data: data$,\n error: error$,\n status: status$,\n isLoading: isLoading$,\n isFetching: isFetching$,\n isStale: isStale$,\n lastUpdatedAt: lastUpdatedAt$,\n hasPendingMutations: hasPendingMutations$,\n refetch,\n reset,\n firstValue,\n }\n}\n"],"mappings":";;;;;;;;;;AAYA,SAAgB,qBAKd,KACA,SAKW;CACX,OAAOA,aAAAA,oBAAuC,KAAK,QAAQ,OAAO;EAChE,MAAM,QAAQ;EACd,SAAS,QAAQ;CACnB,CAAC;AACH;;;;;;;AAQA,SAAgB,UACd,SACA,WAaU;CACV,MAAM,SAAoBC,aAAAA,OAAO,OAAO;CACxC,MAAM,UAA4BA,aAAAA,OAAO,WAAW,UAAU,CAAC,CAAC;CAChE,MAAM,WAA4BA,aAAAA,OAAO,WAAW,WAAW,KAAK;CACpE,MAAM,SAA0BA,aAAAA,OAAO,WAAW,WAAW,KAAK;CAClE,MAAM,cAA+BA,aAAAA,OAAO,WAAW,gBAAgB,KAAK;CAC5E,MAAM,WACJ,WAAW,YAAY,KAAA,IACnBA,aAAAA,OAAO,UAAU,OAAO,IACxBC,aAAAA,eAAe,QAAQ,MAAM,WAAW,KAAK,CAAC,YAAY,KAAK;CAErE,IAAI,iBAAiB;CA2BrB,OAAO;EAjBL,IAAI,QAAQ;GACV,OAAO,OAAO;EAChB;EACA,YAAY,OAAO,KAAK;EACxB,YAAY,YAAY,OAAO,UAAU,OAAO;EAChD,QAAQ;EACR,SAAS;EACT,SAAS;EACT,SAAS;EACT,cAAc;EACd,KAnBU,WAAW,SAAS,SAAY,OAAO,IAAI,IAAI;EAoBzD,cAlBA,WAAW,kBACT,SAAY;GACZ,iBAAiB;GACjB,OAAO,IAAI,IAAI;GACf,OAAO,IAAI,KAAK;EAClB;EAcA,OAAO,WAAW,gBAAgB,OAAO,IAAI,cAAc;EAC3D,aAAa,WAAW,sBAAsB,SAAS,IAAI,IAAI;EAC/D,YAAY,WAAW,eAAe,YAAY,QAAQ,KAAK,EAAE,WAAW;EAC5E,SAAS,WAAW,kBAAkB,CAAC;CAE/B;AACZ;;;;;;;AAQA,SAAgB,eACd,WAae;CACf,MAAM,QAAmCD,aAAAA,OAAO,WAAW,IAAI;CAe/D,OAAO;EACL,MAAM;EACN,OAhB8CA,aAAAA,OAAO,WAAW,KAgBpD;EACZ,QAhBuCA,aAAAA,OACvC,WAAW,WAAW,WAAW,SAAS,KAAA,IAAY,YAAY,OAepD;EACd,WAdsCA,aAAAA,OAAO,WAAW,aAAa,KAcjD;EACpB,YAduCA,aAAAA,OAAO,WAAW,cAAc,KAcjD;EACtB,SAdoCA,aAAAA,OAAO,WAAW,WAAW,KAcjD;EAChB,eAdqDA,aAAAA,OAAO,WAAW,aAc3C;EAC5B,qBAdgDA,aAAAA,OAAO,WAAW,uBAAuB,KAcjD;EACxC,SAbc,WAAW,YAAY,YAAY,MAAM,KAAK;EAc5D,OAbY,WAAW,gBAAgB,CAAC;EAcxC,YAbiB,WAAW,eAAe,YAAY,MAAM,KAAK;CAcpE;AACF"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { O as AsyncState, c as RootOptions, k as AsyncStatus, n as ControllerDef, o as Field, s as Root } from "./types-emq_lZd7.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/testing.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Construct an isolated root wrapping a single controller. The returned object
|
|
6
|
+
* is the controller's api plus the standard Root lifecycle controls
|
|
7
|
+
* (`dispose`, `suspend`, `resume`, `__debug`).
|
|
8
|
+
*
|
|
9
|
+
* Equivalent to defining a tiny root wrapper, but ergonomic in tests.
|
|
10
|
+
*/
|
|
11
|
+
declare function createTestController<Props, Api, TDeps extends Record<string, unknown> = Record<string, unknown>>(def: ControllerDef<Props, Api>, options: {
|
|
12
|
+
deps: TDeps;
|
|
13
|
+
props: Props;
|
|
14
|
+
onError?: RootOptions<TDeps>['onError'];
|
|
15
|
+
}): Root<Api>;
|
|
16
|
+
/**
|
|
17
|
+
* Shape-correct fake `Field<T>` for UI tests. Pass an initial value plus any
|
|
18
|
+
* overrides for the read-only signals. The returned object satisfies `Field<T>`
|
|
19
|
+
* so it can be passed straight into `useField(...)` or any component that
|
|
20
|
+
* accepts a real field. See spec §20.10.
|
|
21
|
+
*/
|
|
22
|
+
declare function fakeField<T>(initial: T, overrides?: Partial<{
|
|
23
|
+
errors: string[];
|
|
24
|
+
isValid: boolean;
|
|
25
|
+
isDirty: boolean;
|
|
26
|
+
touched: boolean;
|
|
27
|
+
isValidating: boolean;
|
|
28
|
+
set: (value: T) => void;
|
|
29
|
+
setAsInitial: (value: T) => void;
|
|
30
|
+
reset: () => void;
|
|
31
|
+
markTouched: () => void;
|
|
32
|
+
revalidate: () => Promise<boolean>;
|
|
33
|
+
dispose: () => void;
|
|
34
|
+
}>): Field<T>;
|
|
35
|
+
/**
|
|
36
|
+
* Shape-correct fake `AsyncState<T>` for UI tests. Pass overrides for any of
|
|
37
|
+
* the signal-backed properties; everything else falls back to inert defaults.
|
|
38
|
+
* The returned object satisfies `AsyncState<T>` so it can stand in for a real
|
|
39
|
+
* query subscription in component tests. See spec §20.10.
|
|
40
|
+
*/
|
|
41
|
+
declare function fakeAsyncState<T>(overrides?: Partial<{
|
|
42
|
+
data: T | undefined;
|
|
43
|
+
error: unknown | undefined;
|
|
44
|
+
status: AsyncStatus;
|
|
45
|
+
isLoading: boolean;
|
|
46
|
+
isFetching: boolean;
|
|
47
|
+
isStale: boolean;
|
|
48
|
+
lastUpdatedAt: number | undefined;
|
|
49
|
+
hasPendingMutations: boolean;
|
|
50
|
+
refetch: () => Promise<T>;
|
|
51
|
+
reset: () => void;
|
|
52
|
+
firstValue: () => Promise<T>;
|
|
53
|
+
}>): AsyncState<T>;
|
|
54
|
+
//#endregion
|
|
55
|
+
export { createTestController, fakeAsyncState, fakeField };
|
|
56
|
+
//# sourceMappingURL=testing.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.d.cts","names":[],"sources":["../src/testing.ts"],"mappings":";;;;AAYA;;;;;;iBAAgB,oBAAA,2BAGA,MAAA,oBAA0B,MAAA,kBAAA,CAExC,GAAA,EAAK,aAAA,CAAc,KAAA,EAAO,GAAA,GAC1B,OAAA;EACE,IAAA,EAAM,KAAA;EACN,KAAA,EAAO,KAAA;EACP,OAAA,GAAU,WAAA,CAAY,KAAA;AAAA,IAEvB,IAAA,CAAK,GAAA;;;;;;;iBAaQ,SAAA,GAAA,CACd,OAAA,EAAS,CAAA,EACT,SAAA,GAAY,OAAA;EACV,MAAA;EACA,OAAA;EACA,OAAA;EACA,OAAA;EACA,YAAA;EACA,GAAA,GAAM,KAAA,EAAO,CAAA;EACb,YAAA,GAAe,KAAA,EAAO,CAAA;EACtB,KAAA;EACA,WAAA;EACA,UAAA,QAAkB,OAAA;EAClB,OAAA;AAAA,KAED,KAAA,CAAM,CAAA;;;;;;;iBA+CO,cAAA,GAAA,CACd,SAAA,GAAY,OAAA;EACV,IAAA,EAAM,CAAA;EACN,KAAA;EACA,MAAA,EAAQ,WAAA;EACR,SAAA;EACA,UAAA;EACA,OAAA;EACA,aAAA;EACA,mBAAA;EACA,OAAA,QAAe,OAAA,CAAQ,CAAA;EACvB,KAAA;EACA,UAAA,QAAkB,OAAA,CAAQ,CAAA;AAAA,KAE3B,UAAA,CAAW,CAAA"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { O as AsyncState, c as RootOptions, k as AsyncStatus, n as ControllerDef, o as Field, s as Root } from "./types-CAMgqCMz.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/testing.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Construct an isolated root wrapping a single controller. The returned object
|
|
6
|
+
* is the controller's api plus the standard Root lifecycle controls
|
|
7
|
+
* (`dispose`, `suspend`, `resume`, `__debug`).
|
|
8
|
+
*
|
|
9
|
+
* Equivalent to defining a tiny root wrapper, but ergonomic in tests.
|
|
10
|
+
*/
|
|
11
|
+
declare function createTestController<Props, Api, TDeps extends Record<string, unknown> = Record<string, unknown>>(def: ControllerDef<Props, Api>, options: {
|
|
12
|
+
deps: TDeps;
|
|
13
|
+
props: Props;
|
|
14
|
+
onError?: RootOptions<TDeps>['onError'];
|
|
15
|
+
}): Root<Api>;
|
|
16
|
+
/**
|
|
17
|
+
* Shape-correct fake `Field<T>` for UI tests. Pass an initial value plus any
|
|
18
|
+
* overrides for the read-only signals. The returned object satisfies `Field<T>`
|
|
19
|
+
* so it can be passed straight into `useField(...)` or any component that
|
|
20
|
+
* accepts a real field. See spec §20.10.
|
|
21
|
+
*/
|
|
22
|
+
declare function fakeField<T>(initial: T, overrides?: Partial<{
|
|
23
|
+
errors: string[];
|
|
24
|
+
isValid: boolean;
|
|
25
|
+
isDirty: boolean;
|
|
26
|
+
touched: boolean;
|
|
27
|
+
isValidating: boolean;
|
|
28
|
+
set: (value: T) => void;
|
|
29
|
+
setAsInitial: (value: T) => void;
|
|
30
|
+
reset: () => void;
|
|
31
|
+
markTouched: () => void;
|
|
32
|
+
revalidate: () => Promise<boolean>;
|
|
33
|
+
dispose: () => void;
|
|
34
|
+
}>): Field<T>;
|
|
35
|
+
/**
|
|
36
|
+
* Shape-correct fake `AsyncState<T>` for UI tests. Pass overrides for any of
|
|
37
|
+
* the signal-backed properties; everything else falls back to inert defaults.
|
|
38
|
+
* The returned object satisfies `AsyncState<T>` so it can stand in for a real
|
|
39
|
+
* query subscription in component tests. See spec §20.10.
|
|
40
|
+
*/
|
|
41
|
+
declare function fakeAsyncState<T>(overrides?: Partial<{
|
|
42
|
+
data: T | undefined;
|
|
43
|
+
error: unknown | undefined;
|
|
44
|
+
status: AsyncStatus;
|
|
45
|
+
isLoading: boolean;
|
|
46
|
+
isFetching: boolean;
|
|
47
|
+
isStale: boolean;
|
|
48
|
+
lastUpdatedAt: number | undefined;
|
|
49
|
+
hasPendingMutations: boolean;
|
|
50
|
+
refetch: () => Promise<T>;
|
|
51
|
+
reset: () => void;
|
|
52
|
+
firstValue: () => Promise<T>;
|
|
53
|
+
}>): AsyncState<T>;
|
|
54
|
+
//#endregion
|
|
55
|
+
export { createTestController, fakeAsyncState, fakeField };
|
|
56
|
+
//# sourceMappingURL=testing.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.d.mts","names":[],"sources":["../src/testing.ts"],"mappings":";;;;AAYA;;;;;;iBAAgB,oBAAA,2BAGA,MAAA,oBAA0B,MAAA,kBAAA,CAExC,GAAA,EAAK,aAAA,CAAc,KAAA,EAAO,GAAA,GAC1B,OAAA;EACE,IAAA,EAAM,KAAA;EACN,KAAA,EAAO,KAAA;EACP,OAAA,GAAU,WAAA,CAAY,KAAA;AAAA,IAEvB,IAAA,CAAK,GAAA;;;;;;;iBAaQ,SAAA,GAAA,CACd,OAAA,EAAS,CAAA,EACT,SAAA,GAAY,OAAA;EACV,MAAA;EACA,OAAA;EACA,OAAA;EACA,OAAA;EACA,YAAA;EACA,GAAA,GAAM,KAAA,EAAO,CAAA;EACb,YAAA,GAAe,KAAA,EAAO,CAAA;EACtB,KAAA;EACA,WAAA;EACA,UAAA,QAAkB,OAAA;EAClB,OAAA;AAAA,KAED,KAAA,CAAM,CAAA;;;;;;;iBA+CO,cAAA,GAAA,CACd,SAAA,GAAY,OAAA;EACV,IAAA,EAAM,CAAA;EACN,KAAA;EACA,MAAA,EAAQ,WAAA;EACR,SAAA;EACA,UAAA;EACA,OAAA;EACA,aAAA;EACA,mBAAA;EACA,OAAA,QAAe,OAAA,CAAQ,CAAA;EACvB,KAAA;EACA,UAAA,QAAkB,OAAA,CAAQ,CAAA;AAAA,KAE3B,UAAA,CAAW,CAAA"}
|
package/dist/testing.mjs
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { d as signal, l as computed, n as createRootWithProps } from "./root-BImHnGj1.mjs";
|
|
2
|
+
//#region src/testing.ts
|
|
3
|
+
/**
|
|
4
|
+
* Construct an isolated root wrapping a single controller. The returned object
|
|
5
|
+
* is the controller's api plus the standard Root lifecycle controls
|
|
6
|
+
* (`dispose`, `suspend`, `resume`, `__debug`).
|
|
7
|
+
*
|
|
8
|
+
* Equivalent to defining a tiny root wrapper, but ergonomic in tests.
|
|
9
|
+
*/
|
|
10
|
+
function createTestController(def, options) {
|
|
11
|
+
return createRootWithProps(def, options.props, {
|
|
12
|
+
deps: options.deps,
|
|
13
|
+
onError: options.onError
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Shape-correct fake `Field<T>` for UI tests. Pass an initial value plus any
|
|
18
|
+
* overrides for the read-only signals. The returned object satisfies `Field<T>`
|
|
19
|
+
* so it can be passed straight into `useField(...)` or any component that
|
|
20
|
+
* accepts a real field. See spec §20.10.
|
|
21
|
+
*/
|
|
22
|
+
function fakeField(initial, overrides) {
|
|
23
|
+
const value$ = signal(initial);
|
|
24
|
+
const errors$ = signal(overrides?.errors ?? []);
|
|
25
|
+
const touched$ = signal(overrides?.touched ?? false);
|
|
26
|
+
const dirty$ = signal(overrides?.isDirty ?? false);
|
|
27
|
+
const validating$ = signal(overrides?.isValidating ?? false);
|
|
28
|
+
const isValid$ = overrides?.isValid !== void 0 ? signal(overrides.isValid) : computed(() => errors$.value.length === 0 && !validating$.value);
|
|
29
|
+
let currentInitial = initial;
|
|
30
|
+
return {
|
|
31
|
+
get value() {
|
|
32
|
+
return value$.value;
|
|
33
|
+
},
|
|
34
|
+
peek: () => value$.peek(),
|
|
35
|
+
subscribe: (handler) => value$.subscribe(handler),
|
|
36
|
+
errors: errors$,
|
|
37
|
+
isValid: isValid$,
|
|
38
|
+
isDirty: dirty$,
|
|
39
|
+
touched: touched$,
|
|
40
|
+
isValidating: validating$,
|
|
41
|
+
set: overrides?.set ?? ((next) => value$.set(next)),
|
|
42
|
+
setAsInitial: overrides?.setAsInitial ?? ((next) => {
|
|
43
|
+
currentInitial = next;
|
|
44
|
+
value$.set(next);
|
|
45
|
+
dirty$.set(false);
|
|
46
|
+
}),
|
|
47
|
+
reset: overrides?.reset ?? (() => value$.set(currentInitial)),
|
|
48
|
+
markTouched: overrides?.markTouched ?? (() => touched$.set(true)),
|
|
49
|
+
revalidate: overrides?.revalidate ?? (async () => errors$.peek().length === 0),
|
|
50
|
+
dispose: overrides?.dispose ?? (() => {})
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Shape-correct fake `AsyncState<T>` for UI tests. Pass overrides for any of
|
|
55
|
+
* the signal-backed properties; everything else falls back to inert defaults.
|
|
56
|
+
* The returned object satisfies `AsyncState<T>` so it can stand in for a real
|
|
57
|
+
* query subscription in component tests. See spec §20.10.
|
|
58
|
+
*/
|
|
59
|
+
function fakeAsyncState(overrides) {
|
|
60
|
+
const data$ = signal(overrides?.data);
|
|
61
|
+
return {
|
|
62
|
+
data: data$,
|
|
63
|
+
error: signal(overrides?.error),
|
|
64
|
+
status: signal(overrides?.status ?? (overrides?.data !== void 0 ? "success" : "idle")),
|
|
65
|
+
isLoading: signal(overrides?.isLoading ?? false),
|
|
66
|
+
isFetching: signal(overrides?.isFetching ?? false),
|
|
67
|
+
isStale: signal(overrides?.isStale ?? false),
|
|
68
|
+
lastUpdatedAt: signal(overrides?.lastUpdatedAt),
|
|
69
|
+
hasPendingMutations: signal(overrides?.hasPendingMutations ?? false),
|
|
70
|
+
refetch: overrides?.refetch ?? (async () => data$.peek()),
|
|
71
|
+
reset: overrides?.reset ?? (() => {}),
|
|
72
|
+
firstValue: overrides?.firstValue ?? (async () => data$.peek())
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
//#endregion
|
|
76
|
+
export { createTestController, fakeAsyncState, fakeField };
|
|
77
|
+
|
|
78
|
+
//# sourceMappingURL=testing.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.mjs","names":[],"sources":["../src/testing.ts"],"sourcesContent":["import { createRootWithProps } from './controller/root'\nimport type { ControllerDef, Field, Root, RootOptions } from './controller/types'\nimport type { AsyncState, AsyncStatus } from './query/types'\nimport { computed, type ReadSignal, type Signal, signal } from './signals'\n\n/**\n * Construct an isolated root wrapping a single controller. The returned object\n * is the controller's api plus the standard Root lifecycle controls\n * (`dispose`, `suspend`, `resume`, `__debug`).\n *\n * Equivalent to defining a tiny root wrapper, but ergonomic in tests.\n */\nexport function createTestController<\n Props,\n Api,\n TDeps extends Record<string, unknown> = Record<string, unknown>,\n>(\n def: ControllerDef<Props, Api>,\n options: {\n deps: TDeps\n props: Props\n onError?: RootOptions<TDeps>['onError']\n },\n): Root<Api> {\n return createRootWithProps<Props, Api, TDeps>(def, options.props, {\n deps: options.deps,\n onError: options.onError,\n })\n}\n\n/**\n * Shape-correct fake `Field<T>` for UI tests. Pass an initial value plus any\n * overrides for the read-only signals. The returned object satisfies `Field<T>`\n * so it can be passed straight into `useField(...)` or any component that\n * accepts a real field. See spec §20.10.\n */\nexport function fakeField<T>(\n initial: T,\n overrides?: Partial<{\n errors: string[]\n isValid: boolean\n isDirty: boolean\n touched: boolean\n isValidating: boolean\n set: (value: T) => void\n setAsInitial: (value: T) => void\n reset: () => void\n markTouched: () => void\n revalidate: () => Promise<boolean>\n dispose: () => void\n }>,\n): Field<T> {\n const value$: Signal<T> = signal(initial)\n const errors$: Signal<string[]> = signal(overrides?.errors ?? [])\n const touched$: Signal<boolean> = signal(overrides?.touched ?? false)\n const dirty$: Signal<boolean> = signal(overrides?.isDirty ?? false)\n const validating$: Signal<boolean> = signal(overrides?.isValidating ?? false)\n const isValid$: ReadSignal<boolean> =\n overrides?.isValid !== undefined\n ? signal(overrides.isValid)\n : computed(() => errors$.value.length === 0 && !validating$.value)\n\n let currentInitial = initial\n const set = overrides?.set ?? ((next: T) => value$.set(next))\n const setAsInitial =\n overrides?.setAsInitial ??\n ((next: T) => {\n currentInitial = next\n value$.set(next)\n dirty$.set(false)\n })\n const fake: Field<T> = {\n get value() {\n return value$.value\n },\n peek: () => value$.peek(),\n subscribe: (handler) => value$.subscribe(handler),\n errors: errors$,\n isValid: isValid$,\n isDirty: dirty$,\n touched: touched$,\n isValidating: validating$,\n set,\n setAsInitial,\n reset: overrides?.reset ?? (() => value$.set(currentInitial)),\n markTouched: overrides?.markTouched ?? (() => touched$.set(true)),\n revalidate: overrides?.revalidate ?? (async () => errors$.peek().length === 0),\n dispose: overrides?.dispose ?? (() => {}),\n }\n return fake\n}\n\n/**\n * Shape-correct fake `AsyncState<T>` for UI tests. Pass overrides for any of\n * the signal-backed properties; everything else falls back to inert defaults.\n * The returned object satisfies `AsyncState<T>` so it can stand in for a real\n * query subscription in component tests. See spec §20.10.\n */\nexport function fakeAsyncState<T>(\n overrides?: Partial<{\n data: T | undefined\n error: unknown | undefined\n status: AsyncStatus\n isLoading: boolean\n isFetching: boolean\n isStale: boolean\n lastUpdatedAt: number | undefined\n hasPendingMutations: boolean\n refetch: () => Promise<T>\n reset: () => void\n firstValue: () => Promise<T>\n }>,\n): AsyncState<T> {\n const data$: ReadSignal<T | undefined> = signal(overrides?.data)\n const error$: ReadSignal<unknown | undefined> = signal(overrides?.error)\n const status$: ReadSignal<AsyncStatus> = signal(\n overrides?.status ?? (overrides?.data !== undefined ? 'success' : 'idle'),\n )\n const isLoading$: ReadSignal<boolean> = signal(overrides?.isLoading ?? false)\n const isFetching$: ReadSignal<boolean> = signal(overrides?.isFetching ?? false)\n const isStale$: ReadSignal<boolean> = signal(overrides?.isStale ?? false)\n const lastUpdatedAt$: ReadSignal<number | undefined> = signal(overrides?.lastUpdatedAt)\n const hasPendingMutations$: ReadSignal<boolean> = signal(overrides?.hasPendingMutations ?? false)\n\n const refetch = overrides?.refetch ?? (async () => data$.peek() as T)\n const reset = overrides?.reset ?? (() => {})\n const firstValue = overrides?.firstValue ?? (async () => data$.peek() as T)\n\n return {\n data: data$,\n error: error$,\n status: status$,\n isLoading: isLoading$,\n isFetching: isFetching$,\n isStale: isStale$,\n lastUpdatedAt: lastUpdatedAt$,\n hasPendingMutations: hasPendingMutations$,\n refetch,\n reset,\n firstValue,\n }\n}\n"],"mappings":";;;;;;;;;AAYA,SAAgB,qBAKd,KACA,SAKW;CACX,OAAO,oBAAuC,KAAK,QAAQ,OAAO;EAChE,MAAM,QAAQ;EACd,SAAS,QAAQ;CACnB,CAAC;AACH;;;;;;;AAQA,SAAgB,UACd,SACA,WAaU;CACV,MAAM,SAAoB,OAAO,OAAO;CACxC,MAAM,UAA4B,OAAO,WAAW,UAAU,CAAC,CAAC;CAChE,MAAM,WAA4B,OAAO,WAAW,WAAW,KAAK;CACpE,MAAM,SAA0B,OAAO,WAAW,WAAW,KAAK;CAClE,MAAM,cAA+B,OAAO,WAAW,gBAAgB,KAAK;CAC5E,MAAM,WACJ,WAAW,YAAY,KAAA,IACnB,OAAO,UAAU,OAAO,IACxB,eAAe,QAAQ,MAAM,WAAW,KAAK,CAAC,YAAY,KAAK;CAErE,IAAI,iBAAiB;CA2BrB,OAAO;EAjBL,IAAI,QAAQ;GACV,OAAO,OAAO;EAChB;EACA,YAAY,OAAO,KAAK;EACxB,YAAY,YAAY,OAAO,UAAU,OAAO;EAChD,QAAQ;EACR,SAAS;EACT,SAAS;EACT,SAAS;EACT,cAAc;EACd,KAnBU,WAAW,SAAS,SAAY,OAAO,IAAI,IAAI;EAoBzD,cAlBA,WAAW,kBACT,SAAY;GACZ,iBAAiB;GACjB,OAAO,IAAI,IAAI;GACf,OAAO,IAAI,KAAK;EAClB;EAcA,OAAO,WAAW,gBAAgB,OAAO,IAAI,cAAc;EAC3D,aAAa,WAAW,sBAAsB,SAAS,IAAI,IAAI;EAC/D,YAAY,WAAW,eAAe,YAAY,QAAQ,KAAK,EAAE,WAAW;EAC5E,SAAS,WAAW,kBAAkB,CAAC;CAE/B;AACZ;;;;;;;AAQA,SAAgB,eACd,WAae;CACf,MAAM,QAAmC,OAAO,WAAW,IAAI;CAe/D,OAAO;EACL,MAAM;EACN,OAhB8C,OAAO,WAAW,KAgBpD;EACZ,QAhBuC,OACvC,WAAW,WAAW,WAAW,SAAS,KAAA,IAAY,YAAY,OAepD;EACd,WAdsC,OAAO,WAAW,aAAa,KAcjD;EACpB,YAduC,OAAO,WAAW,cAAc,KAcjD;EACtB,SAdoC,OAAO,WAAW,WAAW,KAcjD;EAChB,eAdqD,OAAO,WAAW,aAc3C;EAC5B,qBAdgD,OAAO,WAAW,uBAAuB,KAcjD;EACxC,SAbc,WAAW,YAAY,YAAY,MAAM,KAAK;EAc5D,OAbY,WAAW,gBAAgB,CAAC;EAcxC,YAbiB,WAAW,eAAe,YAAY,MAAM,KAAK;CAcpE;AACF"}
|