rask-ui 0.24.0 → 0.24.3
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/asyncState.d.ts +16 -0
- package/dist/asyncState.d.ts.map +1 -0
- package/dist/asyncState.js +24 -0
- package/dist/compiler.d.ts +1 -3
- package/dist/compiler.d.ts.map +1 -1
- package/dist/compiler.js +1 -7
- package/dist/component.d.ts.map +1 -1
- package/dist/component.js +10 -17
- package/dist/context.d.ts +5 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +29 -0
- package/dist/createAsync.test.d.ts +2 -0
- package/dist/createAsync.test.d.ts.map +1 -0
- package/dist/createAsync.test.js +110 -0
- package/dist/createContext.d.ts +1 -1
- package/dist/createContext.d.ts.map +1 -1
- package/dist/createMutation.test.d.ts +2 -0
- package/dist/createMutation.test.d.ts.map +1 -0
- package/dist/createMutation.test.js +168 -0
- package/dist/createQuery.test.d.ts +2 -0
- package/dist/createQuery.test.d.ts.map +1 -0
- package/dist/createQuery.test.js +156 -0
- package/dist/createRef.d.ts +6 -0
- package/dist/createRef.d.ts.map +1 -0
- package/dist/createRef.js +8 -0
- package/dist/createState.d.ts +0 -2
- package/dist/createState.d.ts.map +1 -1
- package/dist/createState.js +5 -40
- package/dist/createState.test.d.ts.map +1 -0
- package/dist/createState.test.js +111 -0
- package/dist/createView.d.ts +44 -18
- package/dist/createView.d.ts.map +1 -1
- package/dist/createView.js +48 -57
- package/dist/createView.test.d.ts.map +1 -0
- package/dist/{tests/createView.test.js → createView.test.js} +40 -40
- package/dist/error.d.ts +14 -3
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +15 -14
- package/dist/jsx.d.ts +256 -10
- package/dist/observation.test.d.ts.map +1 -0
- package/dist/observation.test.js +150 -0
- package/dist/plugin.d.ts +1 -1
- package/dist/plugin.js +3 -3
- package/dist/suspense.d.ts +25 -0
- package/dist/suspense.d.ts.map +1 -0
- package/dist/suspense.js +97 -0
- package/dist/test-setup.d.ts +16 -0
- package/dist/test-setup.d.ts.map +1 -0
- package/dist/test-setup.js +40 -0
- package/dist/test.d.ts +2 -0
- package/dist/test.d.ts.map +1 -0
- package/dist/test.js +24 -0
- package/dist/transformer.d.ts +4 -0
- package/dist/transformer.d.ts.map +1 -0
- package/dist/transformer.js +7 -0
- package/dist/useCatchError.d.ts +1 -1
- package/dist/useCatchError.d.ts.map +1 -1
- package/package.json +4 -4
- package/swc-plugin/target/wasm32-wasip1/release/swc_plugin_rask_component.wasm +0 -0
- package/dist/createComputed.d.ts +0 -4
- package/dist/createComputed.d.ts.map +0 -1
- package/dist/createComputed.js +0 -69
- package/dist/createEffect.d.ts +0 -2
- package/dist/createEffect.d.ts.map +0 -1
- package/dist/createEffect.js +0 -29
- package/dist/createRouter.d.ts +0 -8
- package/dist/createRouter.d.ts.map +0 -1
- package/dist/createRouter.js +0 -27
- package/dist/createTask.d.ts +0 -31
- package/dist/createTask.d.ts.map +0 -1
- package/dist/createTask.js +0 -79
- package/dist/patchInferno.d.ts +0 -6
- package/dist/patchInferno.d.ts.map +0 -1
- package/dist/patchInferno.js +0 -53
- package/dist/scheduler.d.ts +0 -4
- package/dist/scheduler.d.ts.map +0 -1
- package/dist/scheduler.js +0 -107
- package/dist/tests/batch.test.d.ts +0 -2
- package/dist/tests/batch.test.d.ts.map +0 -1
- package/dist/tests/batch.test.js +0 -244
- package/dist/tests/createComputed.test.d.ts +0 -2
- package/dist/tests/createComputed.test.d.ts.map +0 -1
- package/dist/tests/createComputed.test.js +0 -257
- package/dist/tests/createContext.test.d.ts +0 -2
- package/dist/tests/createContext.test.d.ts.map +0 -1
- package/dist/tests/createContext.test.js +0 -136
- package/dist/tests/createEffect.test.d.ts +0 -2
- package/dist/tests/createEffect.test.d.ts.map +0 -1
- package/dist/tests/createEffect.test.js +0 -467
- package/dist/tests/createState.test.d.ts.map +0 -1
- package/dist/tests/createState.test.js +0 -144
- package/dist/tests/createTask.test.d.ts +0 -2
- package/dist/tests/createTask.test.d.ts.map +0 -1
- package/dist/tests/createTask.test.js +0 -322
- package/dist/tests/createView.test.d.ts.map +0 -1
- package/dist/tests/error.test.d.ts +0 -2
- package/dist/tests/error.test.d.ts.map +0 -1
- package/dist/tests/error.test.js +0 -168
- package/dist/tests/observation.test.d.ts.map +0 -1
- package/dist/tests/observation.test.js +0 -341
- package/dist/useComputed.d.ts +0 -5
- package/dist/useComputed.d.ts.map +0 -1
- package/dist/useComputed.js +0 -69
- package/dist/useQuery.d.ts +0 -25
- package/dist/useQuery.d.ts.map +0 -1
- package/dist/useQuery.js +0 -25
- package/dist/useSuspendAsync.d.ts +0 -18
- package/dist/useSuspendAsync.d.ts.map +0 -1
- package/dist/useSuspendAsync.js +0 -37
- package/dist/useTask.d.ts +0 -25
- package/dist/useTask.d.ts.map +0 -1
- package/dist/useTask.js +0 -70
- /package/dist/{tests/createState.test.d.ts → createState.test.d.ts} +0 -0
- /package/dist/{tests/createView.test.d.ts → createView.test.d.ts} +0 -0
- /package/dist/{tests/observation.test.d.ts → observation.test.d.ts} +0 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
type AsyncState<T> = {
|
|
2
|
+
isPending: true;
|
|
3
|
+
value: null;
|
|
4
|
+
error: null;
|
|
5
|
+
} | {
|
|
6
|
+
isPending: false;
|
|
7
|
+
value: T;
|
|
8
|
+
error: null;
|
|
9
|
+
} | {
|
|
10
|
+
isPending: false;
|
|
11
|
+
value: null;
|
|
12
|
+
error: string;
|
|
13
|
+
};
|
|
14
|
+
export declare function createAsyncState<T>(promise: Promise<T>): AsyncState<T>;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=asyncState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asyncState.d.ts","sourceRoot":"","sources":["../src/asyncState.ts"],"names":[],"mappings":"AAEA,KAAK,UAAU,CAAC,CAAC,IACb;IACE,SAAS,EAAE,IAAI,CAAC;IAChB,KAAK,EAAE,IAAI,CAAC;IACZ,KAAK,EAAE,IAAI,CAAC;CACb,GACD;IACE,SAAS,EAAE,KAAK,CAAC;IACjB,KAAK,EAAE,CAAC,CAAC;IACT,KAAK,EAAE,IAAI,CAAC;CACb,GACD;IACE,SAAS,EAAE,KAAK,CAAC;IACjB,KAAK,EAAE,IAAI,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEN,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,iBAwBtD"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createState } from "./createState";
|
|
2
|
+
export function createAsyncState(promise) {
|
|
3
|
+
const state = createState({
|
|
4
|
+
isPending: true,
|
|
5
|
+
error: null,
|
|
6
|
+
value: null,
|
|
7
|
+
});
|
|
8
|
+
promise
|
|
9
|
+
.then((value) => {
|
|
10
|
+
Object.assign(state, {
|
|
11
|
+
value,
|
|
12
|
+
error: null,
|
|
13
|
+
isPending: false,
|
|
14
|
+
});
|
|
15
|
+
})
|
|
16
|
+
.catch((error) => {
|
|
17
|
+
Object.assign(state, {
|
|
18
|
+
value: null,
|
|
19
|
+
error: String(error),
|
|
20
|
+
isPending: false,
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
return state;
|
|
24
|
+
}
|
package/dist/compiler.d.ts
CHANGED
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
export { createVNode, createFragment, createTextVNode, normalizeProps, Component, } from "inferno";
|
|
2
|
-
import { VNode } from "inferno";
|
|
3
|
-
export declare function createComponentVNode(_: any, component: any, props: any | undefined, key: any, ref: any): VNode;
|
|
1
|
+
export { createVNode, createComponentVNode, createFragment, createTextVNode, normalizeProps, Component, } from "inferno";
|
|
4
2
|
//# sourceMappingURL=compiler.d.ts.map
|
package/dist/compiler.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../src/compiler.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,cAAc,EACd,eAAe,EACf,cAAc,EACd,SAAS,GACV,MAAM,SAAS,CAAC
|
|
1
|
+
{"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../src/compiler.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,cAAc,EACd,eAAe,EACf,cAAc,EACd,SAAS,GACV,MAAM,SAAS,CAAC"}
|
package/dist/compiler.js
CHANGED
|
@@ -1,7 +1 @@
|
|
|
1
|
-
export { createVNode, createFragment, createTextVNode, normalizeProps, Component, } from "inferno";
|
|
2
|
-
import { createComponentVNode as infernoCreateComponentVnode, } from "inferno";
|
|
3
|
-
import { RaskComponent } from "./component";
|
|
4
|
-
export function createComponentVNode(_, component, props = {}, key, ref) {
|
|
5
|
-
props.__component = component;
|
|
6
|
-
return infernoCreateComponentVnode(4 /* VNodeFlags.ComponentClass */, RaskComponent, props, key, ref);
|
|
7
|
-
}
|
|
1
|
+
export { createVNode, createComponentVNode, createFragment, createTextVNode, normalizeProps, Component, } from "inferno";
|
package/dist/component.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAsB,QAAQ,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAMrE,wBAAgB,mBAAmB,mCAElC;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,IAAI,QAM5C;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,IAAI,QAMxC;AAED,MAAM,MAAM,8BAA8B,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,IAC3D,CAAC,MAAM,KAAK,CAAC,GACb,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,KAAK,CAAC,CAAC;AAE1B,MAAM,MAAM,6BAA6B,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,IAC1D,CAAC,MAAM,MAAM,KAAK,CAAC,GACnB,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,KAAK,CAAC,CAAC;AAEhC,qBAAa,aAAa,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,CAAE,SAAQ,SAAS,CAAC,CAAC,CAAC;IAC3D,QAAQ,EAAE,8BAA8B,CAAC,CAAC,CAAC,CAAC;IACpD,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM;IAC1C,OAAO,CAAC,aAAa,CAAc;IAwBnC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAS;IAE9B,QAAQ,WAOL;IAEH,WAAW,UAAS;IACpB,OAAO,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC,CAAM;IAC3D,QAAQ,gBAAa;IACrB,eAAe;IAcf,QAAQ,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAM;IACjC,UAAU,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAM;IAEnC,iBAAiB,IAAI,IAAI;IAGzB,oBAAoB,IAAI,IAAI;IAI5B,yBAAyB,CACvB,SAAS,EAAE,QAAQ,CAAC;QAAE,QAAQ,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,CAAC,CAAC,GAClD,IAAI;IAcP,qBAAqB,IAAI,OAAO;IAMhC,MAAM;CA4CP"}
|
package/dist/component.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Component
|
|
1
|
+
import { Component } from "inferno";
|
|
2
2
|
import { getCurrentObserver, Observer, Signal } from "./observation";
|
|
3
3
|
import { syncBatch } from "./batch";
|
|
4
4
|
import { CatchErrorContext } from "./useCatchError";
|
|
@@ -98,33 +98,26 @@ export class RaskComponent extends Component {
|
|
|
98
98
|
render() {
|
|
99
99
|
currentComponent = this;
|
|
100
100
|
const stopObserving = this.observer.observe();
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
try {
|
|
102
|
+
if (!this.renderFn) {
|
|
103
|
+
this.reactiveProps = createReactiveProps(this);
|
|
104
104
|
const component = this.props.__component;
|
|
105
105
|
const renderFn = component(this.reactiveProps);
|
|
106
106
|
if (typeof renderFn === "function") {
|
|
107
|
+
// Since we ran a setup function we need to clear any signals accessed
|
|
108
|
+
this.observer.clearSignals();
|
|
107
109
|
this.renderFn = renderFn;
|
|
108
110
|
}
|
|
109
111
|
else {
|
|
110
112
|
this.renderFn = component;
|
|
111
|
-
|
|
112
|
-
this.observer.clearSignals();
|
|
113
|
+
return renderFn;
|
|
113
114
|
}
|
|
114
115
|
}
|
|
115
|
-
|
|
116
|
-
if (typeof this.context.notifyError !== "function") {
|
|
117
|
-
throw error;
|
|
118
|
-
}
|
|
119
|
-
this.context.notifyError(error);
|
|
120
|
-
return null;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
let result = null;
|
|
124
|
-
try {
|
|
116
|
+
let result = null;
|
|
125
117
|
this.isRendering = true;
|
|
126
118
|
result = this.renderFn(this.reactiveProps);
|
|
127
119
|
this.isRendering = false;
|
|
120
|
+
return result;
|
|
128
121
|
}
|
|
129
122
|
catch (error) {
|
|
130
123
|
const notifyError = CatchErrorContext.use();
|
|
@@ -132,12 +125,12 @@ export class RaskComponent extends Component {
|
|
|
132
125
|
throw error;
|
|
133
126
|
}
|
|
134
127
|
notifyError(error);
|
|
128
|
+
return null;
|
|
135
129
|
}
|
|
136
130
|
finally {
|
|
137
131
|
stopObserving();
|
|
138
132
|
currentComponent = undefined;
|
|
139
133
|
}
|
|
140
|
-
return result;
|
|
141
134
|
}
|
|
142
135
|
}
|
|
143
136
|
function createReactiveProps(comp) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAEA,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM;eAE/B,CAAC;WAaL,CAAC;EAmBX"}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { getCurrentComponent } from "./component";
|
|
2
|
+
export function createContext() {
|
|
3
|
+
const context = {
|
|
4
|
+
set(value) {
|
|
5
|
+
const currentComponent = getCurrentComponent();
|
|
6
|
+
if (!currentComponent) {
|
|
7
|
+
throw new Error("You can not set context out component setup");
|
|
8
|
+
}
|
|
9
|
+
if (!currentComponent.contexts) {
|
|
10
|
+
currentComponent.contexts = new Map();
|
|
11
|
+
}
|
|
12
|
+
currentComponent.contexts.set(context, value);
|
|
13
|
+
},
|
|
14
|
+
get() {
|
|
15
|
+
let currentComponent = getCurrentComponent();
|
|
16
|
+
if (!currentComponent) {
|
|
17
|
+
throw new Error("You can not set context out component setup");
|
|
18
|
+
}
|
|
19
|
+
while (currentComponent) {
|
|
20
|
+
if (currentComponent.contexts?.has(context)) {
|
|
21
|
+
return currentComponent.contexts.get(context);
|
|
22
|
+
}
|
|
23
|
+
currentComponent = currentComponent.parent;
|
|
24
|
+
}
|
|
25
|
+
throw new Error("Could not find context in parent components");
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
return context;
|
|
29
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createAsync.test.d.ts","sourceRoot":"","sources":["../src/createAsync.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { createAsync } from './createAsync';
|
|
3
|
+
describe('createAsync', () => {
|
|
4
|
+
it('should start in pending state', () => {
|
|
5
|
+
const promise = new Promise(() => { });
|
|
6
|
+
const async = createAsync(promise);
|
|
7
|
+
expect(async.isPending).toBe(true);
|
|
8
|
+
expect(async.value).toBeNull();
|
|
9
|
+
expect(async.error).toBeNull();
|
|
10
|
+
});
|
|
11
|
+
it('should resolve to value state on success', async () => {
|
|
12
|
+
const promise = Promise.resolve('success');
|
|
13
|
+
const async = createAsync(promise);
|
|
14
|
+
expect(async.isPending).toBe(true);
|
|
15
|
+
await promise;
|
|
16
|
+
// Wait for state update
|
|
17
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
18
|
+
expect(async.isPending).toBe(false);
|
|
19
|
+
expect(async.value).toBe('success');
|
|
20
|
+
expect(async.error).toBeNull();
|
|
21
|
+
});
|
|
22
|
+
it('should resolve to error state on rejection', async () => {
|
|
23
|
+
const promise = Promise.reject(new Error('failed'));
|
|
24
|
+
const async = createAsync(promise);
|
|
25
|
+
expect(async.isPending).toBe(true);
|
|
26
|
+
try {
|
|
27
|
+
await promise;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// Ignore
|
|
31
|
+
}
|
|
32
|
+
// Wait for state update
|
|
33
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
34
|
+
expect(async.isPending).toBe(false);
|
|
35
|
+
expect(async.value).toBeNull();
|
|
36
|
+
expect(async.error).toContain('failed');
|
|
37
|
+
});
|
|
38
|
+
it('should handle numeric values', async () => {
|
|
39
|
+
const promise = Promise.resolve(42);
|
|
40
|
+
const async = createAsync(promise);
|
|
41
|
+
await promise;
|
|
42
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
43
|
+
expect(async.value).toBe(42);
|
|
44
|
+
});
|
|
45
|
+
it('should handle object values', async () => {
|
|
46
|
+
const data = { id: 1, name: 'Test' };
|
|
47
|
+
const promise = Promise.resolve(data);
|
|
48
|
+
const async = createAsync(promise);
|
|
49
|
+
await promise;
|
|
50
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
51
|
+
expect(async.value).toEqual(data);
|
|
52
|
+
});
|
|
53
|
+
it('should handle array values', async () => {
|
|
54
|
+
const data = [1, 2, 3, 4, 5];
|
|
55
|
+
const promise = Promise.resolve(data);
|
|
56
|
+
const async = createAsync(promise);
|
|
57
|
+
await promise;
|
|
58
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
59
|
+
expect(async.value).toEqual(data);
|
|
60
|
+
});
|
|
61
|
+
it('should convert error to string', async () => {
|
|
62
|
+
const promise = Promise.reject('string error');
|
|
63
|
+
const async = createAsync(promise);
|
|
64
|
+
try {
|
|
65
|
+
await promise;
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// Ignore
|
|
69
|
+
}
|
|
70
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
71
|
+
expect(typeof async.error).toBe('string');
|
|
72
|
+
expect(async.error).toBe('string error');
|
|
73
|
+
});
|
|
74
|
+
it('should handle error objects', async () => {
|
|
75
|
+
const error = new Error('Something went wrong');
|
|
76
|
+
const promise = Promise.reject(error);
|
|
77
|
+
const async = createAsync(promise);
|
|
78
|
+
try {
|
|
79
|
+
await promise;
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
// Ignore
|
|
83
|
+
}
|
|
84
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
85
|
+
expect(async.error).toContain('Something went wrong');
|
|
86
|
+
});
|
|
87
|
+
it('should create reactive state', async () => {
|
|
88
|
+
const promise = new Promise((resolve) => {
|
|
89
|
+
setTimeout(() => resolve('delayed'), 10);
|
|
90
|
+
});
|
|
91
|
+
const async = createAsync(promise);
|
|
92
|
+
expect(async.isPending).toBe(true);
|
|
93
|
+
await promise;
|
|
94
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
95
|
+
expect(async.isPending).toBe(false);
|
|
96
|
+
expect(async.value).toBe('delayed');
|
|
97
|
+
});
|
|
98
|
+
it('should handle immediate resolution', async () => {
|
|
99
|
+
const async = createAsync(Promise.resolve('immediate'));
|
|
100
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
101
|
+
expect(async.isPending).toBe(false);
|
|
102
|
+
expect(async.value).toBe('immediate');
|
|
103
|
+
});
|
|
104
|
+
it('should handle immediate rejection', async () => {
|
|
105
|
+
const async = createAsync(Promise.reject('immediate error'));
|
|
106
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
107
|
+
expect(async.isPending).toBe(false);
|
|
108
|
+
expect(async.error).toBe('immediate error');
|
|
109
|
+
});
|
|
110
|
+
});
|
package/dist/createContext.d.ts
CHANGED
|
@@ -35,7 +35,7 @@ export declare function createContext<T, P extends any[]>(hook: (...params: P) =
|
|
|
35
35
|
* @returns The context value provided by the nearest parent
|
|
36
36
|
* @throws Error if called outside component setup, if no parent context exists, or if the specific context was not provided
|
|
37
37
|
*/
|
|
38
|
-
use():
|
|
38
|
+
use(): T;
|
|
39
39
|
/**
|
|
40
40
|
* Injects a context value by calling the hook function and making it available to all child components.
|
|
41
41
|
* Must be called during component setup.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createContext.d.ts","sourceRoot":"","sources":["../src/createContext.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,SAAS,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC;IAEvE;;;;;;OAMG
|
|
1
|
+
{"version":3,"file":"createContext.d.ts","sourceRoot":"","sources":["../src/createContext.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,SAAS,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC;IAEvE;;;;;;OAMG;WACI,CAAC;IAqBR;;;;;;;OAOG;sBACe,CAAC,GAAG,CAAC;EAc1B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createMutation.test.d.ts","sourceRoot":"","sources":["../src/createMutation.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { createMutation } from './createMutation';
|
|
3
|
+
describe('createMutation', () => {
|
|
4
|
+
it('should start in idle state', () => {
|
|
5
|
+
const mutator = vi.fn(() => Promise.resolve(null));
|
|
6
|
+
const mutation = createMutation(mutator);
|
|
7
|
+
expect(mutation.isPending).toBe(false);
|
|
8
|
+
expect(mutation.params).toBeNull();
|
|
9
|
+
expect(mutation.error).toBeNull();
|
|
10
|
+
expect(mutator).not.toHaveBeenCalled();
|
|
11
|
+
});
|
|
12
|
+
it('should execute mutator when mutate is called', async () => {
|
|
13
|
+
const mutator = vi.fn((params) => Promise.resolve(params));
|
|
14
|
+
const mutation = createMutation(mutator);
|
|
15
|
+
mutation.mutate('test');
|
|
16
|
+
expect(mutation.isPending).toBe(true);
|
|
17
|
+
expect(mutation.params).toBe('test');
|
|
18
|
+
expect(mutator).toHaveBeenCalledWith('test');
|
|
19
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
20
|
+
expect(mutation.isPending).toBe(false);
|
|
21
|
+
expect(mutation.params).toBeNull();
|
|
22
|
+
});
|
|
23
|
+
it('should handle successful mutations', async () => {
|
|
24
|
+
const mutator = (params) => Promise.resolve(params);
|
|
25
|
+
const mutation = createMutation(mutator);
|
|
26
|
+
mutation.mutate({ id: 1 });
|
|
27
|
+
expect(mutation.isPending).toBe(true);
|
|
28
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
29
|
+
expect(mutation.isPending).toBe(false);
|
|
30
|
+
expect(mutation.error).toBeNull();
|
|
31
|
+
expect(mutation.params).toBeNull();
|
|
32
|
+
});
|
|
33
|
+
it('should handle mutation errors', async () => {
|
|
34
|
+
const mutator = (params) => Promise.reject(new Error('Mutation failed'));
|
|
35
|
+
const mutation = createMutation(mutator);
|
|
36
|
+
mutation.mutate('test');
|
|
37
|
+
expect(mutation.isPending).toBe(true);
|
|
38
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
39
|
+
expect(mutation.isPending).toBe(false);
|
|
40
|
+
expect(mutation.error).toContain('Mutation failed');
|
|
41
|
+
expect(mutation.params).toBeNull();
|
|
42
|
+
});
|
|
43
|
+
it('should cancel previous mutation on new mutate call', async () => {
|
|
44
|
+
let resolveFirst;
|
|
45
|
+
let resolveSecond;
|
|
46
|
+
const firstPromise = new Promise((resolve) => {
|
|
47
|
+
resolveFirst = resolve;
|
|
48
|
+
});
|
|
49
|
+
const secondPromise = new Promise((resolve) => {
|
|
50
|
+
resolveSecond = resolve;
|
|
51
|
+
});
|
|
52
|
+
const mutator = vi
|
|
53
|
+
.fn()
|
|
54
|
+
.mockReturnValueOnce(firstPromise)
|
|
55
|
+
.mockReturnValueOnce(secondPromise);
|
|
56
|
+
const mutation = createMutation(mutator);
|
|
57
|
+
mutation.mutate('first');
|
|
58
|
+
expect(mutation.params).toBe('first');
|
|
59
|
+
// Trigger second mutation before first completes
|
|
60
|
+
mutation.mutate('second');
|
|
61
|
+
expect(mutation.params).toBe('second');
|
|
62
|
+
// Resolve first (should be ignored due to cancellation)
|
|
63
|
+
resolveFirst('first');
|
|
64
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
65
|
+
expect(mutation.isPending).toBe(true); // Still pending second
|
|
66
|
+
// Resolve second
|
|
67
|
+
resolveSecond('second');
|
|
68
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
69
|
+
expect(mutation.isPending).toBe(false);
|
|
70
|
+
expect(mutation.params).toBeNull();
|
|
71
|
+
});
|
|
72
|
+
it('should handle rapid successive mutations', async () => {
|
|
73
|
+
let counter = 0;
|
|
74
|
+
const mutator = vi.fn(() => Promise.resolve(++counter));
|
|
75
|
+
const mutation = createMutation(mutator);
|
|
76
|
+
// Rapid mutations
|
|
77
|
+
mutation.mutate('1');
|
|
78
|
+
mutation.mutate('2');
|
|
79
|
+
mutation.mutate('3');
|
|
80
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
81
|
+
// Only the last mutation should complete
|
|
82
|
+
expect(mutator).toHaveBeenCalledTimes(3);
|
|
83
|
+
expect(mutation.isPending).toBe(false);
|
|
84
|
+
expect(mutation.params).toBeNull();
|
|
85
|
+
});
|
|
86
|
+
it('should clear error on successful retry', async () => {
|
|
87
|
+
const mutator = vi
|
|
88
|
+
.fn()
|
|
89
|
+
.mockRejectedValueOnce(new Error('First error'))
|
|
90
|
+
.mockResolvedValueOnce('success');
|
|
91
|
+
const mutation = createMutation(mutator);
|
|
92
|
+
mutation.mutate('attempt1');
|
|
93
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
94
|
+
expect(mutation.error).toContain('First error');
|
|
95
|
+
mutation.mutate('attempt2');
|
|
96
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
97
|
+
expect(mutation.error).toBeNull();
|
|
98
|
+
expect(mutation.isPending).toBe(false);
|
|
99
|
+
});
|
|
100
|
+
it('should handle different parameter types', async () => {
|
|
101
|
+
const mutator = vi.fn((params) => Promise.resolve(params));
|
|
102
|
+
const mutation = createMutation(mutator);
|
|
103
|
+
// Object params
|
|
104
|
+
mutation.mutate({ id: 1, name: 'test' });
|
|
105
|
+
expect(mutation.params).toEqual({ id: 1, name: 'test' });
|
|
106
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
107
|
+
// Array params
|
|
108
|
+
const mutation2 = createMutation(mutator);
|
|
109
|
+
mutation2.mutate([1, 2, 3]);
|
|
110
|
+
expect(mutation2.params).toEqual([1, 2, 3]);
|
|
111
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
112
|
+
// String params
|
|
113
|
+
const mutation3 = createMutation(mutator);
|
|
114
|
+
mutation3.mutate('string');
|
|
115
|
+
expect(mutation3.params).toBe('string');
|
|
116
|
+
});
|
|
117
|
+
it('should convert errors to strings', async () => {
|
|
118
|
+
const mutator = (params) => Promise.reject('string error');
|
|
119
|
+
const mutation = createMutation(mutator);
|
|
120
|
+
mutation.mutate('test');
|
|
121
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
122
|
+
expect(typeof mutation.error).toBe('string');
|
|
123
|
+
expect(mutation.error).toBe('string error');
|
|
124
|
+
});
|
|
125
|
+
it('should handle AbortController cancellation correctly', async () => {
|
|
126
|
+
const abortedPromise = new Promise((_, reject) => {
|
|
127
|
+
const error = new Error('Aborted');
|
|
128
|
+
error.name = 'AbortError';
|
|
129
|
+
setTimeout(() => reject(error), 5);
|
|
130
|
+
});
|
|
131
|
+
const successPromise = Promise.resolve('success');
|
|
132
|
+
const mutator = vi
|
|
133
|
+
.fn()
|
|
134
|
+
.mockReturnValueOnce(abortedPromise)
|
|
135
|
+
.mockReturnValueOnce(successPromise);
|
|
136
|
+
const mutation = createMutation(mutator);
|
|
137
|
+
mutation.mutate('first');
|
|
138
|
+
// Immediately trigger second mutation to abort first
|
|
139
|
+
mutation.mutate('second');
|
|
140
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
141
|
+
expect(mutation.isPending).toBe(false);
|
|
142
|
+
expect(mutation.error).toBeNull();
|
|
143
|
+
});
|
|
144
|
+
it('should track params during pending state', () => {
|
|
145
|
+
const mutator = () => new Promise((resolve) => setTimeout(() => resolve(null), 100));
|
|
146
|
+
const mutation = createMutation(mutator);
|
|
147
|
+
const params = { id: 123, action: 'update' };
|
|
148
|
+
mutation.mutate(params);
|
|
149
|
+
expect(mutation.isPending).toBe(true);
|
|
150
|
+
expect(mutation.params).toEqual(params);
|
|
151
|
+
});
|
|
152
|
+
it('should expose reactive getters', async () => {
|
|
153
|
+
const mutator = () => Promise.resolve('data');
|
|
154
|
+
const mutation = createMutation(mutator);
|
|
155
|
+
// Access getters before mutation
|
|
156
|
+
expect(mutation.isPending).toBe(false);
|
|
157
|
+
expect(mutation.params).toBeNull();
|
|
158
|
+
expect(mutation.error).toBeNull();
|
|
159
|
+
mutation.mutate('test');
|
|
160
|
+
// Access getters during mutation
|
|
161
|
+
expect(mutation.isPending).toBe(true);
|
|
162
|
+
expect(mutation.params).toBe('test');
|
|
163
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
164
|
+
// Access getters after mutation
|
|
165
|
+
expect(mutation.isPending).toBe(false);
|
|
166
|
+
expect(mutation.params).toBeNull();
|
|
167
|
+
});
|
|
168
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createQuery.test.d.ts","sourceRoot":"","sources":["../src/createQuery.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { createQuery } from './createQuery';
|
|
3
|
+
describe('createQuery', () => {
|
|
4
|
+
it('should start in pending state and fetch immediately', async () => {
|
|
5
|
+
const fetcher = vi.fn(() => Promise.resolve('data'));
|
|
6
|
+
const query = createQuery(fetcher);
|
|
7
|
+
expect(query.isPending).toBe(true);
|
|
8
|
+
expect(query.data).toBeNull();
|
|
9
|
+
expect(query.error).toBeNull();
|
|
10
|
+
expect(fetcher).toHaveBeenCalledTimes(1);
|
|
11
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
12
|
+
expect(query.isPending).toBe(false);
|
|
13
|
+
expect(query.data).toBe('data');
|
|
14
|
+
});
|
|
15
|
+
it('should resolve to data state on success', async () => {
|
|
16
|
+
const fetcher = () => Promise.resolve({ id: 1, name: 'Test' });
|
|
17
|
+
const query = createQuery(fetcher);
|
|
18
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
19
|
+
expect(query.isPending).toBe(false);
|
|
20
|
+
expect(query.data).toEqual({ id: 1, name: 'Test' });
|
|
21
|
+
expect(query.error).toBeNull();
|
|
22
|
+
});
|
|
23
|
+
it('should resolve to error state on failure', async () => {
|
|
24
|
+
const fetcher = () => Promise.reject(new Error('Network error'));
|
|
25
|
+
const query = createQuery(fetcher);
|
|
26
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
27
|
+
expect(query.isPending).toBe(false);
|
|
28
|
+
expect(query.data).toBeNull();
|
|
29
|
+
expect(query.error).toContain('Network error');
|
|
30
|
+
});
|
|
31
|
+
it('should allow manual refetch', async () => {
|
|
32
|
+
const fetcher = vi.fn(() => Promise.resolve('data'));
|
|
33
|
+
const query = createQuery(fetcher);
|
|
34
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
35
|
+
expect(fetcher).toHaveBeenCalledTimes(1);
|
|
36
|
+
query.fetch();
|
|
37
|
+
expect(query.isPending).toBe(true);
|
|
38
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
39
|
+
expect(fetcher).toHaveBeenCalledTimes(2);
|
|
40
|
+
expect(query.isPending).toBe(false);
|
|
41
|
+
});
|
|
42
|
+
it('should retain old data during refetch by default', async () => {
|
|
43
|
+
const fetcher = vi
|
|
44
|
+
.fn()
|
|
45
|
+
.mockResolvedValueOnce('data1')
|
|
46
|
+
.mockResolvedValueOnce('data2');
|
|
47
|
+
const query = createQuery(fetcher);
|
|
48
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
49
|
+
expect(query.data).toBe('data1');
|
|
50
|
+
query.fetch();
|
|
51
|
+
expect(query.isPending).toBe(true);
|
|
52
|
+
expect(query.data).toBe('data1'); // Old data retained
|
|
53
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
54
|
+
expect(query.data).toBe('data2');
|
|
55
|
+
});
|
|
56
|
+
it('should clear old data when force refetch is used', async () => {
|
|
57
|
+
const fetcher = vi
|
|
58
|
+
.fn()
|
|
59
|
+
.mockResolvedValueOnce('data1')
|
|
60
|
+
.mockResolvedValueOnce('data2');
|
|
61
|
+
const query = createQuery(fetcher);
|
|
62
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
63
|
+
expect(query.data).toBe('data1');
|
|
64
|
+
query.fetch(true); // Force refresh
|
|
65
|
+
expect(query.isPending).toBe(true);
|
|
66
|
+
expect(query.data).toBeNull(); // Old data cleared
|
|
67
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
68
|
+
expect(query.data).toBe('data2');
|
|
69
|
+
});
|
|
70
|
+
it('should cancel previous request on new fetch', async () => {
|
|
71
|
+
let resolveFirst;
|
|
72
|
+
let resolveSecond;
|
|
73
|
+
const firstPromise = new Promise((resolve) => {
|
|
74
|
+
resolveFirst = resolve;
|
|
75
|
+
});
|
|
76
|
+
const secondPromise = new Promise((resolve) => {
|
|
77
|
+
resolveSecond = resolve;
|
|
78
|
+
});
|
|
79
|
+
const fetcher = vi
|
|
80
|
+
.fn()
|
|
81
|
+
.mockReturnValueOnce(firstPromise)
|
|
82
|
+
.mockReturnValueOnce(secondPromise);
|
|
83
|
+
const query = createQuery(fetcher);
|
|
84
|
+
expect(query.isPending).toBe(true);
|
|
85
|
+
// Trigger second fetch before first completes
|
|
86
|
+
query.fetch();
|
|
87
|
+
// Resolve first (should be ignored due to cancellation)
|
|
88
|
+
resolveFirst('first');
|
|
89
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
90
|
+
expect(query.data).toBeNull(); // First result ignored
|
|
91
|
+
// Resolve second
|
|
92
|
+
resolveSecond('second');
|
|
93
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
94
|
+
expect(query.data).toBe('second');
|
|
95
|
+
});
|
|
96
|
+
it('should handle rapid successive fetches', async () => {
|
|
97
|
+
let counter = 0;
|
|
98
|
+
const fetcher = vi.fn(() => Promise.resolve(`data-${++counter}`));
|
|
99
|
+
const query = createQuery(fetcher);
|
|
100
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
101
|
+
// Rapid fetches
|
|
102
|
+
query.fetch();
|
|
103
|
+
query.fetch();
|
|
104
|
+
query.fetch();
|
|
105
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
106
|
+
// Only the last fetch should matter
|
|
107
|
+
expect(fetcher).toHaveBeenCalledTimes(4); // Initial + 3 fetches
|
|
108
|
+
expect(query.data).toBe('data-4');
|
|
109
|
+
});
|
|
110
|
+
it('should cancel on error and allow refetch', async () => {
|
|
111
|
+
const fetcher = vi
|
|
112
|
+
.fn()
|
|
113
|
+
.mockRejectedValueOnce(new Error('First error'))
|
|
114
|
+
.mockResolvedValueOnce('success');
|
|
115
|
+
const query = createQuery(fetcher);
|
|
116
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
117
|
+
expect(query.error).toContain('First error');
|
|
118
|
+
expect(query.data).toBeNull();
|
|
119
|
+
query.fetch();
|
|
120
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
121
|
+
expect(query.error).toBeNull();
|
|
122
|
+
expect(query.data).toBe('success');
|
|
123
|
+
});
|
|
124
|
+
it('should handle AbortController cancellation correctly', async () => {
|
|
125
|
+
const abortedPromise = new Promise((_, reject) => {
|
|
126
|
+
const error = new Error('Aborted');
|
|
127
|
+
error.name = 'AbortError';
|
|
128
|
+
setTimeout(() => reject(error), 5);
|
|
129
|
+
});
|
|
130
|
+
const successPromise = Promise.resolve('success');
|
|
131
|
+
const fetcher = vi
|
|
132
|
+
.fn()
|
|
133
|
+
.mockReturnValueOnce(abortedPromise)
|
|
134
|
+
.mockReturnValueOnce(successPromise);
|
|
135
|
+
const query = createQuery(fetcher);
|
|
136
|
+
// Immediately trigger second fetch to abort first
|
|
137
|
+
query.fetch();
|
|
138
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
139
|
+
expect(query.data).toBe('success');
|
|
140
|
+
expect(query.error).toBeNull();
|
|
141
|
+
});
|
|
142
|
+
it('should expose reactive getters', async () => {
|
|
143
|
+
const fetcher = () => Promise.resolve('data');
|
|
144
|
+
const query = createQuery(fetcher);
|
|
145
|
+
// Access getters
|
|
146
|
+
const pending1 = query.isPending;
|
|
147
|
+
const data1 = query.data;
|
|
148
|
+
const error1 = query.error;
|
|
149
|
+
expect(pending1).toBe(true);
|
|
150
|
+
expect(data1).toBeNull();
|
|
151
|
+
expect(error1).toBeNull();
|
|
152
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
153
|
+
expect(query.isPending).toBe(false);
|
|
154
|
+
expect(query.data).toBe('data');
|
|
155
|
+
});
|
|
156
|
+
});
|